neutron 一共支持三种类型的资源的 qos,分别是 fip 端口,网关路由器端口,以及 固定 ip 端口。
其中 qos 的添加和删除操作都是基于 ovsdbapp 库实现的
ovsdbapp 中关于 qos_add 的实现,
(vv) ➜ neutron git:(master) pwd
/Users/aoy/g/m/neutron
(vv) ➜ neutron git:(master) grep -A 5 ovn_rule -r *
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: for ovn_rule in [self._ovn_qos_rule(direction, {}, port_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- network_id, delete=True)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- for direction in constants.VALID_DIRECTIONS]:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: min_qos_value = ovn_rule.pop(_MIN_RATE, None)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_del(**ovn_rule))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- if not port_deleted:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- self._update_lsp_qos_options(txn, lsp, port_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- min_qos_value)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py-
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- def _add_port_qos_rules(self, txn, port_id, network_id, qos_policy_id,
--
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: # generate a "ovn_rule" to be used as input in a "qos_del" method.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: ovn_rule = self._ovn_qos_rule(direction, rules, port_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- network_id, delete=not rules)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: min_qos_value = ovn_rule.pop(_MIN_RATE, None)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- if rules:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # NOTE(ralonsoh): with "may_exist=True", the "qos_add" will
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # create the QoS OVN rule or update the existing one.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_add(**ovn_rule, may_exist=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- else:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # Delete, if exists, the QoS rule in this direction.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_del(**ovn_rule, if_exists=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- self._update_lsp_qos_options(txn, lsp, port_id, min_qos_value)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py-
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- def _update_port_qos_rules(self, txn, port_id, network_id, qos_policy_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- qos_rules, lsp=None, port_deleted=False):
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- if not qos_policy_id:
--
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: # generate a "ovn_rule" to be used as input in a "qos_del" method.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: ovn_rule = self._ovn_qos_rule(
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- direction, rules, gw_port_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- floatingip['floating_network_id'], fip_id=floatingip['id'],
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- ip_address=floatingip['floating_ip_address'],
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- resident_port=resident_port, delete=not rules)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- if rules:
--
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_add(**ovn_rule, may_exist=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- else:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # Delete, if exists, the QoS rule in this direction.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_del(**ovn_rule, if_exists=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py-
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- def delete_floatingip(self, txn, floatingip):
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- self.update_floatingip(txn, floatingip)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py-
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- def disassociate_floatingip(self, txn, floatingip):
--
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: # generate a "ovn_rule" to be used as input in a "qos_del" method.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: ovn_rule = self._ovn_qos_rule(
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- direction, rules, gw_port_id, gw_network_id,
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- router_id=router_id, delete=not rules)
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- if rules:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # NOTE(ralonsoh): with "may_exist=True", the "qos_add" will
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # create the QoS OVN rule or update the existing one.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_add(**ovn_rule, may_exist=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- else:
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- # Delete, if exists, the QoS rule in this direction.
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py: txn.add(self.nb_idl.qos_del(**ovn_rule, if_exists=True))
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py-
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- def update_policy(self, context, policy):
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- updated_port_ids = set([])
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- updated_fip_ids = set([])
neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py- updated_router_ids = set([])
--
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py: egress_ovn_rule = self.qos_driver._ovn_qos_rule(
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- constants.EGRESS_DIRECTION, rules.get(constants.EGRESS_DIRECTION),
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- port_id, network_id, fip_id=fip_id, ip_address=ip_address)
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py: ingress_ovn_rule = self.qos_driver._ovn_qos_rule(
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- constants.INGRESS_DIRECTION,
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- rules.get(constants.INGRESS_DIRECTION), port_id, network_id,
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- fip_id=fip_id, ip_address=ip_address)
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py-
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- with self.nb_api.transaction(check_error=True):
--
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py: ref_rule = (egress_ovn_rule if rule.direction == 'from-lport'
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py: else ingress_ovn_rule)
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- action = {}
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- if 'dscp' in ref_rule:
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- action = {'dscp': ref_rule['dscp']}
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- bandwidth = {}
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py- if 'rate' in ref_rule:
--
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py: for ovn_rule in [self.qos_driver._ovn_qos_rule(
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- direction, {}, port['id'], port['network_id'],
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- delete=True)
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- for direction in constants.VALID_DIRECTIONS]:
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py: txn.add(self.nb_api.qos_del(**ovn_rule))
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- self._validate_qos_records(should_match=False)
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py-
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- # Manually sync port QoS registers.
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- nb_synchronizer = ovn_db_sync.OvnNbSynchronizer(
neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py- self.plugin, self.mech_driver.nb_ovn, self.mech_driver.sb_ovn,
--
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py: ovn_rules = qos_extension._ovn_qos_rule(constants.EGRESS_DIRECTION,
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py- rules, lsp.name, network_id)
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py: self.nb_api.qos_add(**ovn_rules, may_exist=True).execute(
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py- check_error=True)
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py-
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py- # Retrieve the min-bw and max-bw egress rules associated to a port.
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py- max_kbps, min_kbps = agent_ovsdb.get_port_qos(self.nb_api, lsp.name)
neutron/tests/functional/agent/ovn/agent/test_ovsdb.py- self.assertEqual((max_qos_value, min_qos_value), (max_kbps, min_kbps))
--
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: ovn_rule = {'switch': lswitch_name,
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- 'priority': 1000,
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- 'direction': 'from-lport',
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- 'match': 'inport == ' + port_id,
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- 'rate': 10000,
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- 'external_ids': {ovn_const.OVN_PORT_EXT_ID_KEY: port_id}}
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: self.nb_api.qos_add(**ovn_rule).execute(check_error=True)
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- n_utils.wait_until_true(
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: lambda: check_update_egress_called(ovn_rule['rate']), timeout=5)
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py-
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: ovn_rule['rate'] = 15000
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: self.nb_api.qos_add(**ovn_rule, may_exist=True).execute(
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- check_error=True)
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- n_utils.wait_until_true(
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py: lambda: check_update_egress_called(ovn_rule['rate']), timeout=5)
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py-
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py-
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py-class QoSMinimumBandwidthEventTestCase(base.TestOVNFunctionalBase):
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py-
neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py- def setUp(self, **kwargs):
def update_router(self, txn, router):
gw_info = router.get(l3_api.EXTERNAL_GW_INFO) or {}
qos_policy_id = n_utils.effective_qos_policy_id(router)
router_id = router.get('id')
gw_port_id = router.get('gw_port_id')
gw_network_id = gw_info.get('network_id')
if not (router_id and gw_port_id and gw_network_id):
# NOTE(ralonsoh): when the gateway network is detached, the gateway
# port is deleted. Any QoS policy related to this port_id is
# deleted in "self.update_port()".
LOG.debug('Router %s does not have ID or gateway assigned',
router_id)
return
admin_context = n_context.get_admin_context()
qos_rules = self._qos_rules(admin_context, qos_policy_id)
for direction, rules in qos_rules.items():
# "delete=not rule": that means, when we don't have rules, we
# generate a "ovn_rule" to be used as input in a "qos_del" method.
ovn_rule = self._ovn_qos_rule(
direction, rules, gw_port_id, gw_network_id,
router_id=router_id, delete=not rules) # qos 的主要参数
if rules:
# NOTE(ralonsoh): with "may_exist=True", the "qos_add" will
# create the QoS OVN rule or update the existing one.
txn.add(self.nb_idl.qos_add(**ovn_rule, may_exist=True))
else:
# Delete, if exists, the QoS rule in this direction.
txn.add(self.nb_idl.qos_del(**ovn_rule, if_exists=True))
该功能的实现,用的就是 northbound QoS 的表。
参考: