summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/bgpd.frr.j24
-rw-r--r--interface-definitions/include/bgp/afi-redistribute-common-protocols.xml.i8
-rw-r--r--interface-definitions/include/version/bgp-version.xml.i2
-rw-r--r--python/vyos/ifconfig/wireguard.py78
-rw-r--r--smoketest/config-tests/bgp-rpki1
-rw-r--r--smoketest/configs/bgp-rpki7
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py76
-rwxr-xr-xsmoketest/scripts/cli/test_service_ipoe-server.py22
-rwxr-xr-xsrc/conf_mode/system_sflow.py2
-rwxr-xr-xsrc/etc/netplug/vyos-netplug-dhcp-client13
-rw-r--r--src/migration-scripts/bgp/5-to-639
-rwxr-xr-xsrc/services/vyos-domain-resolver12
12 files changed, 232 insertions, 32 deletions
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index 2f3719fdf..3b462b4a9 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -310,8 +310,8 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if afi_config.redistribute is vyos_defined %}
{% for protocol, protocol_config in afi_config.redistribute.items() %}
{% if protocol == 'table' %}
-{% for table in protocol_config %}
- redistribute table-direct {{ table }}
+{% for table, table_config in protocol_config.items() %}
+ redistribute table-direct {{ table }} {{ 'metric ' ~ table_config.metric if table_config.metric is vyos_defined }} {{ 'route-map ' ~ table_config.route_map if table_config.route_map is vyos_defined }}
{% endfor %}
{% else %}
{% set redistribution_protocol = protocol %}
diff --git a/interface-definitions/include/bgp/afi-redistribute-common-protocols.xml.i b/interface-definitions/include/bgp/afi-redistribute-common-protocols.xml.i
index f4d18bc70..141a704c7 100644
--- a/interface-definitions/include/bgp/afi-redistribute-common-protocols.xml.i
+++ b/interface-definitions/include/bgp/afi-redistribute-common-protocols.xml.i
@@ -39,14 +39,16 @@
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
-<leafNode name="table">
+<tagNode name="table">
<properties>
<help>Redistribute non-main Kernel Routing Table</help>
<completionHelp>
<path>protocols static table</path>
</completionHelp>
#include <include/constraint/protocols-static-table.xml.i>
- <multi/>
</properties>
-</leafNode>
+ <children>
+ #include <include/bgp/afi-redistribute-metric-route-map.xml.i>
+ </children>
+</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i
index 6bed7189f..c90276151 100644
--- a/interface-definitions/include/version/bgp-version.xml.i
+++ b/interface-definitions/include/version/bgp-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/bgp-version.xml.i -->
-<syntaxVersion component='bgp' version='5'></syntaxVersion>
+<syntaxVersion component='bgp' version='6'></syntaxVersion>
<!-- include end -->
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index fed7a5f84..be9bffd20 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -77,6 +77,84 @@ class WireGuardOperational(Operational):
}
return output
+ def show_interface(self):
+ from vyos.config import Config
+
+ c = Config()
+
+ wgdump = self._dump().get(self.config['ifname'], None)
+
+ c.set_level(['interfaces', 'wireguard', self.config['ifname']])
+ description = c.return_effective_value(['description'])
+ ips = c.return_effective_values(['address'])
+ hostnames = c.return_effective_values(['host-name'])
+
+ answer = 'interface: {}\n'.format(self.config['ifname'])
+ if description:
+ answer += ' description: {}\n'.format(description)
+ if ips:
+ answer += ' address: {}\n'.format(', '.join(ips))
+ if hostnames:
+ answer += ' hostname: {}\n'.format(', '.join(hostnames))
+
+ answer += ' public key: {}\n'.format(wgdump['public_key'])
+ answer += ' private key: (hidden)\n'
+ answer += ' listening port: {}\n'.format(wgdump['listen_port'])
+ answer += '\n'
+
+ for peer in c.list_effective_nodes(['peer']):
+ if wgdump['peers']:
+ pubkey = c.return_effective_value(['peer', peer, 'public-key'])
+ if pubkey in wgdump['peers']:
+ wgpeer = wgdump['peers'][pubkey]
+
+ answer += ' peer: {}\n'.format(peer)
+ answer += ' public key: {}\n'.format(pubkey)
+
+ """ figure out if the tunnel is recently active or not """
+ status = 'inactive'
+ if wgpeer['latest_handshake'] is None:
+ """ no handshake ever """
+ status = 'inactive'
+ else:
+ if int(wgpeer['latest_handshake']) > 0:
+ delta = timedelta(
+ seconds=int(time.time() - wgpeer['latest_handshake'])
+ )
+ answer += ' latest handshake: {}\n'.format(delta)
+ if time.time() - int(wgpeer['latest_handshake']) < (60 * 5):
+ """ Five minutes and the tunnel is still active """
+ status = 'active'
+ else:
+ """ it's been longer than 5 minutes """
+ status = 'inactive'
+ elif int(wgpeer['latest_handshake']) == 0:
+ """ no handshake ever """
+ status = 'inactive'
+ answer += ' status: {}\n'.format(status)
+
+ if wgpeer['endpoint'] is not None:
+ answer += ' endpoint: {}\n'.format(wgpeer['endpoint'])
+
+ if wgpeer['allowed_ips'] is not None:
+ answer += ' allowed ips: {}\n'.format(
+ ','.join(wgpeer['allowed_ips']).replace(',', ', ')
+ )
+
+ if wgpeer['transfer_rx'] > 0 or wgpeer['transfer_tx'] > 0:
+ rx_size = size(wgpeer['transfer_rx'], system=alternative)
+ tx_size = size(wgpeer['transfer_tx'], system=alternative)
+ answer += ' transfer: {} received, {} sent\n'.format(
+ rx_size, tx_size
+ )
+
+ if wgpeer['persistent_keepalive'] is not None:
+ answer += ' persistent keepalive: every {} seconds\n'.format(
+ wgpeer['persistent_keepalive']
+ )
+ answer += '\n'
+ return answer
+
def get_latest_handshakes(self):
"""Get latest handshake time for each peer"""
output = {}
diff --git a/smoketest/config-tests/bgp-rpki b/smoketest/config-tests/bgp-rpki
index 587de67c6..657d4abcc 100644
--- a/smoketest/config-tests/bgp-rpki
+++ b/smoketest/config-tests/bgp-rpki
@@ -13,6 +13,7 @@ set policy route-map ebgp-transit-rpki rule 30 set local-preference '100'
set policy route-map ebgp-transit-rpki rule 40 action 'permit'
set policy route-map ebgp-transit-rpki rule 40 set extcommunity rt '192.0.2.100:100'
set policy route-map ebgp-transit-rpki rule 40 set extcommunity soo '64500:100'
+set protocols bgp address-family ipv4-unicast redistribute table 100
set protocols bgp neighbor 1.2.3.4 address-family ipv4-unicast nexthop-self
set protocols bgp neighbor 1.2.3.4 address-family ipv4-unicast route-map import 'ebgp-transit-rpki'
set protocols bgp neighbor 1.2.3.4 remote-as '10'
diff --git a/smoketest/configs/bgp-rpki b/smoketest/configs/bgp-rpki
index 5588f15c9..2d136d545 100644
--- a/smoketest/configs/bgp-rpki
+++ b/smoketest/configs/bgp-rpki
@@ -46,6 +46,13 @@ policy {
}
protocols {
bgp 64500 {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ table 100
+ }
+ }
+ }
neighbor 1.2.3.4 {
address-family {
ipv4-unicast {
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 0eda52ff6..0c6d36213 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2024 VyOS maintainers and contributors
+# Copyright (C) 2021-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
@@ -685,14 +685,30 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
'route_map' : 'redistr-ipv4-static',
},
'table' : {
- 'number' : ['10', '20', '30', '40'],
+ '10' : {
+ 'metric' : '810',
+ 'route_map' : 'redistr-ipv4-table-10',
+ },
+ '20' : {
+ 'metric' : '820',
+ 'route_map' : 'redistr-ipv4-table-20',
+ },
+ '30' : {
+ 'metric' : '830',
+ 'route_map' : 'redistr-ipv4-table-30',
+ },
},
}
for proto, proto_config in redistributes.items():
proto_path = base_path + ['address-family', 'ipv4-unicast', 'redistribute', proto]
- if proto == 'table' and 'number' in proto_config:
- for number in proto_config['number']:
- self.cli_set(proto_path, value=number)
+ if proto == 'table':
+ for table, table_config in proto_config.items():
+ self.cli_set(proto_path + [table])
+ if 'metric' in table_config:
+ self.cli_set(proto_path + [table, 'metric'], value=table_config['metric'])
+ if 'route_map' in table_config:
+ self.cli_set(['policy', 'route-map', table_config['route_map'], 'rule', '10', 'action'], value='permit')
+ self.cli_set(proto_path + [table, 'route-map'], value=table_config['route_map'])
else:
self.cli_set(proto_path)
if 'metric' in proto_config:
@@ -723,9 +739,16 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(' address-family ipv4 unicast', frrconfig)
for proto, proto_config in redistributes.items():
- if proto == 'table' and 'number' in proto_config:
- for number in proto_config['number']:
- self.assertIn(f' redistribute table-direct {number}', frrconfig)
+ if proto == 'table':
+ for table, table_config in proto_config.items():
+ tmp = f' redistribute table-direct {table}'
+ if 'metric' in proto_config:
+ metric = proto_config['metric']
+ tmp += f' metric {metric}'
+ if 'route_map' in proto_config:
+ route_map = proto_config['route_map']
+ tmp += f' route-map {route_map}'
+ self.assertIn(tmp, frrconfig)
else:
tmp = f' redistribute {proto}'
if 'metric' in proto_config:
@@ -794,14 +817,30 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
'route_map' : 'redistr-ipv6-static',
},
'table' : {
- 'number' : ['100', '120', '130', '140'],
+ '110' : {
+ 'metric' : '811',
+ 'route_map' : 'redistr-ipv6-table-110',
+ },
+ '120' : {
+ 'metric' : '821',
+ 'route_map' : 'redistr-ipv6-table-120',
+ },
+ '130' : {
+ 'metric' : '831',
+ 'route_map' : 'redistr-ipv6-table-130',
+ },
},
}
for proto, proto_config in redistributes.items():
proto_path = base_path + ['address-family', 'ipv6-unicast', 'redistribute', proto]
- if proto == 'table' and 'number' in proto_config:
- for number in proto_config['number']:
- self.cli_set(proto_path, value=number)
+ if proto == 'table':
+ for table, table_config in proto_config.items():
+ self.cli_set(proto_path + [table])
+ if 'metric' in table_config:
+ self.cli_set(proto_path + [table, 'metric'], value=table_config['metric'])
+ if 'route_map' in table_config:
+ self.cli_set(['policy', 'route-map', table_config['route_map'], 'rule', '10', 'action'], value='permit')
+ self.cli_set(proto_path + [table, 'route-map'], value=table_config['route_map'])
else:
self.cli_set(proto_path)
if 'metric' in proto_config:
@@ -829,9 +868,16 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(' no bgp ebgp-requires-policy', frrconfig)
for proto, proto_config in redistributes.items():
- if proto == 'table' and 'number' in proto_config:
- for number in proto_config['number']:
- self.assertIn(f' redistribute table-direct {number}', frrconfig)
+ if proto == 'table':
+ for table, table_config in proto_config.items():
+ tmp = f' redistribute table-direct {table}'
+ if 'metric' in proto_config:
+ metric = proto_config['metric']
+ tmp += f' metric {metric}'
+ if 'route_map' in proto_config:
+ route_map = proto_config['route_map']
+ tmp += f' route-map {route_map}'
+ self.assertIn(tmp, frrconfig)
else:
# FRR calls this OSPF6
if proto == 'ospfv3':
diff --git a/smoketest/scripts/cli/test_service_ipoe-server.py b/smoketest/scripts/cli/test_service_ipoe-server.py
index ab0898d17..67e8ca93f 100755
--- a/smoketest/scripts/cli/test_service_ipoe-server.py
+++ b/smoketest/scripts/cli/test_service_ipoe-server.py
@@ -295,6 +295,28 @@ delegate={delegate_2_prefix},{delegate_mask},name={pool_name}"""
tmp = re.findall(regex, tmp)
self.assertTrue(tmp)
+ def test_ipoe_server_start_session(self):
+ start_session = 'auto'
+
+ # Configuration of local authentication for PPPoE server
+ self.basic_config()
+ self.cli_commit()
+
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=', strict=False)
+ conf.read(self._config_file)
+ # if 'start-session' option is not set the default value is 'dhcp'
+ self.assertIn(f'start=dhcpv4', conf['ipoe']['interface'])
+
+ # change 'start-session' option to 'auto'
+ self.set(['interface', interface, 'start-session', start_session])
+ self.cli_commit()
+
+ # Validate changed configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=', strict=False)
+ conf.read(self._config_file)
+ self.assertIn(f'start={start_session}', conf['ipoe']['interface'])
+
@unittest.skip("PPP is not a part of IPoE")
def test_accel_ppp_options(self):
pass
diff --git a/src/conf_mode/system_sflow.py b/src/conf_mode/system_sflow.py
index 41119b494..a22dac36f 100755
--- a/src/conf_mode/system_sflow.py
+++ b/src/conf_mode/system_sflow.py
@@ -54,7 +54,7 @@ def verify(sflow):
# Check if configured sflow agent-address exist in the system
if 'agent_address' in sflow:
tmp = sflow['agent_address']
- if not is_addr_assigned(tmp):
+ if not is_addr_assigned(tmp, include_vrf=True):
raise ConfigError(
f'Configured "sflow agent-address {tmp}" does not exist in the system!'
)
diff --git a/src/etc/netplug/vyos-netplug-dhcp-client b/src/etc/netplug/vyos-netplug-dhcp-client
index 83fed70f0..4cc824afd 100755
--- a/src/etc/netplug/vyos-netplug-dhcp-client
+++ b/src/etc/netplug/vyos-netplug-dhcp-client
@@ -19,21 +19,22 @@ import sys
from time import sleep
-from vyos.configquery import ConfigTreeQuery
+from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.ifconfig import Interface
from vyos.ifconfig import Section
from vyos.utils.boot import boot_configuration_complete
from vyos.utils.commit import commit_in_progress
from vyos import airbag
+
airbag.enable()
if len(sys.argv) < 3:
- airbag.noteworthy("Must specify both interface and link status!")
+ airbag.noteworthy('Must specify both interface and link status!')
sys.exit(1)
if not boot_configuration_complete():
- airbag.noteworthy("System bootup not yet finished...")
+ airbag.noteworthy('System bootup not yet finished...')
sys.exit(1)
interface = sys.argv[1]
@@ -47,8 +48,10 @@ while commit_in_progress():
sleep(1)
in_out = sys.argv[2]
-config = ConfigTreeQuery()
+config = Config()
interface_path = ['interfaces'] + Section.get_config_path(interface).split()
-_, interface_config = get_interface_dict(config, interface_path[:-1], ifname=interface, with_pki=True)
+_, interface_config = get_interface_dict(
+ config, interface_path[:-1], ifname=interface, with_pki=True
+)
Interface(interface).update(interface_config)
diff --git a/src/migration-scripts/bgp/5-to-6 b/src/migration-scripts/bgp/5-to-6
new file mode 100644
index 000000000..e6fea6574
--- /dev/null
+++ b/src/migration-scripts/bgp/5-to-6
@@ -0,0 +1,39 @@
+# 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/>.
+
+# T7163: migrate "address-family ipv4|6-unicast redistribute table" from a multi
+# leafNode to a tagNode. This is needed to support per table definition of a
+# route-map and/or metric
+
+from vyos.configtree import ConfigTree
+
+def migrate(config: ConfigTree) -> None:
+ bgp_base = ['protocols', 'bgp']
+ if not config.exists(bgp_base):
+ return
+
+ for address_family in ['ipv4-unicast', 'ipv6-unicast']:
+ # there is no non-main routing table beeing redistributed under this addres family
+ # bail out early and continue with next AFI
+ table_path = bgp_base + ['address-family', address_family, 'redistribute', 'table']
+ if not config.exists(table_path):
+ continue
+
+ tables = config.return_values(table_path)
+ config.delete(table_path)
+
+ for table in tables:
+ config.set(table_path + [table])
+ config.set_tag(table_path)
diff --git a/src/services/vyos-domain-resolver b/src/services/vyos-domain-resolver
index bfc8caa0a..48c6b86d8 100755
--- a/src/services/vyos-domain-resolver
+++ b/src/services/vyos-domain-resolver
@@ -65,13 +65,15 @@ def get_config(conf, node):
node_config = dict_merge(default_values, node_config)
- global timeout, cache
+ if node == base_firewall and 'global_options' in node_config:
+ global_config = node_config['global_options']
+ global timeout, cache
- if 'resolver_interval' in node_config:
- timeout = int(node_config['resolver_interval'])
+ if 'resolver_interval' in global_config:
+ timeout = int(global_config['resolver_interval'])
- if 'resolver_cache' in node_config:
- cache = True
+ if 'resolver_cache' in global_config:
+ cache = True
fqdn_config_parse(node_config, node[0])