neutron qos

199 阅读4分钟

neutron 一共支持三种类型的资源的 qos,分别是 fip 端口,网关路由器端口,以及 固定 ip 端口。

image.png

其中 qos 的添加和删除操作都是基于 ovsdbapp 库实现的

image.png

ovsdbapp 中关于 qos_add 的实现,

image.png


(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))


image.png

该功能的实现,用的就是 northbound QoS 的表。

参考:

github.com/openstack/n…

github.com/openstack/n…

github.com/openstack/o…