]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
SR-IOV: Convert max rate from kbps to Mbps
authorMoshe Levi <moshele@mellanox.com>
Tue, 11 Aug 2015 04:08:11 +0000 (07:08 +0300)
committerIhar Hrachyshka <ihrachys@redhat.com>
Tue, 11 Aug 2015 12:58:13 +0000 (14:58 +0200)
ip link tool configures max rate in Mbps and
it the QoS model max rate is defined in kbps. This
patch convert the max rate from kbps to Mbps. Also
because zero disables the rate limit the min value
is 1Mbps and not 1kbps.

DocImpact
Partially-Implements: blueprint ml2-sriov-qos-with-bwlimiting
Change-Id: I91b08c5d8ccaa2867b6eafd0c86872f401dd04c8

neutron/common/utils.py
neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py
neutron/plugins/ml2/drivers/mech_sriov/agent/pci_lib.py
neutron/tests/unit/common/test_utils.py
neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py

index 579766fb4279bfd5afffab06cceb414633a2c479..6c9d9b17b7c2241dfbf6c04f9b4c3092ae118757 100644 (file)
@@ -19,6 +19,7 @@
 """Utilities and helper functions."""
 
 import datetime
+import decimal
 import errno
 import functools
 import hashlib
@@ -442,3 +443,10 @@ class DelayedStringRenderer(object):
 
 def camelize(s):
     return ''.join(s.replace('_', ' ').title().split())
+
+
+def round_val(val):
+    # we rely on decimal module since it behaves consistently across Python
+    # versions (2.x vs. 3.x)
+    return int(decimal.Decimal(val).quantize(decimal.Decimal('1'),
+                                             rounding=decimal.ROUND_HALF_UP))
index 0bfb0e0f8bbfba4c8e6bea1da11022169f179040..938db459005a07ce567efc2957f50d791f3cdf3e 100644 (file)
@@ -20,6 +20,7 @@ import re
 from oslo_log import log as logging
 import six
 
+from neutron.common import utils
 from neutron.i18n import _LE, _LW
 from neutron.plugins.ml2.drivers.mech_sriov.agent.common \
     import exceptions as exc
@@ -163,7 +164,30 @@ class EmbSwitch(object):
         @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)
+        #(Note): ip link set max rate in Mbps therefore
+        #we need to convert the max_kbps to Mbps.
+        #Zero means to disable the rate so the lowest rate
+        #available is 1Mbps. Floating numbers are not allowed
+        if max_kbps > 0 and max_kbps < 1000:
+            max_mbps = 1
+        else:
+            max_mbps = utils.round_val(max_kbps / 1000.0)
+
+        log_dict = {
+            'max_rate': max_mbps,
+            'max_kbps': max_kbps,
+            'vf_index': vf_index
+        }
+        if max_kbps % 1000 != 0:
+            LOG.debug("Maximum rate for SR-IOV ports is counted in Mbps; "
+                      "setting %(max_rate)s Mbps limit for port %(vf_index)s "
+                      "instead of %(max_kbps)s kbps",
+                      log_dict)
+        else:
+            LOG.debug("Setting %(max_rate)s Mbps limit for port %(vf_index)s",
+                      log_dict)
+
+        return self.pci_dev_wrapper.set_vf_max_rate(vf_index, max_mbps)
 
     def _get_vf_index(self, pci_slot):
         vf_index = self.pci_slot_map.get(pci_slot)
index a1e31cd66697118eb886e9ec9daa8c9bcdf18580..8f984e0aac4b6d8f08108c16d4decdfcded477d5 100644 (file)
@@ -126,7 +126,7 @@ class PciDeviceIPWrapper(ip_lib.IPWrapper):
         """sets vf max rate.
 
         @param vf_index: vf index
-        @param max_tx_rate: vf max tx rate
+        @param max_tx_rate: vf max tx rate in Mbps
         """
         try:
             self._as_root([], "link", ("set", self.dev_name, "vf",
index 20e764bfadd82d8f7bea7794e54b85fa3d9438e0..b604bbb27aebfe83b123a197a44c42487a642713 100644 (file)
@@ -690,3 +690,13 @@ class TestCamelize(base.BaseTestCase):
 
         for s, expected in data.items():
             self.assertEqual(expected, utils.camelize(s))
+
+
+class TestRoundVal(base.BaseTestCase):
+    def test_round_val_ok(self):
+        for expected, value in ((0, 0),
+                                (0, 0.1),
+                                (1, 0.5),
+                                (1, 1.49),
+                                (2, 1.5)):
+            self.assertEqual(expected, utils.round_val(value))
index e131dc1ebf2f7d62259e4491b9e55238e9ac7b30..2d30a05070516c3459142a28bfbcfc9f1caae9f1 100644 (file)
@@ -277,8 +277,39 @@ class TestEmbSwitch(base.BaseTestCase):
 
     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)
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 2000)
+            pci_lib_mock.assert_called_with(0, 2)
+
+    def test_set_device_max_rate_ok2(self):
+        with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 99)
+            pci_lib_mock.assert_called_with(0, 1)
+
+    def test_set_device_max_rate_rounded_ok(self):
+        with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 2001)
+            pci_lib_mock.assert_called_with(0, 2)
+
+    def test_set_device_max_rate_rounded_ok2(self):
+        with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 2499)
+            pci_lib_mock.assert_called_with(0, 2)
+
+    def test_set_device_max_rate_rounded_ok3(self):
+        with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 2500)
+            pci_lib_mock.assert_called_with(0, 3)
+
+    def test_set_device_max_rate_disable(self):
+        with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
+                        "PciDeviceIPWrapper.set_vf_max_rate") as pci_lib_mock:
+            self.emb_switch.set_device_max_rate(self.PCI_SLOT, 0)
+            pci_lib_mock.assert_called_with(0, 0)
 
     def test_set_device_max_rate_fail(self):
         with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."