summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2025-02-24 20:54:25 +0100
committerChristian Breunig <christian@breunig.cc>2025-02-24 20:54:25 +0100
commit216e80b61881a13c502f44c5d32fd7603b6ffe60 (patch)
tree08a92ec479f854e0e098fb4e54d1cb8b7a46ea22
parent5d9d232fd93ad5bf89ba44a2d0ec3b196599fa74 (diff)
downloadvyos-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.j211
-rw-r--r--interface-definitions/include/version/lldp-version.xml.i2
-rw-r--r--interface-definitions/service_lldp.xml.in29
-rw-r--r--smoketest/config-tests/dialup-router-complex1
-rw-r--r--smoketest/config-tests/nat-basic2
-rw-r--r--smoketest/configs/dialup-router-complex3
-rwxr-xr-xsmoketest/scripts/cli/test_service_lldp.py49
-rw-r--r--src/migration-scripts/lldp/2-to-331
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')