diff options
author | Christian Breunig <christian@breunig.cc> | 2025-02-24 20:54:25 +0100 |
---|---|---|
committer | Christian Breunig <christian@breunig.cc> | 2025-02-24 20:54:25 +0100 |
commit | 216e80b61881a13c502f44c5d32fd7603b6ffe60 (patch) | |
tree | 08a92ec479f854e0e098fb4e54d1cb8b7a46ea22 | |
parent | 5d9d232fd93ad5bf89ba44a2d0ec3b196599fa74 (diff) | |
download | vyos-1x-216e80b61881a13c502f44c5d32fd7603b6ffe60.tar.gz vyos-1x-216e80b61881a13c502f44c5d32fd7603b6ffe60.zip |
lldp: T7165: add support to enable only rx or tx on specific interface
LLDP is a stateless protocol which does not necessitate sending to receive
advertisements. There are multiple scenarios such as provider peering links in
which it is advantageous to receive LLDP but not disclose internal information
to the provider.
Add new CLI command:
* set service lldp interface <name> mode [disable|rx-tx|rx|tx]
The default is unchanged and will be rx-tx.
Furthermore if an interface has an explicit LLDP disable configured under
"set service lldp interface <name> disable" this will be migrated to
"set service lldp interface <name> mode disable"
-rw-r--r-- | data/templates/lldp/vyos.conf.j2 | 11 | ||||
-rw-r--r-- | interface-definitions/include/version/lldp-version.xml.i | 2 | ||||
-rw-r--r-- | interface-definitions/service_lldp.xml.in | 29 | ||||
-rw-r--r-- | smoketest/config-tests/dialup-router-complex | 1 | ||||
-rw-r--r-- | smoketest/config-tests/nat-basic | 2 | ||||
-rw-r--r-- | smoketest/configs/dialup-router-complex | 3 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_lldp.py | 49 | ||||
-rw-r--r-- | src/migration-scripts/lldp/2-to-3 | 31 |
8 files changed, 123 insertions, 5 deletions
diff --git a/data/templates/lldp/vyos.conf.j2 b/data/templates/lldp/vyos.conf.j2 index 4b4228cea..432a7a8e6 100644 --- a/data/templates/lldp/vyos.conf.j2 +++ b/data/templates/lldp/vyos.conf.j2 @@ -4,7 +4,7 @@ configure system platform VyOS configure system description "VyOS {{ version }}" {% if interface is vyos_defined %} {% set tmp = [] %} -{% for iface, iface_options in interface.items() if iface_options.disable is not vyos_defined %} +{% for iface, iface_options in interface.items() %} {% if iface == 'all' %} {% set iface = '*' %} {% endif %} @@ -17,6 +17,15 @@ configure ports {{ iface }} med location elin "{{ iface_options.location.elin }} configure ports {{ iface }} med location coordinate latitude "{{ iface_options.location.coordinate_based.latitude }}" longitude "{{ iface_options.location.coordinate_based.longitude }}" altitude "{{ iface_options.location.coordinate_based.altitude }}m" datum "{{ iface_options.location.coordinate_based.datum }}" {% endif %} {% endif %} +{% set mode = iface_options.mode %} +{% if mode == 'tx' %} +{% set mode = 'tx-only' %} +{% elif mode == 'rx' %} +{% set mode = 'rx-only' %} +{% elif mode == 'rx-tx' %} +{% set mode = 'rx-and-tx' %} +{% endif %} +configure ports {{ iface }} lldp status {{ mode }} {% endfor %} configure system interface pattern "{{ tmp | join(",") }}" {% endif %} diff --git a/interface-definitions/include/version/lldp-version.xml.i b/interface-definitions/include/version/lldp-version.xml.i index b41d80451..a7110691a 100644 --- a/interface-definitions/include/version/lldp-version.xml.i +++ b/interface-definitions/include/version/lldp-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/lldp-version.xml.i --> -<syntaxVersion component='lldp' version='2'></syntaxVersion> +<syntaxVersion component='lldp' version='3'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/service_lldp.xml.in b/interface-definitions/service_lldp.xml.in index 51a9f9cce..a189cc13b 100644 --- a/interface-definitions/service_lldp.xml.in +++ b/interface-definitions/service_lldp.xml.in @@ -29,7 +29,34 @@ </constraint> </properties> <children> - #include <include/generic-disable-node.xml.i> + <leafNode name="mode"> + <properties> + <help>Set LLDP receive/transmit operation mode of this interface</help> + <completionHelp> + <list>disable rx-tx tx rx</list> + </completionHelp> + <valueHelp> + <format>disable</format> + <description>Do not process or send LLDP messages</description> + </valueHelp> + <valueHelp> + <format>rx-tx</format> + <description>Send and process LLDP messages</description> + </valueHelp> + <valueHelp> + <format>rx</format> + <description>Process incoming LLDP messages</description> + </valueHelp> + <valueHelp> + <format>tx</format> + <description>Send LLDP messages</description> + </valueHelp> + <constraint> + <regex>(disable|rx-tx|tx|rx)</regex> + </constraint> + </properties> + <defaultValue>rx-tx</defaultValue> + </leafNode> <node name="location"> <properties> <help>LLDP-MED location data</help> diff --git a/smoketest/config-tests/dialup-router-complex b/smoketest/config-tests/dialup-router-complex index c356c73c0..12edcfef2 100644 --- a/smoketest/config-tests/dialup-router-complex +++ b/smoketest/config-tests/dialup-router-complex @@ -695,6 +695,7 @@ set service dns forwarding ignore-hosts-file set service dns forwarding listen-address '172.16.254.30' set service dns forwarding listen-address '172.31.0.254' set service dns forwarding negative-ttl '60' +set service lldp interface pppoe0 mode 'disable' set service lldp legacy-protocols cdp set service lldp snmp set service mdns repeater interface 'eth0.35' diff --git a/smoketest/config-tests/nat-basic b/smoketest/config-tests/nat-basic index ba2b1b838..f1cc0121d 100644 --- a/smoketest/config-tests/nat-basic +++ b/smoketest/config-tests/nat-basic @@ -60,7 +60,7 @@ set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 range 0 set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 range 0 stop '192.168.189.254' set service dhcp-server shared-network-name LAN subnet 192.168.189.0/24 subnet-id '1' set service lldp interface all -set service lldp interface eth1 disable +set service lldp interface eth1 mode 'disable' set service ntp allow-client address '192.168.189.0/24' set service ntp listen-address '192.168.189.1' set service ntp server time1.vyos.net diff --git a/smoketest/configs/dialup-router-complex b/smoketest/configs/dialup-router-complex index aa9837fe9..018379bcd 100644 --- a/smoketest/configs/dialup-router-complex +++ b/smoketest/configs/dialup-router-complex @@ -1392,6 +1392,9 @@ service { } } lldp { + interface pppoe0 { + disable + } legacy-protocols { cdp } diff --git a/smoketest/scripts/cli/test_service_lldp.py b/smoketest/scripts/cli/test_service_lldp.py index 9d72ef78f..c73707e0d 100755 --- a/smoketest/scripts/cli/test_service_lldp.py +++ b/smoketest/scripts/cli/test_service_lldp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022-2024 VyOS maintainers and contributors +# Copyright (C) 2022-2025 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 @@ -117,6 +117,8 @@ class TestServiceLLDP(VyOSUnitTestSHIM.TestCase): config = read_file(LLDPD_CONF) self.assertIn(f'configure ports {interface} med location elin "{elin}"', config) + # This is the CLI default mode + self.assertIn(f'configure ports {interface} lldp status rx-and-tx', config) self.assertIn(f'configure system interface pattern "{interface}"', config) def test_06_lldp_snmp(self): @@ -134,5 +136,50 @@ class TestServiceLLDP(VyOSUnitTestSHIM.TestCase): self.cli_delete(['service', 'snmp']) + def test_07_lldp_interface_mode(self): + interfaces = Section.interfaces('ethernet', vlan=False) + + # set interface mode to 'tx' + self.cli_set(base_path + ['interface', 'all']) + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'mode', 'disable']) + # commit changes + self.cli_commit() + + # verify configuration + config = read_file(LLDPD_CONF) + for interface in interfaces: + self.assertIn(f'configure ports {interface} lldp status disable', config) + + # Change configuration to rx-only + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'mode', 'rx']) + # commit changes + self.cli_commit() + # verify configuration + config = read_file(LLDPD_CONF) + for interface in interfaces: + self.assertIn(f'configure ports {interface} lldp status rx-only', config) + + # Change configuration to tx-only + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'mode', 'tx']) + # commit changes + self.cli_commit() + # verify configuration + config = read_file(LLDPD_CONF) + for interface in interfaces: + self.assertIn(f'configure ports {interface} lldp status tx-only', config) + + # Change configuration to rx-only + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'mode', 'rx-tx']) + # commit changes + self.cli_commit() + # verify configuration + config = read_file(LLDPD_CONF) + for interface in interfaces: + self.assertIn(f'configure ports {interface} lldp status rx-and-tx', config) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/migration-scripts/lldp/2-to-3 b/src/migration-scripts/lldp/2-to-3 new file mode 100644 index 000000000..93090756c --- /dev/null +++ b/src/migration-scripts/lldp/2-to-3 @@ -0,0 +1,31 @@ +# Copyright 2025 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +# T7165: Migrate LLDP interface disable to 'mode disable' + +from vyos.configtree import ConfigTree + +base = ['service', 'lldp'] + +def migrate(config: ConfigTree) -> None: + interface_base = base + ['interface'] + if not config.exists(interface_base): + # Nothing to do + return + + for interface in config.list_nodes(interface_base): + if config.exists(interface_base + [interface, 'disable']): + config.delete(interface_base + [interface, 'disable']) + config.set(interface_base + [interface, 'mode'], value='disable') |