diff options
| author | Nataliia Solomko <natalirs1985@gmail.com> | 2026-06-22 18:58:14 +0300 |
|---|---|---|
| committer | Nataliia Solomko <natalirs1985@gmail.com> | 2026-06-24 11:37:16 +0300 |
| commit | 68cb83099e4f71d60019eacca88c8892a4247d01 (patch) | |
| tree | 291e77ae8f8f28d165e4d9c49fb1db83b81985b3 | |
| parent | 02f8c17a56518157e48048fb39b69f373ee9c829 (diff) | |
| download | vyos-1x-68cb83099e4f71d60019eacca88c8892a4247d01.tar.gz vyos-1x-68cb83099e4f71d60019eacca88c8892a4247d01.zip | |
T9011: enable proxy_ndp sysctl for static IPv6 neighbor proxy
| -rw-r--r-- | smoketest/scripts/cli/test_protocols_static_neighbor-proxy.py | 90 | ||||
| -rwxr-xr-x | src/conf_mode/protocols_static_neighbor-proxy.py | 29 |
2 files changed, 117 insertions, 2 deletions
diff --git a/smoketest/scripts/cli/test_protocols_static_neighbor-proxy.py b/smoketest/scripts/cli/test_protocols_static_neighbor-proxy.py new file mode 100644 index 000000000..beed3156c --- /dev/null +++ b/smoketest/scripts/cli/test_protocols_static_neighbor-proxy.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# +# Copyright VyOS maintainers and contributors <maintainers@vyos.io> +# +# 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +import unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.utils.system import sysctl_read +from vyos.utils.process import cmd + +base_path = ['protocols', 'static', 'neighbor-proxy'] +interface = 'eth0' + + +class TestProtocolsStaticNeighborProxy(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestProtocolsStaticNeighborProxy, cls).setUpClass() + cls.cli_delete(cls, base_path) + + def tearDown(self): + self.cli_delete(base_path) + self.cli_commit() + super().tearDown() + + def test_arp_proxy(self): + address = '192.0.2.1/24' + neighbor = '192.0.2.10' + + self.cli_set(['interfaces', 'ethernet', interface, 'address', address]) + self.cli_set(base_path + ['arp', neighbor, 'interface', interface]) + self.cli_commit() + + proxy_entries = cmd('ip -4 neigh show proxy') + self.assertIn(f'{neighbor} dev {interface} proxy', proxy_entries) + + self.cli_delete(['interfaces', 'ethernet', interface, 'address', address]) + + def test_nd_proxy(self): + address = 'fd00::1/64' + neighbor = 'fd00::99' + interface2 = 'eth1' + + self.cli_set(['interfaces', 'ethernet', interface, 'address', address]) + # Add ND proxy on two interfaces + self.cli_set(base_path + ['nd', neighbor, 'interface', interface]) + self.cli_set(base_path + ['nd', neighbor, 'interface', interface2]) + self.cli_commit() + + # Verify proxy entries are installed + proxy_entries = cmd('ip -6 neigh show proxy') + for iface in [interface, interface2]: + self.assertIn(f'{neighbor} dev {iface} proxy', proxy_entries) + # Verify proxy_ndp sysctl is enabled on both interfaces + self.assertEqual( + sysctl_read(['net', 'ipv6', 'conf', iface, 'proxy_ndp']), '1' + ) + + # Remove one interface + self.cli_delete(base_path + ['nd', neighbor, 'interface', interface2]) + self.cli_commit() + + # First interface still enabled + self.assertEqual( + sysctl_read(['net', 'ipv6', 'conf', interface, 'proxy_ndp']), '1' + ) + # Removed interface disabled + self.assertEqual( + sysctl_read(['net', 'ipv6', 'conf', interface2, 'proxy_ndp']), '0' + ) + + self.cli_delete(['interfaces', 'ethernet', interface, 'address', address]) + + +if __name__ == '__main__': + unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) diff --git a/src/conf_mode/protocols_static_neighbor-proxy.py b/src/conf_mode/protocols_static_neighbor-proxy.py index bda737e75..0c8fd8483 100755 --- a/src/conf_mode/protocols_static_neighbor-proxy.py +++ b/src/conf_mode/protocols_static_neighbor-proxy.py @@ -17,11 +17,16 @@ from sys import exit from vyos.config import Config +from vyos.configdict import leaf_node_changed +from vyos.configdict import node_changed from vyos.utils.process import call +from vyos.utils.system import sysctl_write from vyos import ConfigError from vyos import airbag + airbag.enable() + def get_config(config=None): if config: conf = config @@ -31,8 +36,19 @@ def get_config(config=None): base = ['protocols', 'static', 'neighbor-proxy'] config = conf.get_config_dict(base, get_first_key=True) + if not config: + config = {'deleted': True} + + removed_nd_interfaces = set() + for neighbor in node_changed(conf, base + ['nd'], recursive=True): + tmp = leaf_node_changed(conf, base + ['nd', neighbor, 'interface']) + if tmp: + removed_nd_interfaces.update(tmp) + config['removed_nd_interfaces'] = removed_nd_interfaces + return config + def verify(config): if 'arp' in config: for neighbor, neighbor_conf in config['arp'].items(): @@ -45,14 +61,21 @@ def verify(config): for neighbor, neighbor_conf in config['nd'].items(): if 'interface' not in neighbor_conf: raise ConfigError( - f"ARP neighbor-proxy for '{neighbor}' requires an interface to be set!" + f"NDP neighbor-proxy for '{neighbor}' requires an interface to be set!" ) + def generate(config): pass + def apply(config): - if not config: + # Disable proxy_ndp on interfaces removed from config + removed_nd_interfaces = config.pop('removed_nd_interfaces', set()) + for iface in removed_nd_interfaces: + sysctl_write(['net', 'ipv6', 'conf', iface, 'proxy_ndp'], 0) + + if 'deleted' in config: # Cleanup proxy call('ip neighbor flush proxy') call('ip -6 neighbor flush proxy') @@ -73,6 +96,8 @@ def apply(config): for neighbor, neighbor_conf in config['nd'].items(): for interface in neighbor_conf['interface']: call(f'ip -6 neighbor add proxy {neighbor} dev {interface}') + sysctl_write(['net', 'ipv6', 'conf', interface, 'proxy_ndp'], 1) + if __name__ == '__main__': try: |
