Add "max-rate" value to minimum bandwidth rules

OVS translates the QoS and associated queue registers,
attached to a port, into "tc" linux-htb classfull traffic
shaper, applied on the port.

OVS creates a "tc" root class on the port device. On top of
this root class, the queues are represented as child "tc"
classes. In order to define a "min-rate" value ("tc rate"),
a "max-rate" value ("tc ceil") must be provided and higher than
"min-rate".

By default, OVS agent QoS minimum rules do not have a "max-rate"
defined. Before this patch, any minimum bandwidth rule was
limiting the maximum rate to 100Mbit/s, that is the default value
set in "tc ceil". This patch provides the maximum "max-rate" value
for any minimum bandwidth rule.

Closes-Bug: #1977752

Conflicts:
    neutron/agent/common/ovs_lib.py
    neutron/tests/functional/agent/common/test_ovs_lib.py
    neutron/tests/fullstack/test_qos.py

Change-Id: I2c6f09548f39cadfe85e57032091a70a5bc978e5
(cherry picked from commit a575dbc4a1)
(cherry picked from commit cd87a7cbd1)
This commit is contained in:
Rodolfo Alonso Hernandez 2022-05-18 03:43:40 +00:00
parent 07e1c6c22e
commit 9dd0cce8fd
3 changed files with 13 additions and 5 deletions

View File

@ -70,6 +70,7 @@ _SENTINEL = object()
CTRL_RATE_LIMIT_MIN = 100
CTRL_BURST_LIMIT_MIN = 25
OVS_MAX_RATE = 2 ** 35 - 1
# TODO(slaweq): move this to neutron_lib.constants
TYPE_GRE_IP6 = 'ip6gre'
@ -1056,7 +1057,9 @@ class OVSBridge(BaseOVS):
def _update_queue(self, port_id, queue_num, queue_type, max_kbps=None,
max_burst_kbps=None, min_kbps=None):
other_config = {}
queue = self._find_queue(port_id, _type=queue_type)
other_config = dict(queue['other_config']) if queue else {}
if max_kbps:
other_config[six.u('max-rate')] = six.u(
str(int(max_kbps) * p_const.SI_BASE))
@ -1065,8 +1068,9 @@ class OVSBridge(BaseOVS):
if min_kbps:
other_config[six.u('min-rate')] = six.u(
str(min_kbps * p_const.SI_BASE))
if six.u('max-rate') not in other_config:
other_config[six.u('max-rate')] = six.u(str(OVS_MAX_RATE))
queue = self._find_queue(port_id, _type=queue_type)
if queue and queue['_uuid']:
if queue['other_config'] != other_config:
self.set_db_attribute('Queue', queue['_uuid'], 'other_config',
@ -1124,11 +1128,13 @@ class OVSBridge(BaseOVS):
if not qos_id:
external_ids = {'id': rule_type_id,
'_type': rule_type}
other_config = {'max-rate': str(OVS_MAX_RATE)}
self.ovsdb.db_create(
'QoS',
type='linux-htb',
queues=queues,
external_ids=external_ids).execute(check_error=True)
external_ids=external_ids,
other_config=other_config).execute(check_error=True)
qos_id, _ = self._find_qos(rule_type_id, rule_type)
else:
self.clear_db_attribute('QoS', qos_id, 'queues')

View File

@ -715,7 +715,8 @@ class TestMinBwQoSOvs(_TestMinBwQoS, base.BaseFullStackTestCase):
vm, MIN_BANDWIDTH, self.direction)
qos, queue = self._find_agent_qos_and_queue(vm)
self.assertEqual({'min-rate': str(MIN_BANDWIDTH * 1000)},
self.assertEqual({'min-rate': str(MIN_BANDWIDTH * 1000),
'max-rate': str(ovs_lib.OVS_MAX_RATE)},
queue.other_config)
queues = vm.bridge._list_queues(port=vm.neutron_port['id'])
self.assertEqual(1, len(queues))

View File

@ -477,7 +477,8 @@ class BaseOVSTestCase(base.BaseSudoTestCase):
six.u('type'): six.u(
qos_constants.RULE_TYPE_MINIMUM_BANDWIDTH),
six.u('queue-num'): six.u(str(queue_num))}
other_config = {six.u('min-rate'): six.u('1700000')}
other_config = {six.u('min-rate'): six.u('1700000'),
six.u('max-rate'): six.u(str(ovs_lib.OVS_MAX_RATE))}
expected = {'_uuid': queue_id,
'external_ids': external_ids,
'other_config': other_config}