diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/completion/qos/list_traffic_match_group.py | 35 | ||||
-rwxr-xr-x | src/conf_mode/qos.py | 77 |
2 files changed, 107 insertions, 5 deletions
diff --git a/src/completion/qos/list_traffic_match_group.py b/src/completion/qos/list_traffic_match_group.py new file mode 100644 index 000000000..015d7ada9 --- /dev/null +++ b/src/completion/qos/list_traffic_match_group.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from vyos.config import Config + + +def get_qos_traffic_match_group(): + config = Config() + base = ['qos', 'traffic-match-group'] + conf = config.get_config_dict(base, key_mangling=('-', '_')) + groups = [] + + for group in conf.get('traffic_match_group', []): + groups.append(group) + + return groups + + +if __name__ == "__main__": + groups = get_qos_traffic_match_group() + print(" ".join(groups)) + diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py index 8a590cbc6..45248fb4a 100755 --- a/src/conf_mode/qos.py +++ b/src/conf_mode/qos.py @@ -17,6 +17,7 @@ from sys import exit from netifaces import interfaces +from vyos.base import Warning from vyos.config import Config from vyos.configdep import set_dependents from vyos.configdep import call_dependents @@ -89,6 +90,36 @@ def _clean_conf_dict(conf): return conf +def _get_group_filters(config: dict, group_name: str, visited=None) -> dict: + filters = dict() + if not visited: + visited = [group_name, ] + else: + if group_name in visited: + return filters + visited.append(group_name) + + for filter, filter_config in config.get(group_name, {}).items(): + if filter == 'match': + for match, match_config in filter_config.items(): + filters[f'{group_name}-{match}'] = match_config + elif filter == 'match_group': + for group in filter_config: + filters.update(_get_group_filters(config, group, visited)) + + return filters + + +def _get_group_match(config:dict, group_name:str) -> dict: + match = dict() + for key, val in _get_group_filters(config, group_name).items(): + # delete duplicate matches + if val not in match.values(): + match[key] = val + + return match + + def get_config(config=None): if config: conf = config @@ -135,11 +166,27 @@ def get_config(config=None): qos = conf.merge_defaults(qos, recursive=True) + if 'traffic_match_group' in qos: + for group, group_config in qos['traffic_match_group'].items(): + if 'match_group' in group_config: + qos['traffic_match_group'][group]['match'] = _get_group_match(qos['traffic_match_group'], group) + for policy in qos.get('policy', []): for p_name, p_config in qos['policy'][policy].items(): # cleanup empty match config if 'class' in p_config: for cls, cls_config in p_config['class'].items(): + if 'match_group' in cls_config: + # merge group match to match + for group in cls_config['match_group']: + for match, match_conf in qos['traffic_match_group'].get(group, {'match': {}})['match'].items(): + if 'match' not in cls_config: + cls_config['match'] = dict() + if match in cls_config['match']: + cls_config['match'][f'{group}-{match}'] = match_conf + else: + cls_config['match'][match] = match_conf + if 'match' in cls_config: cls_config['match'] = _clean_conf_dict(cls_config['match']) if cls_config['match'] == {}: @@ -147,6 +194,22 @@ def get_config(config=None): return qos + +def _verify_match(cls_config: dict) -> None: + if 'match' in cls_config: + for match, match_config in cls_config['match'].items(): + if {'ip', 'ipv6'} <= set(match_config): + raise ConfigError( + f'Can not use both IPv6 and IPv4 in one match ({match})!') + + +def _verify_match_group_exist(cls_config, qos): + if 'match_group' in cls_config: + for group in cls_config['match_group']: + if 'traffic_match_group' not in qos or group not in qos['traffic_match_group']: + Warning(f'Match group "{group}" does not exist!') + + def verify(qos): if not qos or 'interface' not in qos: return None @@ -174,11 +237,8 @@ def verify(qos): # bandwidth is not mandatory for priority-queue - that is why this is on the exception list if 'bandwidth' not in cls_config and policy_type not in ['priority_queue', 'round_robin', 'shaper_hfsc']: raise ConfigError(f'Bandwidth must be defined for policy "{policy}" class "{cls}"!') - if 'match' in cls_config: - for match, match_config in cls_config['match'].items(): - if {'ip', 'ipv6'} <= set(match_config): - raise ConfigError(f'Can not use both IPv6 and IPv4 in one match ({match})!') - + _verify_match(cls_config) + _verify_match_group_exist(cls_config, qos) if policy_type in ['random_detect']: if 'precedence' in policy_config: for precedence, precedence_config in policy_config['precedence'].items(): @@ -216,8 +276,14 @@ def verify(qos): if direction not in tmp: raise ConfigError(f'Selected QoS policy on interface "{interface}" only supports "{tmp}"!') + if 'traffic_match_group' in qos: + for group, group_config in qos['traffic_match_group'].items(): + _verify_match(group_config) + _verify_match_group_exist(group_config, qos) + return None + def generate(qos): if not qos or 'interface' not in qos: return None @@ -254,6 +320,7 @@ def apply(qos): return None + if __name__ == '__main__': try: c = get_config() |