From: Moshe Levi Date: Sun, 2 Aug 2015 09:58:54 +0000 (+0300) Subject: SR-IOV: Update eswitch manager to support rate X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=81009f6b942e468214db9550d58cda11ecf06545;p=openstack-build%2Fneutron-build.git SR-IOV: Update eswitch manager to support rate This patch update the eswitch manager to support max rate on VF, moreover it updates the eswitch manager to be singleton so it can be called from the SR-IOV qos driver. Partially-Implements: blueprint ml2-qos Change-Id: I3e0d0a3fe2effade4e7bcd94018313ab2beb8f28 --- diff --git a/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py b/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py index 866476977..ada37b2de 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py @@ -144,11 +144,7 @@ class EmbSwitch(object): @param pci_slot: Virtual Function address """ - vf_index = self.pci_slot_map.get(pci_slot) - if vf_index is None: - LOG.warning(_LW("Cannot find vf index for pci slot %s"), - pci_slot) - raise exc.InvalidPciSlotError(pci_slot=pci_slot) + vf_index = self._get_vf_index(pci_slot) return self.pci_dev_wrapper.get_vf_state(vf_index) def set_device_state(self, pci_slot, state): @@ -157,12 +153,25 @@ class EmbSwitch(object): @param pci_slot: Virtual Function address @param state: link state """ + vf_index = self._get_vf_index(pci_slot) + return self.pci_dev_wrapper.set_vf_state(vf_index, state) + + def set_device_max_rate(self, pci_slot, max_kbps): + """Set device max rate. + + @param pci_slot: Virtual Function address + @param max_kbps: device max rate in kbps + """ + vf_index = self._get_vf_index(pci_slot) + return self.pci_dev_wrapper.set_vf_max_rate(vf_index, max_kbps) + + def _get_vf_index(self, pci_slot): vf_index = self.pci_slot_map.get(pci_slot) if vf_index is None: LOG.warning(_LW("Cannot find vf index for pci slot %s"), pci_slot) raise exc.InvalidPciSlotError(pci_slot=pci_slot) - return self.pci_dev_wrapper.set_vf_state(vf_index, state) + return vf_index def set_device_spoofcheck(self, pci_slot, enabled): """Set device spoofchecking @@ -194,7 +203,13 @@ class EmbSwitch(object): class ESwitchManager(object): """Manages logical Embedded Switch entities for physical network.""" - def __init__(self, device_mappings, exclude_devices): + def __new__(cls): + # make it a singleton + if not hasattr(cls, '_instance'): + cls._instance = super(ESwitchManager, cls).__new__(cls) + return cls._instance + + def __init__(self): """Constructor. Create Embedded Switch logical entities for all given device mappings, @@ -203,8 +218,6 @@ class ESwitchManager(object): self.emb_switches_map = {} self.pci_slot_map = {} - self._discover_devices(device_mappings, exclude_devices) - def device_exists(self, device_mac, pci_slot): """Verify if device exists. @@ -250,6 +263,19 @@ class ESwitchManager(object): return embedded_switch.get_device_state(pci_slot) return False + def set_device_max_rate(self, device_mac, pci_slot, max_kbps): + """Set device max rate + + Sets the device max rate in kbps + @param device_mac: device mac + @param pci_slot: pci slot + @param max_kbps: device max rate in kbps + """ + embedded_switch = self._get_emb_eswitch(device_mac, pci_slot) + if embedded_switch: + embedded_switch.set_device_max_rate(pci_slot, + max_kbps) + def set_device_state(self, device_mac, pci_slot, admin_state_up): """Set device state @@ -276,7 +302,7 @@ class ESwitchManager(object): embedded_switch.set_device_spoofcheck(pci_slot, enabled) - def _discover_devices(self, device_mappings, exclude_devices): + def discover_devices(self, device_mappings, exclude_devices): """Discover which Virtual functions to manage. Discover devices, and create embedded switch object for network device diff --git a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py index e1dd7247b..7bf297955 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py @@ -130,7 +130,8 @@ class SriovNicSwitchAgent(object): LOG.exception(_LE("Failed reporting state!")) def setup_eswitch_mgr(self, device_mappings, exclude_devices={}): - self.eswitch_mgr = esm.ESwitchManager(device_mappings, exclude_devices) + self.eswitch_mgr = esm.ESwitchManager() + self.eswitch_mgr.discover_devices(device_mappings, exclude_devices) def scan_devices(self, registered_devices, updated_devices): curr_devices = self.eswitch_mgr.get_assigned_devices() diff --git a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py index a9a5b3a67..e131dc1eb 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py @@ -42,7 +42,8 @@ class TestCreateESwitchManager(base.BaseTestCase): return_value=True): with testtools.ExpectedException(exc.InvalidDeviceError): - esm.ESwitchManager(device_mappings, None) + esm.ESwitchManager().discover_devices( + device_mappings, None) def test_create_eswitch_mgr_ok(self): device_mappings = {'physnet1': 'p6p1'} @@ -53,7 +54,7 @@ class TestCreateESwitchManager(base.BaseTestCase): "eswitch_manager.PciOsWrapper.is_assigned_vf", return_value=True): - esm.ESwitchManager(device_mappings, None) + esm.ESwitchManager().discover_devices(device_mappings, None) class TestESwitchManagerApi(base.BaseTestCase): @@ -75,7 +76,8 @@ class TestESwitchManagerApi(base.BaseTestCase): mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." "eswitch_manager.PciOsWrapper.is_assigned_vf", return_value=True): - self.eswitch_mgr = esm.ESwitchManager(device_mappings, None) + self.eswitch_mgr = esm.ESwitchManager() + self.eswitch_mgr.discover_devices(device_mappings, None) def test_get_assigned_devices(self): with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." @@ -132,6 +134,19 @@ class TestESwitchManagerApi(base.BaseTestCase): self.eswitch_mgr.set_device_state(self.ASSIGNED_MAC, self.PCI_SLOT, True) + def test_set_device_max_rate(self): + with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." + "eswitch_manager.EmbSwitch.get_pci_device", + return_value=self.ASSIGNED_MAC) as get_pci_mock,\ + mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." + "eswitch_manager.EmbSwitch.set_device_max_rate")\ + as set_device_max_rate_mock: + self.eswitch_mgr.set_device_max_rate(self.ASSIGNED_MAC, + self.PCI_SLOT, 1000) + get_pci_mock.assert_called_once_with(self.PCI_SLOT) + set_device_max_rate_mock.assert_called_once_with( + self.PCI_SLOT, 1000) + def test_set_device_status_mismatch(self): with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." "eswitch_manager.EmbSwitch.get_pci_device", @@ -260,6 +275,18 @@ class TestEmbSwitch(base.BaseTestCase): self.emb_switch.set_device_spoofcheck, self.WRONG_PCI_SLOT, True) + def test_set_device_max_rate_ok(self): + with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib." + "PciDeviceIPWrapper.set_vf_max_rate"): + self.emb_switch.set_device_max_rate(self.PCI_SLOT, 1000) + + def test_set_device_max_rate_fail(self): + with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib." + "PciDeviceIPWrapper.set_vf_max_rate"): + self.assertRaises(exc.InvalidPciSlotError, + self.emb_switch.set_device_max_rate, + self.WRONG_PCI_SLOT, 1000) + def test_get_pci_device(self): with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib." "PciDeviceIPWrapper.get_assigned_macs",