From adeac78ed6585b16102bd82581b54c75819714b2 Mon Sep 17 00:00:00 2001 From: Andrew Topp Date: Tue, 30 Jul 2024 13:48:18 +1000 Subject: pbr: T6430: Allow forwarding into VRFs by name as well as route table IDs * PBR can only target table IDs up to 200 and the previous PR to extend the range was rejected * PBR with this PR can now also target VRFs directly by name, working around targeting problems for VRF table IDs outside the overlapping 100-200 range * Validation ensures rules can't target both a table ID and a VRF name (internally they are handled the same) * Added a simple accessor (get_vrf_table_id) for runtime mapping a VRF name to table ID, based on vyos.ifconfig.interface._set_vrf_ct_zone(). It does not replace that usage, as it deliberately does not handle non-VRF interface lookups (would fail with a KeyError). * Added route table ID lookup dict, global route table and VRF table defs to vyos.defaults. Table ID references have been updated in code touched by this PR. * Added a simple smoketest to validate 'set vrf' usage in PBR rules --- src/conf_mode/policy_route.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/conf_mode/policy_route.py b/src/conf_mode/policy_route.py index c58fe1bce..da9002b59 100755 --- a/src/conf_mode/policy_route.py +++ b/src/conf_mode/policy_route.py @@ -25,6 +25,9 @@ from vyos.template import render from vyos.utils.dict import dict_search_args from vyos.utils.process import cmd from vyos.utils.process import run +from vyos.utils.network import get_vrf_table_id +from vyos.defaults import rt_global_table +from vyos.defaults import rt_global_vrf from vyos import ConfigError from vyos import airbag airbag.enable() @@ -83,6 +86,9 @@ def verify_rule(policy, name, rule_conf, ipv6, rule_id): if not tcp_flags or 'syn' not in tcp_flags: raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS') + if 'vrf' in rule_conf['set'] and 'table' in rule_conf['set']: + raise ConfigError(f'{name} rule {rule_id}: Cannot set both forwarding route table and VRF') + tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags') if tcp_flags: if dict_search_args(rule_conf, 'protocol') != 'tcp': @@ -152,15 +158,26 @@ def apply_table_marks(policy): for name, pol_conf in policy[route].items(): if 'rule' in pol_conf: for rule_id, rule_conf in pol_conf['rule'].items(): + vrf_table_id = None set_table = dict_search_args(rule_conf, 'set', 'table') - if set_table: + set_vrf = dict_search_args(rule_conf, 'set', 'vrf') + if set_vrf: + if set_vrf == 'default': + vrf_table_id = rt_global_vrf + else: + vrf_table_id = get_vrf_table_id(set_vrf) + elif set_table: if set_table == 'main': - set_table = '254' - if set_table in tables: + vrf_table_id = rt_global_table + else: + vrf_table_id = set_table + if vrf_table_id is not None: + vrf_table_id = int(vrf_table_id) + if vrf_table_id in tables: continue - tables.append(set_table) - table_mark = mark_offset - int(set_table) - cmd(f'{cmd_str} rule add pref {set_table} fwmark {table_mark} table {set_table}') + tables.append(vrf_table_id) + table_mark = mark_offset - vrf_table_id + cmd(f'{cmd_str} rule add pref {vrf_table_id} fwmark {table_mark} table {vrf_table_id}') def cleanup_table_marks(): for cmd_str in ['ip', 'ip -6']: -- cgit v1.2.3 From 9b99a01653e3315b1abc9ef98824ca71bd283047 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Tue, 30 Jul 2024 08:07:29 +0200 Subject: pbr: T6430: refactor to use vyos.utils.network.get_vrf_tableid() Commit 452068ce78 ("interfaces: T6592: moving an interface between VRF instances failed") added a similar but more detailed implementation of get_vrf_table_id() that was added in commit adeac78ed of this PR. Move to the common available implementation. --- python/vyos/firewall.py | 6 +++--- python/vyos/utils/network.py | 3 --- src/conf_mode/policy_route.py | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 89cd68183..facd498ca 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -30,7 +30,7 @@ from vyos.utils.dict import dict_search_args from vyos.utils.dict import dict_search_recursive from vyos.utils.process import cmd from vyos.utils.process import run -from vyos.utils.network import get_vrf_table_id +from vyos.utils.network import get_vrf_tableid from vyos.defaults import rt_global_table from vyos.defaults import rt_global_vrf @@ -482,8 +482,8 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): if vrf_name == 'default': table = rt_global_vrf else: - # NOTE: VRF->table ID lookup depends on the VRF iface already existing. - table = get_vrf_table_id(vrf_name) + # NOTE: VRF->table ID lookup depends on the VRF iface already existing. + table = get_vrf_tableid(vrf_name) if 'table' in rule_conf['set']: set_table = True table = rule_conf['set']['table'] diff --git a/python/vyos/utils/network.py b/python/vyos/utils/network.py index d297a1ddb..8fce08de0 100644 --- a/python/vyos/utils/network.py +++ b/python/vyos/utils/network.py @@ -74,9 +74,6 @@ def get_vrf_members(vrf: str) -> list: pass return interfaces -def get_vrf_table_id(vrf: str): - return get_interface_config(vrf)['linkinfo']['info_data']['table'] - def get_interface_vrf(interface): """ Returns VRF of given interface """ from vyos.utils.dict import dict_search diff --git a/src/conf_mode/policy_route.py b/src/conf_mode/policy_route.py index da9002b59..223175b8a 100755 --- a/src/conf_mode/policy_route.py +++ b/src/conf_mode/policy_route.py @@ -25,7 +25,7 @@ from vyos.template import render from vyos.utils.dict import dict_search_args from vyos.utils.process import cmd from vyos.utils.process import run -from vyos.utils.network import get_vrf_table_id +from vyos.utils.network import get_vrf_tableid from vyos.defaults import rt_global_table from vyos.defaults import rt_global_vrf from vyos import ConfigError @@ -165,14 +165,14 @@ def apply_table_marks(policy): if set_vrf == 'default': vrf_table_id = rt_global_vrf else: - vrf_table_id = get_vrf_table_id(set_vrf) + vrf_table_id = get_vrf_tableid(set_vrf) elif set_table: if set_table == 'main': vrf_table_id = rt_global_table else: vrf_table_id = set_table if vrf_table_id is not None: - vrf_table_id = int(vrf_table_id) + vrf_table_id = int(vrf_table_id) if vrf_table_id in tables: continue tables.append(vrf_table_id) -- cgit v1.2.3