diff options
| author | Christian Breunig <christian@breunig.cc> | 2023-08-17 21:53:50 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-17 21:53:50 +0200 | 
| commit | 49f25c568c91750e06bb982ae0321d4448fbddbb (patch) | |
| tree | f3a48a845e03603a4c4fff8913bc82f1b230e375 | |
| parent | 214d0d4933e90cbe9440280d916f069b9db463fc (diff) | |
| parent | 6bd061100ae43bc3a8319408f5123ec9bde3f2b8 (diff) | |
| download | vyos-1x-49f25c568c91750e06bb982ae0321d4448fbddbb.tar.gz vyos-1x-49f25c568c91750e06bb982ae0321d4448fbddbb.zip | |
Merge pull request #2130 from aapostoliuk/T5409-sagitta
wireguard: T5409: Added 'set interfaces wireguard wgX threaded'
| -rw-r--r-- | interface-definitions/include/interface/per-client-thread.xml.i | 8 | ||||
| -rw-r--r-- | interface-definitions/interfaces-wireguard.xml.in | 1 | ||||
| -rw-r--r-- | interface-definitions/interfaces-wireless.xml.in | 1 | ||||
| -rw-r--r-- | python/vyos/ifconfig/interface.py | 39 | ||||
| -rw-r--r-- | python/vyos/ifconfig/wireguard.py | 4 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_interfaces_wireguard.py | 37 | ||||
| -rwxr-xr-x | src/conf_mode/interfaces-wireguard.py | 6 | 
7 files changed, 83 insertions, 13 deletions
| diff --git a/interface-definitions/include/interface/per-client-thread.xml.i b/interface-definitions/include/interface/per-client-thread.xml.i new file mode 100644 index 000000000..2fd19b5ce --- /dev/null +++ b/interface-definitions/include/interface/per-client-thread.xml.i @@ -0,0 +1,8 @@ +<!-- include start from interface/per-client-thread.xml.i --> +<leafNode name="per-client-thread"> +  <properties> +    <help>Process traffic from each client in a dedicated thread</help> +    <valueless/> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 2dd5b47d1..3c79cef28 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -120,6 +120,7 @@              </children>            </tagNode>            #include <include/interface/redirect.xml.i> +          #include <include/interface/per-client-thread.xml.i>            #include <include/interface/vrf.xml.i>          </children>        </tagNode> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index a9538d577..421d46c6e 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -778,6 +778,7 @@              </properties>              <defaultValue>monitor</defaultValue>            </leafNode> +          #include <include/interface/per-client-thread.xml.i>            #include <include/interface/redirect.xml.i>            #include <include/interface/vif.xml.i>            #include <include/interface/vif-s.xml.i> diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index cc6149428..ddac387e7 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public @@ -224,6 +224,10 @@ class Interface(Control):              'validate': lambda link: assert_range(link,0,3),              'location': '/proc/sys/net/ipv4/conf/{ifname}/link_filter',          }, +        'per_client_thread': { +            'validate': assert_boolean, +            'location': '/sys/class/net/{ifname}/threaded', +        },      }      _sysfs_get = { @@ -275,6 +279,10 @@ class Interface(Control):          'link_detect': {              'location': '/proc/sys/net/ipv4/conf/{ifname}/link_filter',          }, +        'per_client_thread': { +            'validate': assert_boolean, +            'location': '/sys/class/net/{ifname}/threaded', +        },      }      @classmethod @@ -1386,6 +1394,30 @@ class Interface(Control):                                   f'egress redirect dev {target_if}')              if err: print('tc filter add for redirect failed') +    def set_per_client_thread(self, enable): +        """ +        Per-device control to enable/disable the threaded mode for all the napi +        instances of the given network device, without the need for a device up/down. + +        User sets it to 1 or 0 to enable or disable threaded mode. + +        Example: +        >>> from vyos.ifconfig import Interface +        >>> Interface('wg1').set_per_client_thread(1) +        """ +        # In the case of a "virtual" interface like wireguard, the sysfs +        # node is only created once there is a peer configured. We can now +        # add a verify() code-path for this or make this dynamic without +        # nagging the user +        tmp = self._sysfs_get['per_client_thread']['location'] +        if not os.path.exists(tmp): +            return None + +        tmp = self.get_interface('per_client_thread') +        if tmp == enable: +            return None +        self.set_interface('per_client_thread', enable) +      def update(self, config):          """ General helper function which works on a dictionary retrived by          get_config_dict(). It's main intention is to consolidate the scattered @@ -1601,6 +1633,11 @@ class Interface(Control):          # configure interface mirror or redirection target          self.set_mirror_redirect() +        # enable/disable NAPI threading mode +        tmp = dict_search('per_client_thread', config) +        value = '1' if (tmp != None) else '0' +        self.set_per_client_thread(value) +          # Enable/Disable of an interface must always be done at the end of the          # derived class to make use of the ref-counting set_admin_state()          # function. We will only enable the interface if 'up' was called as diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index fe5e9c519..4aac103ec 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,7 @@ from hurry.filesize import alternative  from vyos.ifconfig import Interface  from vyos.ifconfig import Operational  from vyos.template import is_ipv6 +from vyos.base import Warning  class WireGuardOperational(Operational):      def _dump(self): @@ -184,7 +185,6 @@ class WireGuardIf(Interface):          base_cmd += f' private-key {tmp_file.name}'          base_cmd = base_cmd.format(**config) -          if 'peer' in config:              for peer, peer_config in config['peer'].items():                  # T4702: No need to configure this peer when it was explicitly diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py index f84ce159d..48c7cb6a1 100755 --- a/smoketest/scripts/cli/test_interfaces_wireguard.py +++ b/smoketest/scripts/cli/test_interfaces_wireguard.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-2023 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 @@ -19,6 +19,7 @@ import unittest  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError +from vyos.utils.file import read_file  base_path = ['interfaces', 'wireguard'] @@ -35,7 +36,7 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase):          self.cli_delete(base_path)          self.cli_commit() -    def test_wireguard_peer(self): +    def test_01_wireguard_peer(self):          # Create WireGuard interfaces with associated peers          for intf in self._interfaces:              peer = 'foo-' + intf @@ -62,7 +63,7 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase):              self.assertTrue(os.path.isdir(f'/sys/class/net/{intf}')) -    def test_wireguard_add_remove_peer(self): +    def test_02_wireguard_add_remove_peer(self):          # T2939: Create WireGuard interfaces with associated peers.          # Remove one of the configured peers.          # T4774: Test prevention of duplicate peer public keys @@ -100,10 +101,9 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase):          self.cli_delete(base_path + [interface, 'peer', 'PEER01'])          self.cli_commit() -    def test_wireguard_same_public_key(self): -        # T2939: Create WireGuard interfaces with associated peers. -        # Remove one of the configured peers. -        # T4774: Test prevention of duplicate peer public keys +    def test_03_wireguard_same_public_key(self): +        # T5413: Test prevention of equality interface public key and peer's +        #        public key          interface = 'wg0'          port = '12345'          privkey = 'OOjcXGfgQlAuM6q8Z9aAYduCua7pxf7UKYvIqoUPoGQ=' @@ -129,5 +129,28 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase):          self.assertTrue(os.path.isdir(f'/sys/class/net/{interface}')) +    def test_04_wireguard_threaded(self): +        # T5409: Test adding threaded option on interface. +        #        Test prevention for adding threaded +        #        if no enabled peer is configured. +        interface = 'wg0' +        port = '12345' +        privkey = 'OOjcXGfgQlAuM6q8Z9aAYduCua7pxf7UKYvIqoUPoGQ=' +        pubkey = 'ebFx/1G0ti8tvuZd94sEIosAZZIznX+dBAKG/8DFm0I=' + +        self.cli_set(base_path + [interface, 'address', '172.16.0.1/24']) +        self.cli_set(base_path + [interface, 'private-key', privkey]) + +        self.cli_set(base_path + [interface, 'peer', 'PEER01', 'port', port]) +        self.cli_set(base_path + [interface, 'peer', 'PEER01', 'public-key', pubkey]) +        self.cli_set(base_path + [interface, 'peer', 'PEER01', 'allowed-ips', '10.205.212.10/32']) +        self.cli_set(base_path + [interface, 'peer', 'PEER01', 'address', '192.0.2.1']) +        self.cli_set(base_path + [interface, 'per-client-thread']) + +        # Commit peers +        self.cli_commit() +        tmp = read_file(f'/sys/class/net/{interface}/threaded') +        self.assertTrue(tmp, "1") +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 446399255..122d9589a 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -90,7 +90,6 @@ def verify(wireguard):      # run checks on individual configured WireGuard peer      public_keys = [] -      for tmp in wireguard['peer']:          peer = wireguard['peer'][tmp] @@ -107,8 +106,9 @@ def verify(wireguard):          if peer['public_key'] in public_keys:              raise ConfigError(f'Duplicate public-key defined on peer "{tmp}"') -        if 'disable' not in peer and is_wireguard_key_pair(wireguard['private_key'], peer['public_key']): -            raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"') +        if 'disable' not in peer: +            if is_wireguard_key_pair(wireguard['private_key'], peer['public_key']): +                raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"')          public_keys.append(peer['public_key']) | 
