diff options
Diffstat (limited to 'src/conf_mode/firewall.py')
-rwxr-xr-x | src/conf_mode/firewall.py | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 769cc598f..3d799318e 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -27,6 +27,7 @@ from vyos.configdict import node_changed from vyos.configdiff import get_config_diff, Diff from vyos.configdep import set_dependents, call_dependents from vyos.configverify import verify_interface_exists +from vyos.ethtool import Ethtool from vyos.firewall import fqdn_config_parse from vyos.firewall import geoip_update from vyos.template import render @@ -141,13 +142,7 @@ def get_config(config=None): fqdn_config_parse(firewall) - firewall['flowtable_enabled'] = False - flow_offload = dict_search_args(firewall, 'global_options', 'flow_offload') - if flow_offload and 'disable' not in flow_offload: - for offload_type in ('software', 'hardware'): - if dict_search_args(flow_offload, offload_type, 'interface'): - firewall['flowtable_enabled'] = True - break + set_dependents('conntrack', conf) return firewall @@ -169,6 +164,15 @@ def verify_rule(firewall, rule_conf, ipv6): if target not in dict_search_args(firewall, 'ipv6', 'name'): raise ConfigError(f'Invalid jump-target. Firewall ipv6 name {target} does not exist on the system') + if rule_conf['action'] == 'offload': + if 'offload_target' not in rule_conf: + raise ConfigError('Action set to offload, but no offload-target specified') + + offload_target = rule_conf['offload_target'] + + if not dict_search_args(firewall, 'flowtable', offload_target): + raise ConfigError(f'Invalid offload-target. Flowtable "{offload_target}" does not exist on the system') + if 'queue_options' in rule_conf: if 'queue' not in rule_conf['action']: raise ConfigError('queue-options defined, but action queue needed and it is not defined') @@ -288,7 +292,31 @@ def verify_nested_group(group_name, group, groups, seen): if 'include' in groups[g]: verify_nested_group(g, groups[g], groups, seen) +def verify_hardware_offload(ifname): + ethtool = Ethtool(ifname) + enabled, fixed = ethtool.get_hw_tc_offload() + + if not enabled and fixed: + raise ConfigError(f'Interface "{ifname}" does not support hardware offload') + + if not enabled: + raise ConfigError(f'Interface "{ifname}" requires "offload hw-tc-offload"') + def verify(firewall): + if 'flowtable' in firewall: + for flowtable, flowtable_conf in firewall['flowtable'].items(): + if 'interface' not in flowtable_conf: + raise ConfigError(f'Flowtable "{flowtable}" requires at least one interface') + + for ifname in flowtable_conf['interface']: + verify_interface_exists(ifname) + + if dict_search_args(flowtable_conf, 'offload') == 'hardware': + interfaces = flowtable_conf['interface'] + + for ifname in interfaces: + verify_hardware_offload(ifname) + if 'group' in firewall: for group_type in nested_group_types: if group_type in firewall['group']: @@ -336,33 +364,12 @@ def verify(firewall): for rule_id, rule_conf in name_conf['rule'].items(): verify_rule(firewall, rule_conf, True) - # Verify flow offload options - flow_offload = dict_search_args(firewall, 'global_options', 'flow_offload') - for offload_type in ('software', 'hardware'): - interfaces = dict_search_args(flow_offload, offload_type, 'interface') or [] - for interface in interfaces: - # nft will raise an error when adding a non-existent interface to a flowtable - verify_interface_exists(interface) - return None def generate(firewall): if not os.path.exists(nftables_conf): firewall['first_install'] = True - # Determine if conntrack is needed - firewall['ipv4_conntrack_action'] = 'return' - firewall['ipv6_conntrack_action'] = 'return' - if firewall['flowtable_enabled']: # Netfilter's flowtable offload requires conntrack - firewall['ipv4_conntrack_action'] = 'accept' - firewall['ipv6_conntrack_action'] = 'accept' - else: # Check if conntrack is needed by firewall rules - for proto in ('ipv4', 'ipv6'): - for rules, _ in dict_search_recursive(firewall.get(proto, {}), 'rule'): - if any(('state' in rule_conf or 'connection_status' in rule_conf) for rule_conf in rules.values()): - firewall[f'{proto}_conntrack_action'] = 'accept' - break - render(nftables_conf, 'firewall/nftables.j2', firewall) return None @@ -392,8 +399,7 @@ def apply(firewall): apply_sysfs(firewall) - if firewall['group_resync']: - call_dependents() + call_dependents() # T970 Enable a resolver (systemd daemon) that checks # domain-group/fqdn addresses and update entries for domains by timeout |