Enforce port QoS policies for all ports.

This patch enforces the port QoS policies applied on all ports.
Besides that, a port QoS policy must prevail over a network QoS
policy, if both are present on the same port.

Change-Id: Icccb835e48bb70ac1a08e0887ecb34160bec8cfa
Closes-Bug: #1659312
Closes-Bug: #1665282
This commit is contained in:
Rodolfo Alonso Hernandez 2017-01-25 15:36:54 +00:00
parent d7020ce931
commit 4ffeef246f
3 changed files with 30 additions and 8 deletions

View File

@ -80,12 +80,17 @@ class QosRule(base.NeutronDbObject):
this method, or we could make it abstract to allow different this method, or we could make it abstract to allow different
rule behaviour. rule behaviour.
""" """
is_network_rule = self.qos_policy_id != port[qos_consts.QOS_POLICY_ID] is_port_policy = self.qos_policy_id == port[qos_consts.QOS_POLICY_ID]
is_network_policy_only = port[qos_consts.QOS_POLICY_ID] is None
is_network_device_port = any(port['device_owner'].startswith(prefix) is_network_device_port = any(port['device_owner'].startswith(prefix)
for prefix for prefix
in constants.DEVICE_OWNER_PREFIXES) in constants.DEVICE_OWNER_PREFIXES)
# NOTE(ralonsoh): return True if:
return not (is_network_rule and is_network_device_port) # - Is a port QoS policy (not a network QoS policy)
# - Is not a network device (e.g. router) and is a network QoS
# policy and there is no port QoS policy
return (is_port_policy or
(not is_network_device_port and is_network_policy_only))
@obj_base.VersionedObjectRegistry.register @obj_base.VersionedObjectRegistry.register

View File

@ -42,6 +42,13 @@ class QosRuleObjectTestCase(neutron_test_base.BaseTestCase):
device_owner=constants.DEVICE_OWNER_ROUTER_INTF, device_owner=constants.DEVICE_OWNER_ROUTER_INTF,
expected_result=False) expected_result=False)
def test_should_apply_to_port_with_network_port_and_only_net_policy(self):
self._test_should_apply_to_port(
rule_policy_id=POLICY_ID_B,
port_policy_id=None,
device_owner=constants.DEVICE_OWNER_ROUTER_INTF,
expected_result=False)
def test_should_apply_to_port_with_network_port_and_port_policy(self): def test_should_apply_to_port_with_network_port_and_port_policy(self):
self._test_should_apply_to_port( self._test_should_apply_to_port(
rule_policy_id=POLICY_ID_A, rule_policy_id=POLICY_ID_A,
@ -50,10 +57,19 @@ class QosRuleObjectTestCase(neutron_test_base.BaseTestCase):
expected_result=True) expected_result=True)
def test_should_apply_to_port_with_compute_port_and_net_policy(self): def test_should_apply_to_port_with_compute_port_and_net_policy(self):
# NOTE(ralonsoh): in this case the port has a port QoS policy; the
# network QoS policy can't be applied.
self._test_should_apply_to_port( self._test_should_apply_to_port(
rule_policy_id=POLICY_ID_B, rule_policy_id=POLICY_ID_B,
port_policy_id=POLICY_ID_A, port_policy_id=POLICY_ID_A,
device_owner=DEVICE_OWNER_COMPUTE, device_owner=DEVICE_OWNER_COMPUTE,
expected_result=False)
def test_should_apply_to_port_with_compute_port_and_only_net_policy(self):
self._test_should_apply_to_port(
rule_policy_id=POLICY_ID_B,
port_policy_id=None,
device_owner=DEVICE_OWNER_COMPUTE,
expected_result=True) expected_result=True)
def test_should_apply_to_port_with_compute_port_and_port_policy(self): def test_should_apply_to_port_with_compute_port_and_port_policy(self):

View File

@ -54,6 +54,7 @@ class QosSRIOVAgentDriverTestCase(base.BaseTestCase):
self.qos_policy_min_tx_rate = self._create_qos_policy_obj( self.qos_policy_min_tx_rate = self._create_qos_policy_obj(
[self.rule_min_tx_rate]) [self.rule_min_tx_rate])
self.port = self._create_fake_port(self.qos_policy.id) self.port = self._create_fake_port(self.qos_policy.id)
self.port_min = self._create_fake_port(self.qos_policy_min_tx_rate.id)
def _create_bw_limit_rule_obj(self): def _create_bw_limit_rule_obj(self):
rule_obj = rule.QosBandwidthLimitRule() rule_obj = rule.QosBandwidthLimitRule()
@ -124,21 +125,21 @@ class QosSRIOVAgentDriverTestCase(base.BaseTestCase):
self.assertFalse(self.max_rate_mock.called) self.assertFalse(self.max_rate_mock.called)
def test_create_minimum_bandwidth(self): def test_create_minimum_bandwidth(self):
self.qos_driver.create(self.port, self.qos_policy_min_tx_rate) self.qos_driver.create(self.port_min, self.qos_policy_min_tx_rate)
self.min_tx_rate_mock.assert_called_once_with( self.min_tx_rate_mock.assert_called_once_with(
self.ASSIGNED_MAC, self.PCI_SLOT, self.rule_min_tx_rate.min_kbps) self.ASSIGNED_MAC, self.PCI_SLOT, self.rule_min_tx_rate.min_kbps)
def test_update_minimum_bandwidth(self): def test_update_minimum_bandwidth(self):
self.qos_driver.update(self.port, self.qos_policy_min_tx_rate) self.qos_driver.update(self.port_min, self.qos_policy_min_tx_rate)
self.min_tx_rate_mock.assert_called_once_with( self.min_tx_rate_mock.assert_called_once_with(
self.ASSIGNED_MAC, self.PCI_SLOT, self.rule_min_tx_rate.min_kbps) self.ASSIGNED_MAC, self.PCI_SLOT, self.rule_min_tx_rate.min_kbps)
def test_delete_minimum_bandwidth_on_assigned_vf(self): def test_delete_minimum_bandwidth_on_assigned_vf(self):
self.qos_driver.delete(self.port, self.qos_policy_min_tx_rate) self.qos_driver.delete(self.port_min, self.qos_policy_min_tx_rate)
self.min_tx_rate_mock.assert_called_once_with( self.min_tx_rate_mock.assert_called_once_with(
self.ASSIGNED_MAC, self.PCI_SLOT, 0) self.ASSIGNED_MAC, self.PCI_SLOT, 0)
def test_delete_minimum_bandwidth_on_released_vf(self): def test_delete_minimum_bandwidth_on_released_vf(self):
del self.port['device_owner'] del self.port_min['device_owner']
self.qos_driver.delete(self.port, self.qos_policy_min_tx_rate) self.qos_driver.delete(self.port_min, self.qos_policy_min_tx_rate)
self.clear_min_tx_rate_mock.assert_called_once_with(self.PCI_SLOT) self.clear_min_tx_rate_mock.assert_called_once_with(self.PCI_SLOT)