From bbfe6b54b58b68768f6427496d8ac3c1ef38da93 Mon Sep 17 00:00:00 2001 From: Nicolas Fort Date: Mon, 27 Feb 2023 20:11:35 +0000 Subject: T5037: Firewall: Add queue action and options to firewall --- interface-definitions/firewall.xml.in | 2 ++ .../include/firewall/action.xml.i | 8 +++-- .../include/firewall/nft-queue.xml.i | 34 ++++++++++++++++++++++ python/vyos/firewall.py | 9 ++++++ smoketest/scripts/cli/test_firewall.py | 13 ++++++++- src/conf_mode/firewall.py | 9 ++++++ 6 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 interface-definitions/include/firewall/nft-queue.xml.i diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index 7d7e0a38f..c9a132c4a 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -502,6 +502,7 @@ + #include @@ -671,6 +672,7 @@ #include + #include diff --git a/interface-definitions/include/firewall/action.xml.i b/interface-definitions/include/firewall/action.xml.i index 468340cbb..7c6e33839 100644 --- a/interface-definitions/include/firewall/action.xml.i +++ b/interface-definitions/include/firewall/action.xml.i @@ -3,7 +3,7 @@ Rule action - accept jump reject return drop + accept jump reject return drop queue accept @@ -25,8 +25,12 @@ drop Drop matching entries + + queue + Enqueue packet to userspace + - (accept|jump|reject|return|drop) + (accept|jump|reject|return|drop|queue) diff --git a/interface-definitions/include/firewall/nft-queue.xml.i b/interface-definitions/include/firewall/nft-queue.xml.i new file mode 100644 index 000000000..8799eac74 --- /dev/null +++ b/interface-definitions/include/firewall/nft-queue.xml.i @@ -0,0 +1,34 @@ + + + + Queue target to use. Action queue must be defined to use this setting + + u32:0-65535 + Queue target + + + + + + + + + Options used for queue target. Action queue must be defined to use this setting + + bypass fanout + + + bypass + Let packets go through if userspace application cannot back off + + + fanout + Distribute packets between several queues + + + (bypass|fanout) + + + + + \ No newline at end of file diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index b4b9e67bb..149803bf0 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -337,6 +337,15 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): target = rule_conf['jump_target'] output.append(f'NAME{def_suffix}_{target}') + if 'queue' in rule_conf['action']: + if 'queue' in rule_conf: + target = rule_conf['queue'] + output.append(f'num {target}') + + if 'queue_options' in rule_conf: + queue_opts = ','.join(rule_conf['queue_options']) + output.append(f'{queue_opts}') + else: output.append('return') diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index f1c18d761..41ba633d9 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -284,6 +284,15 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', name2, 'rule', '1', 'action', 'jump']) self.cli_set(['firewall', 'name', name2, 'rule', '1', 'jump-target', name]) + self.cli_set(['firewall', 'name', name2, 'rule', '2', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', name2, 'rule', '2', 'action', 'queue']) + self.cli_set(['firewall', 'name', name2, 'rule', '2', 'queue', '3']) + self.cli_set(['firewall', 'name', name2, 'rule', '3', 'protocol', 'udp']) + self.cli_set(['firewall', 'name', name2, 'rule', '3', 'action', 'queue']) + self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue-options', 'fanout']) + self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue-options', 'bypass']) + self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue', '0-15']) + self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) self.cli_commit() @@ -294,7 +303,9 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ['ip length 1-30000', 'ip length != 60000-65535', 'ip dscp 0x03-0x0b', 'ip dscp != 0x15-0x19', 'return'], [f'log prefix "[{name}-default-D]"', 'drop'], ['ip saddr 198.51.100.1', f'jump NAME_{name}'], - [f'log prefix "[{name2}-default-J]"', f'jump NAME_{name}'] + [f'log prefix "[{name2}-default-J]"', f'jump NAME_{name}'], + [f'meta l4proto tcp','queue to 3'], + [f'meta l4proto udp','queue flags bypass,fanout to 0-15'] ] self.verify_nftables(nftables_search, 'ip vyos_filter') diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 20cf1ead1..b63ed4eb9 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -197,6 +197,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 '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') + if 'fanout' in rule_conf['queue_options'] and ('queue' not in rule_conf or '-' not in rule_conf['queue']): + raise ConfigError('queue-options fanout defined, then queue needs to be defined as a range') + + if 'queue' in rule_conf and 'queue' not in rule_conf['action']: + raise ConfigError('queue defined, but action queue needed and it is not defined') + if 'fragment' in rule_conf: if {'match_frag', 'match_non_frag'} <= set(rule_conf['fragment']): raise ConfigError('Cannot specify both "match-frag" and "match-non-frag"') -- cgit v1.2.3