Merge "Test QoS max bandwidth limit for router gateways, along with other types"

This commit is contained in:
Zuul
2025-07-24 09:37:27 +00:00
committed by Gerrit Code Review

View File

@@ -322,10 +322,16 @@ class QosBaseTest(test_qos.QoSTestMixin, base.TrafficFlowTest):
# a 20% of lower deviation is allowed
self.assertGreater(measured_bw, bw_limit * 0.8)
def _validate_traffic_bw_limit(self, client, server,
egress=True, ipv6=False, fip_qos=False):
def _validate_traffic_bw_limit(self, client, server, egress=True,
ipv6=False, fip_qos=False, gw_qos=False):
"""Validate that bw limit is applied to the traffic between client and
server VMs
server VMs.
Precedence summary for max-bw limit:
- only port: then max-bw port
- port + gw: minimum max-bw
- port + gw/fip: minimum max-bw of port or FIP
(GW is discarded because FIP has precedence)
Scenario:
1. First make sure that bw between VMs is not limited.
@@ -341,8 +347,22 @@ class QosBaseTest(test_qos.QoSTestMixin, base.TrafficFlowTest):
7. Send traffic between 2 VMs and make sure that now bw is
limited according to the new value (since rule for port has higher
priority).
8. Delete bw limit rule from the port QoS policy and make sure
that traffic is not limited.
8. Create another QoS policy applied to GW,
verify together with port QoS when lower/higher.
9. Delete bandwidth rule from the router gateway QoS policy
and make sure that traffic is limited for port value - step 12
(unless FIP checked, then rule kept to verify when all 3 used).
10. Create another QoS policy applied to FIP, verify
FIP and port lower/higher (if enabled also GW higher),
also verify when GW lower than FIP/port - lowest between FIP/port
prioritized (priority - A: port > FIP > GW, B: FIP > port > GW).
11. Delete bandwidth rule from FIP QoS policy,
and make sure that traffic is limited for GW value.
12. Delete bandwidth rule from GW QoS policy,
and make sure that traffic is limited for port value again.
13. Delete bandwidth limit rule from the port QoS policy and make
sure that traffic is not limited.
14. Verify a QoS policy attached to a port cannot be deleted.
"""
# Prerequisite: install iperf3
self._skip_if_iperf3_not_installed(client['ssh_client'])
@@ -414,6 +434,79 @@ class QosBaseTest(test_qos.QoSTestMixin, base.TrafficFlowTest):
client, server, egress, bw_limit=max_kbps * 1000,
protocol=constants.PROTO_NAME_UDP)
# NOTE(mblue): only enabled in north-south topology option when
# routed through gateways.
if gw_qos:
# apply policy for router gateway (no rule in policy yet)
gw_bw_policy_id = self._create_qos_policy()
self.router['external_gateway_info'][
'qos_policy_id'] = gw_bw_policy_id
self.router = self.admin_client.update_router(
self.router['id'],
external_gateway_info=self.router['external_gateway_info']
)['router']
del self.router['external_gateway_info']['qos_policy_id']
self.addCleanup(
self.admin_client.update_router,
self.router['id'],
external_gateway_info=self.router['external_gateway_info'])
# gw bw limit greater than port bw limit
gw_max_kbps = max_kbps * 20
rule_data = {
'max_kbps': gw_max_kbps,
'max_burst_kbps': gw_max_kbps * 0.8,
'direction': direction}
gw_port_rule_id = self._create_qos_bw_limit_rule(
gw_bw_policy_id, rule_data)['id']
# port bw limit is lower than gw bw limit, so max_kbps
# will be the measured bw
self._validate_bw_limit(
client, server, egress, bw_limit=max_kbps * 1000,
protocol=constants.PROTO_NAME_UDP)
# gw bw limit lower than port bw limit
gw_max_kbps = max_kbps // 2
rule_update_data = {
'max_kbps': gw_max_kbps,
'max_burst_kbps': gw_max_kbps * 0.8}
self.qos_bw_limit_rule_client.update_limit_bandwidth_rule(
qos_policy_id=gw_bw_policy_id, rule_id=gw_port_rule_id,
**rule_update_data)
# For rocky images, running iperf tests with low BW limits using
# TCP does not work well, wo UDP is used instead
# TODO(eolivare): provide link to iperf/rocky bug
protocol = (constants.PROTO_NAME_TCP
if self.username != "rocky"
else constants.PROTO_NAME_UDP)
# gw bw limit is lower than port bw limit, so gw_max_kbps
# will be the measured bw
self._validate_bw_limit(client, server, egress,
bw_limit=gw_max_kbps * 1000,
protocol=protocol)
# delete bw limit rule associated to gw qos policy,
# port bw limit applies again
# (unless FIP checked, then keep GW rule to also test
# FIP/GW precedence when each is lower).
# NOTE(mblue): port validation happens anyways at end of method.
if not fip_qos:
self.qos_bw_limit_rule_client.delete_limit_bandwidth_rule(
gw_bw_policy_id, gw_port_rule_id)
self._validate_bw_limit(client, server, egress,
bw_limit=max_kbps * 1000,
protocol=protocol)
else:
# gw bw limit greater than port/fip bw limit
gw_max_kbps = max_kbps * 20
rule_update_data = {
'max_kbps': gw_max_kbps,
'max_burst_kbps': gw_max_kbps * 0.8,
'direction': direction}
self.qos_bw_limit_rule_client.update_limit_bandwidth_rule(
qos_policy_id=gw_bw_policy_id, rule_id=gw_port_rule_id,
**rule_update_data)
# Create a new Qos Policy and attach to the FIP of src server
# This only applies to south-north tests because the traffic from the
# src server to the dst server goes through the src FIP
@@ -434,14 +527,32 @@ class QosBaseTest(test_qos.QoSTestMixin, base.TrafficFlowTest):
src_fip_id, qos_policy_id=fip_qos_pol_id)
self.addCleanup(self.admin_client.update_floatingip,
src_fip_id, qos_policy_id=None)
# port bw limit is lower than fip bw limit, so max_kbps
# will be the measured bw
# port bw limit is lower than fip (sometimes also gw) bw limit,
# so max_kbps will be the measured bw
self._validate_bw_limit(
client, server, egress, bw_limit=max_kbps * 1000,
protocol=constants.PROTO_NAME_UDP)
# fip bw limit lower than port bw limit
fip_max_kbps = max_kbps // 2
# only if gw_qos True, test when gw lower than fip and port:
# expected - fip prioritzied over gw (LP#2110018),
# and port limit applied before reaching this datapath part.
if gw_qos:
gw_max_kbps = max_kbps // 2
rule_update_data = {
'max_kbps': gw_max_kbps,
'max_burst_kbps': gw_max_kbps * 0.8,
'direction': direction}
self.qos_bw_limit_rule_client.update_limit_bandwidth_rule(
qos_policy_id=gw_bw_policy_id, rule_id=gw_port_rule_id,
**rule_update_data)
# port limit expected
self._validate_bw_limit(client, server, egress,
bw_limit=max_kbps * 1000,
protocol=protocol)
# update fip bw limit lower than port bw limit
# (also lower than gw limit if exists)
fip_max_kbps = max_kbps // 3
rule_update_data = {
'max_kbps': fip_max_kbps,
'max_burst_kbps': fip_max_kbps * 0.8}
@@ -455,16 +566,25 @@ class QosBaseTest(test_qos.QoSTestMixin, base.TrafficFlowTest):
protocol = (constants.PROTO_NAME_TCP
if self.username != "rocky"
else constants.PROTO_NAME_UDP)
# fip bw limit is lower than port bw limit, so fip_max_kbps
# fip bw limit is lower than port/gw bw limit, so fip_max_kbps
# will be the measured bw
self._validate_bw_limit(client, server, egress,
bw_limit=fip_max_kbps * 1000,
protocol=protocol)
# delete bw limit rule associated to fip qos policy
# port bw limit applies again
# delete bw limit rule associated to fip qos policy,
# so either port/gw bw limit applies again
self.qos_bw_limit_rule_client.delete_limit_bandwidth_rule(
fip_qos_pol_id, fip_port_rule_id)
# only for GW: test lower GW prioritized when with port (no FIP),
# delete GW rule for next checks
if gw_qos:
self._validate_bw_limit(client, server, egress,
bw_limit=gw_max_kbps * 1000,
protocol=protocol)
self.qos_bw_limit_rule_client.delete_limit_bandwidth_rule(
gw_bw_policy_id, gw_port_rule_id)
# validate port limit applies again
self._validate_bw_limit(client, server, egress,
bw_limit=max_kbps * 1000,
protocol=protocol)
@@ -945,9 +1065,9 @@ class QosTestCommon(QosBaseTest):
# self._create_vms_by_topology should be reverse
server, client = self._create_vms_by_topology(topology='north-south')
self._validate_traffic_bw_limit(
client, server, egress=True, fip_qos=True)
client, server, egress=True, fip_qos=True, gw_qos=True)
self._validate_traffic_bw_limit(
client, server, egress=False, fip_qos=True)
client, server, egress=False, fip_qos=True, gw_qos=True)
@decorators.idempotent_id('fc833d46-d18f-4edf-b082-5f5fe909fb79')
def test_bw_limit_east_west(self):