diff options
| -rw-r--r-- | interface-definitions/firewall.xml.in | 2 | ||||
| -rw-r--r-- | interface-definitions/include/firewall/action.xml.i | 8 | ||||
| -rw-r--r-- | interface-definitions/include/firewall/nft-queue.xml.i | 34 | ||||
| -rw-r--r-- | python/vyos/firewall.py | 9 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_firewall.py | 13 | ||||
| -rwxr-xr-x | src/conf_mode/firewall.py | 9 | 
6 files changed, 72 insertions, 3 deletions
| 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 @@                    </completionHelp>                  </properties>                </leafNode> +              #include <include/firewall/nft-queue.xml.i>              </children>            </tagNode>          </children> @@ -671,6 +672,7 @@                  </properties>                </leafNode>                #include <include/firewall/ttl.xml.i> +              #include <include/firewall/nft-queue.xml.i>              </children>            </tagNode>          </children> 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 @@    <properties>      <help>Rule action</help>      <completionHelp> -      <list>accept jump reject return drop</list> +      <list>accept jump reject return drop queue</list>      </completionHelp>      <valueHelp>        <format>accept</format> @@ -25,8 +25,12 @@        <format>drop</format>        <description>Drop matching entries</description>      </valueHelp> +    <valueHelp> +      <format>queue</format> +      <description>Enqueue packet to userspace</description> +    </valueHelp>      <constraint> -      <regex>(accept|jump|reject|return|drop)</regex> +      <regex>(accept|jump|reject|return|drop|queue)</regex>      </constraint>    </properties>  </leafNode> 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 @@ +<!-- include start from firewall/nft-queue.xml.i --> +<leafNode name="queue"> +  <properties> +    <help>Queue target to use. Action queue must be defined to use this setting</help> +    <valueHelp> +      <format>u32:0-65535</format> +      <description>Queue target</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--allow-range --range 0-65535"/> +    </constraint> +  </properties> +</leafNode> +<leafNode name="queue-options"> +  <properties> +    <help>Options used for queue target. Action queue must be defined to use this setting</help> +    <completionHelp> +      <list>bypass fanout</list> +    </completionHelp> +    <valueHelp> +      <format>bypass</format> +      <description>Let packets go through if userspace application cannot back off</description> +    </valueHelp> +    <valueHelp> +      <format>fanout</format> +      <description>Distribute packets between several queues</description> +    </valueHelp> +    <constraint> +      <regex>(bypass|fanout)</regex> +    </constraint> +    <multi/> +  </properties> +</leafNode> +<!-- include end -->
\ 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"') | 
