From 8a75a0ea52f24b27ef0b4e50dc91e4144bcca059 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Thu, 30 Mar 2023 08:51:15 +0000 Subject: T4173: Fix smoketest for load-balancing wan Counter jump WANLOADBALANCE was deleted in the commit https://github.com/vyos/vyos-1x/commit/27ca5b9d6d699e201f88ffff41b0a651166b65eb I guess it was done to pass the smoketest even if it broke the load-balance wan feature Fix it --- smoketest/scripts/cli/test_load_balancing_wan.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smoketest/scripts/cli/test_load_balancing_wan.py b/smoketest/scripts/cli/test_load_balancing_wan.py index 0e1806f66..8df3471f7 100755 --- a/smoketest/scripts/cli/test_load_balancing_wan.py +++ b/smoketest/scripts/cli/test_load_balancing_wan.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-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 @@ -177,7 +177,7 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase): nat_vyos_pre_snat_hook = """table ip nat { chain VYOS_PRE_SNAT_HOOK { type nat hook postrouting priority srcnat - 1; policy accept; - return + counter jump WANLOADBALANCE } }""" -- cgit v1.2.3 From a78982625a8a18069bd5a13744734873698fd0f9 Mon Sep 17 00:00:00 2001 From: aapostoliuk Date: Thu, 30 Mar 2023 18:28:56 +0300 Subject: ipsec: T5093: Fixed 'reset vpn ipsec profile' command Fixed 'reset vpn ipsec profile' command using vici library and new op-mode style. Added ability to use 'reset vpn ipsec profile' command with 'remote-host' option. --- op-mode-definitions/vpn-ipsec.xml.in | 19 +++++++-- python/vyos/ipsec.py | 38 +++++++++++++++++ src/completion/list_ipsec_profile_tunnels.py | 48 +++++++++++++++++++++ src/op_mode/ipsec.py | 62 ++++++++++++++++++++++++++++ src/op_mode/vpn_ipsec.py | 61 ++------------------------- 5 files changed, 168 insertions(+), 60 deletions(-) create mode 100644 src/completion/list_ipsec_profile_tunnels.py diff --git a/op-mode-definitions/vpn-ipsec.xml.in b/op-mode-definitions/vpn-ipsec.xml.in index 5baaec7ce..5a7e6dd63 100644 --- a/op-mode-definitions/vpn-ipsec.xml.in +++ b/op-mode-definitions/vpn-ipsec.xml.in @@ -14,7 +14,7 @@ - Reset all tunnels for given DMVPN profile + Reset a specific tunnel for given DMVPN profile vpn ipsec profile @@ -23,11 +23,24 @@ Reset a specific tunnel for given DMVPN profile + + + - sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$6" --tunnel="$8" + + + + Reset a specific tunnel for given DMVPN NBMA + + <x.x.x.x> <h:h:h:h:h:h:h:h> + + + sudo ${vyos_op_scripts_dir}/ipsec.py reset_profile_dst --profile="$5" --tunnel="$7" --nbma_dst="$9" + + + sudo ${vyos_op_scripts_dir}/ipsec.py reset_profile_all --profile="$5" --tunnel="$7" - sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$6" --tunnel="all" diff --git a/python/vyos/ipsec.py b/python/vyos/ipsec.py index cb7c39ff6..bb5611025 100644 --- a/python/vyos/ipsec.py +++ b/python/vyos/ipsec.py @@ -139,3 +139,41 @@ def terminate_vici_by_name(ike_name: str, child_name: str) -> None: else: raise ViciCommandError( f'Failed to terminate SA for IKE {ike_name}') + + +def vici_initiate(ike_sa_name: str, child_sa_name: str, src_addr: str, + dst_addr: str) -> bool: + """Initiate IKE SA connection with specific peer + + Args: + ike_sa_name (str): an IKE SA connection name + child_sa_name (str): a child SA profile name + src_addr (str): source address + dst_addr (str): remote address + + Returns: + bool: a result of initiation command + """ + from vici import Session as vici_session + + try: + session = vici_session() + except Exception: + raise ViciInitiateError("IPsec not initialized") + + try: + session_generator = session.initiate({ + 'ike': ike_sa_name, + 'child': child_sa_name, + 'timeout': '-1', + 'my-host': src_addr, + 'other-host': dst_addr + }) + # a dummy `for` loop is required because of requirements + # from vici. Without a full iteration on the output, the + # command to vici may not be executed completely + for _ in session_generator: + pass + return True + except Exception: + raise ViciCommandError(f'Failed to initiate SA for IKE {ike_sa_name}') \ No newline at end of file diff --git a/src/completion/list_ipsec_profile_tunnels.py b/src/completion/list_ipsec_profile_tunnels.py new file mode 100644 index 000000000..df6c52f6d --- /dev/null +++ b/src/completion/list_ipsec_profile_tunnels.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-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 +# 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 . + +import os +import sys +import argparse + +from vyos.config import Config +from vyos.util import dict_search + +def get_tunnels_from_ipsecprofile(profile): + config = Config() + base = ['vpn', 'ipsec', 'profile', profile, 'bind'] + profile_conf = config.get_config_dict(base, effective=True, key_mangling=('-', '_')) + tunnels = [] + + try: + for tunnel in (dict_search('bind.tunnel', profile_conf) or []): + tunnels.append(tunnel) + except: + pass + + return tunnels + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-p", "--profile", type=str, help="List tunnels per profile") + args = parser.parse_args() + + tunnels = [] + + tunnels = get_tunnels_from_ipsecprofile(args.profile) + + print(" ".join(tunnels)) + diff --git a/src/op_mode/ipsec.py b/src/op_mode/ipsec.py index 6acde08ea..7f4fb72e5 100755 --- a/src/op_mode/ipsec.py +++ b/src/op_mode/ipsec.py @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . + import re import sys import typing @@ -487,6 +488,67 @@ def reset_ra(username: typing.Optional[str] = None): vyos.ipsec.terminate_vici_ikeid_list(list_sa_id) +def reset_profile_dst(profile: str, tunnel: str, nbma_dst: str): + if profile and tunnel and nbma_dst: + ike_sa_name = f'dmvpn-{profile}-{tunnel}' + try: + # Get IKE SAs + sa_list = convert_data( + vyos.ipsec.get_vici_sas_by_name(ike_sa_name, None)) + if not sa_list: + raise vyos.opmode.IncorrectValue( + f'SA(s) for profile {profile} tunnel {tunnel} not found, aborting') + sa_nbma_list = list([x for x in sa_list if + ike_sa_name in x and x[ike_sa_name][ + 'remote-host'] == nbma_dst]) + if not sa_nbma_list: + raise vyos.opmode.IncorrectValue( + f'SA(s) for profile {profile} tunnel {tunnel} remote-host {nbma_dst} not found, aborting') + # terminate IKE SAs + vyos.ipsec.terminate_vici_ikeid_list(list( + [x[ike_sa_name]['uniqueid'] for x in sa_nbma_list if + ike_sa_name in x])) + # initiate IKE SAs + for ike in sa_nbma_list: + if ike_sa_name in ike: + vyos.ipsec.vici_initiate(ike_sa_name, 'dmvpn', + ike[ike_sa_name]['local-host'], + ike[ike_sa_name]['remote-host']) + print( + f'Profile {profile} tunnel {tunnel} remote-host {nbma_dst} reset result: success') + except (vyos.ipsec.ViciInitiateError) as err: + raise vyos.opmode.UnconfiguredSubsystem(err) + except (vyos.ipsec.ViciCommandError) as err: + raise vyos.opmode.IncorrectValue(err) + + +def reset_profile_all(profile: str, tunnel: str): + if profile and tunnel: + ike_sa_name = f'dmvpn-{profile}-{tunnel}' + try: + # Get IKE SAs + sa_list: list = convert_data( + vyos.ipsec.get_vici_sas_by_name(ike_sa_name, None)) + if not sa_list: + raise vyos.opmode.IncorrectValue( + f'SA(s) for profile {profile} tunnel {tunnel} not found, aborting') + # terminate IKE SAs + vyos.ipsec.terminate_vici_by_name(ike_sa_name, None) + # initiate IKE SAs + for ike in sa_list: + if ike_sa_name in ike: + vyos.ipsec.vici_initiate(ike_sa_name, 'dmvpn', + ike[ike_sa_name]['local-host'], + ike[ike_sa_name]['remote-host']) + print( + f'Profile {profile} tunnel {tunnel} remote-host {ike[ike_sa_name]["remote-host"]} reset result: success') + print(f'Profile {profile} tunnel {tunnel} reset result: success') + except (vyos.ipsec.ViciInitiateError) as err: + raise vyos.opmode.UnconfiguredSubsystem(err) + except (vyos.ipsec.ViciCommandError) as err: + raise vyos.opmode.IncorrectValue(err) + + def show_sa(raw: bool): sa_data = _get_raw_data_sas() if raw: diff --git a/src/op_mode/vpn_ipsec.py b/src/op_mode/vpn_ipsec.py index 2392cfe92..b81d1693e 100755 --- a/src/op_mode/vpn_ipsec.py +++ b/src/op_mode/vpn_ipsec.py @@ -16,12 +16,12 @@ import re import argparse -from subprocess import TimeoutExpired from vyos.util import call SWANCTL_CONF = '/etc/swanctl/swanctl.conf' + def get_peer_connections(peer, tunnel, return_all = False): search = rf'^[\s]*(peer_{peer}_(tunnel_[\d]+|vti)).*' matches = [] @@ -34,57 +34,6 @@ def get_peer_connections(peer, tunnel, return_all = False): matches.append(result[1]) return matches -def reset_peer(peer, tunnel): - if not peer: - print('Invalid peer, aborting') - return - - conns = get_peer_connections(peer, tunnel, return_all = (not tunnel or tunnel == 'all')) - - if not conns: - print('Tunnel(s) not found, aborting') - return - - result = True - for conn in conns: - try: - call(f'/usr/sbin/ipsec down {conn}{{*}}', timeout = 10) - call(f'/usr/sbin/ipsec up {conn}', timeout = 10) - except TimeoutExpired as e: - print(f'Timed out while resetting {conn}') - result = False - - - print('Peer reset result: ' + ('success' if result else 'failed')) - -def get_profile_connection(profile, tunnel = None): - search = rf'(dmvpn-{profile}-[\w]+)' if tunnel == 'all' else rf'(dmvpn-{profile}-{tunnel})' - with open(SWANCTL_CONF, 'r') as f: - for line in f.readlines(): - result = re.search(search, line) - if result: - return result[1] - return None - -def reset_profile(profile, tunnel): - if not profile: - print('Invalid profile, aborting') - return - - if not tunnel: - print('Invalid tunnel, aborting') - return - - conn = get_profile_connection(profile) - - if not conn: - print('Profile not found, aborting') - return - - call(f'/usr/sbin/ipsec down {conn}') - result = call(f'/usr/sbin/ipsec up {conn}') - - print('Profile reset result: ' + ('success' if result == 0 else 'failed')) def debug_peer(peer, tunnel): peer = peer.replace(':', '-') @@ -119,6 +68,7 @@ def debug_peer(peer, tunnel): for conn in conns: call(f'/usr/sbin/ipsec statusall | grep {conn}') + if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--action', help='Control action', required=True) @@ -127,9 +77,6 @@ if __name__ == '__main__': args = parser.parse_args() - if args.action == 'reset-peer': - reset_peer(args.name, args.tunnel) - elif args.action == "reset-profile": - reset_profile(args.name, args.tunnel) - elif args.action == "vpn-debug": + + if args.action == "vpn-debug": debug_peer(args.name, args.tunnel) -- cgit v1.2.3 From 328c2f1c2111870796d30a7c7616a03f9339c2fe Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Thu, 30 Mar 2023 14:12:39 -0500 Subject: interfaces: T5130: show/interfaces/node.def defined in vyos-1x --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index a4bfac17d..4f49f0d27 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,6 @@ op_mode_definitions: $(op_xml_obj) rm -f $(OP_TMPL_DIR)/generate/node.def rm -f $(OP_TMPL_DIR)/monitor/node.def rm -f $(OP_TMPL_DIR)/set/node.def - rm -f $(OP_TMPL_DIR)/show/interfaces/node.def rm -f $(OP_TMPL_DIR)/show/node.def rm -f $(OP_TMPL_DIR)/show/system/node.def -- cgit v1.2.3 From 33b804c2030f8bc47acb3499a155a0e2f1f2db0f Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Thu, 30 Mar 2023 14:12:59 -0500 Subject: interfaces: T5130: remove obsoleted show_interfaces.py --- src/op_mode/show_interfaces.py | 310 ----------------------------------------- 1 file changed, 310 deletions(-) delete mode 100755 src/op_mode/show_interfaces.py diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py deleted file mode 100755 index eac068274..000000000 --- a/src/op_mode/show_interfaces.py +++ /dev/null @@ -1,310 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2017-2021 VyOS maintainers and contributors -# -# 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 . - -import os -import re -import sys -import glob -import argparse - -from vyos.ifconfig import Section -from vyos.ifconfig import Interface -from vyos.ifconfig import VRRP -from vyos.util import cmd, call - - -# interfaces = Sections.reserved() -interfaces = ['eno', 'ens', 'enp', 'enx', 'eth', 'vmnet', 'lo', 'tun', 'wan', 'pppoe'] -glob_ifnames = '/sys/class/net/({})*'.format('|'.join(interfaces)) - - -actions = {} -def register(name): - """ - Decorator to register a function into actions with a name. - `actions[name]' can be used to call the registered functions. - We wrap each function in a SIGPIPE handler as all registered functions - can be subject to a broken pipe if there are a lot of interfaces. - """ - def _register(function): - def handled_function(*args, **kwargs): - try: - function(*args, **kwargs) - except BrokenPipeError: - # Flush output to /dev/null and bail out. - os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno()) - sys.exit(1) - actions[name] = handled_function - return handled_function - return _register - - -def filtered_interfaces(ifnames, iftypes, vif, vrrp): - """ - get all the interfaces from the OS and returns them - ifnames can be used to filter which interfaces should be considered - - ifnames: a list of interfaces names to consider, empty do not filter - return an instance of the interface class - """ - if isinstance(iftypes, list): - for iftype in iftypes: - yield from filtered_interfaces(ifnames, iftype, vif, vrrp) - - for ifname in Section.interfaces(iftypes): - # Bail out early if interface name not part of our search list - if ifnames and ifname not in ifnames: - continue - - # As we are only "reading" from the interface - we must use the - # generic base class which exposes all the data via a common API - interface = Interface(ifname, create=False, debug=False) - - # VLAN interfaces have a '.' in their name by convention - if vif and not '.' in ifname: - continue - - if vrrp: - vrrp_interfaces = VRRP.active_interfaces() - if ifname not in vrrp_interfaces: - continue - - yield interface - - -def split_text(text, used=0): - """ - take a string and attempt to split it to fit with the width of the screen - - text: the string to split - used: number of characted already used in the screen - """ - no_tty = call('tty -s') - - returned = cmd('stty size') if not no_tty else '' - if len(returned) == 2: - rows, columns = [int(_) for _ in returned] - else: - rows, columns = (40, 80) - - desc_len = columns - used - - line = '' - for word in text.split(): - if len(line) + len(word) < desc_len: - line = f'{line} {word}' - continue - if line: - yield line[1:] - else: - line = f'{line} {word}' - - yield line[1:] - - -def get_counter_val(clear, now): - """ - attempt to correct a counter if it wrapped, copied from perl - - clear: previous counter - now: the current counter - """ - # This function has to deal with both 32 and 64 bit counters - if clear == 0: - return now - - # device is using 64 bit values assume they never wrap - value = now - clear - if (now >> 32) != 0: - return value - - # The counter has rolled. If the counter has rolled - # multiple times since the clear value, then this math - # is meaningless. - if (value < 0): - value = (4294967296 - clear) + now - - return value - - -@register('help') -def usage(*args): - print(f"Usage: {sys.argv[0]} [intf=NAME|intf-type=TYPE|vif|vrrp] action=ACTION") - print(f" NAME = " + ' | '.join(Section.interfaces())) - print(f" TYPE = " + ' | '.join(Section.sections())) - print(f" ACTION = " + ' | '.join(actions)) - sys.exit(1) - - -@register('allowed') -def run_allowed(**kwarg): - sys.stdout.write(' '.join(Section.interfaces())) - - -def pppoe(ifname): - out = cmd(f'ps -C pppd -f') - if ifname in out: - return 'C' - elif ifname in [_.split('/')[-1] for _ in glob.glob('/etc/ppp/peers/pppoe*')]: - return 'D' - return '' - - -@register('show') -def run_show_intf(ifnames, iftypes, vif, vrrp): - handled = [] - for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): - handled.append(interface.ifname) - cache = interface.operational.load_counters() - - out = cmd(f'ip addr show {interface.ifname}') - out = re.sub(f'^\d+:\s+','',out) - if re.search('link/tunnel6', out): - tunnel = cmd(f'ip -6 tun show {interface.ifname}') - # tun0: ip/ipv6 remote ::2 local ::1 encaplimit 4 hoplimit 64 tclass inherit flowlabel inherit (flowinfo 0x00000000) - tunnel = re.sub('.*encap', 'encap', tunnel) - out = re.sub('(\n\s+)(link/tunnel6)', f'\g<1>{tunnel}\g<1>\g<2>', out) - - print(out) - - timestamp = int(cache.get('timestamp', 0)) - if timestamp: - when = interface.operational.strtime(timestamp) - print(f' Last clear: {when}') - - description = interface.get_alias() - if description: - print(f' Description: {description}') - - print() - print(interface.operational.formated_stats()) - - for ifname in ifnames: - if ifname not in handled and ifname.startswith('pppoe'): - state = pppoe(ifname) - if not state: - continue - string = { - 'C': 'Coming up', - 'D': 'Link down', - }[state] - print('{}: {}'.format(ifname, string)) - - -@register('show-brief') -def run_show_intf_brief(ifnames, iftypes, vif, vrrp): - format1 = '%-16s %-33s %-4s %s' - format2 = '%-16s %s' - - print('Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down') - print(format1 % ("Interface", "IP Address", "S/L", "Description")) - print(format1 % ("---------", "----------", "---", "-----------")) - - handled = [] - for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): - handled.append(interface.ifname) - - oper_state = interface.operational.get_state() - admin_state = interface.get_admin_state() - - intf = [interface.ifname,] - - oper = ['u', ] if oper_state in ('up', 'unknown') else ['D', ] - admin = ['u', ] if admin_state in ('up', 'unknown') else ['A', ] - addrs = [_ for _ in interface.get_addr() if not _.startswith('fe80::')] or ['-', ] - descs = list(split_text(interface.get_alias(),0)) - - while intf or oper or admin or addrs or descs: - i = intf.pop(0) if intf else '' - a = addrs.pop(0) if addrs else '' - d = descs.pop(0) if descs else '' - s = [admin.pop(0)] if admin else [] - l = [oper.pop(0)] if oper else [] - if len(a) < 33: - print(format1 % (i, a, '/'.join(s+l), d)) - else: - print(format2 % (i, a)) - print(format1 % ('', '', '/'.join(s+l), d)) - - for ifname in ifnames: - if ifname not in handled and ifname.startswith('pppoe'): - state = pppoe(ifname) - if not state: - continue - string = { - 'C': 'u/D', - 'D': 'A/D', - }[state] - print(format1 % (ifname, '', string, '')) - - -@register('show-count') -def run_show_counters(ifnames, iftypes, vif, vrrp): - formating = '%-12s %10s %10s %10s %10s' - print(formating % ('Interface', 'Rx Packets', 'Rx Bytes', 'Tx Packets', 'Tx Bytes')) - - for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): - oper = interface.operational.get_state() - - if oper not in ('up','unknown'): - continue - - stats = interface.operational.get_stats() - cache = interface.operational.load_counters() - print(formating % ( - interface.ifname, - get_counter_val(cache['rx_packets'], stats['rx_packets']), - get_counter_val(cache['rx_bytes'], stats['rx_bytes']), - get_counter_val(cache['tx_packets'], stats['tx_packets']), - get_counter_val(cache['tx_bytes'], stats['tx_bytes']), - )) - - -@register('clear') -def run_clear_intf(ifnames, iftypes, vif, vrrp): - for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): - print(f'Clearing {interface.ifname}') - interface.operational.clear_counters() - - -@register('reset') -def run_reset_intf(ifnames, iftypes, vif, vrrp): - for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp): - interface.operational.reset_counters() - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(add_help=False, description='Show interface information') - parser.add_argument('--intf', action="store", type=str, default='', help='only show the specified interface(s)') - parser.add_argument('--intf-type', action="store", type=str, default='', help='only show the specified interface type') - parser.add_argument('--action', action="store", type=str, default='show', help='action to perform') - parser.add_argument('--vif', action='store_true', default=False, help="only show vif interfaces") - parser.add_argument('--vrrp', action='store_true', default=False, help="only show vrrp interfaces") - parser.add_argument('--help', action='store_true', default=False, help="show help") - - args = parser.parse_args() - - def missing(*args): - print('Invalid action [{args.action}]') - usage() - - actions.get(args.action, missing)( - [_ for _ in args.intf.split(' ') if _], - [_ for _ in args.intf_type.split(' ') if _], - args.vif, - args.vrrp - ) -- cgit v1.2.3 From d1345fe688546082a1d8283ccb0c3b05bcd0a1d3 Mon Sep 17 00:00:00 2001 From: fett0 Date: Thu, 30 Mar 2023 22:54:16 +0000 Subject: T5131: fix op-mode show isis segment-routing prefix-sids --- op-mode-definitions/include/isis-common.xml.i | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 95a171515..4a2f1e503 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -122,6 +122,12 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show Prefix-SID information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + vtysh -c "show isis route" @@ -136,12 +142,6 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - Show prefix segment IDs - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - -- cgit v1.2.3 From 599c5405e7ff5b76aa774b8cc97a82fbc053d46c Mon Sep 17 00:00:00 2001 From: Nicolas Fort Date: Thu, 30 Mar 2023 12:55:30 +0000 Subject: T5128: Policy Route: allow wildcard on interface --- data/templates/firewall/nftables-policy.j2 | 2 +- .../constraint/interface-name-with-wildcard.xml.in | 4 ++++ .../include/generic-interface-multi-wildcard.xml.i | 19 +++++++++++++++++++ interface-definitions/policy-route.xml.in | 4 ++-- smoketest/scripts/cli/test_policy_route.py | 8 +++++--- 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 interface-definitions/include/constraint/interface-name-with-wildcard.xml.in create mode 100644 interface-definitions/include/generic-interface-multi-wildcard.xml.i diff --git a/data/templates/firewall/nftables-policy.j2 b/data/templates/firewall/nftables-policy.j2 index 6cb3b2f95..7a89d29e4 100644 --- a/data/templates/firewall/nftables-policy.j2 +++ b/data/templates/firewall/nftables-policy.j2 @@ -11,7 +11,7 @@ table ip vyos_mangle { type filter hook prerouting priority -150; policy accept; {% if route is vyos_defined %} {% for route_text, conf in route.items() if conf.interface is vyos_defined %} - iifname { {{ ",".join(conf.interface) }} } counter jump VYOS_PBR_{{ route_text }} + iifname { {{ conf.interface | join(",") }} } counter jump VYOS_PBR_{{ route_text }} {% endfor %} {% endif %} } diff --git a/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in b/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in new file mode 100644 index 000000000..09867b380 --- /dev/null +++ b/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in @@ -0,0 +1,4 @@ + +(bond|br|dum|en|ersp|eth|gnv|ifb|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|veth|vti|vtun|vxlan|wg|wlan|wwan)([0-9]?)(\*?)(.+)?|lo + + diff --git a/interface-definitions/include/generic-interface-multi-wildcard.xml.i b/interface-definitions/include/generic-interface-multi-wildcard.xml.i new file mode 100644 index 000000000..354841a85 --- /dev/null +++ b/interface-definitions/include/generic-interface-multi-wildcard.xml.i @@ -0,0 +1,19 @@ + + + + + Interface name to apply policy route configuration + + + + + txt + Interface name + + + #include + + + + + diff --git a/interface-definitions/policy-route.xml.in b/interface-definitions/policy-route.xml.in index bbd6dbf56..d4ec75786 100644 --- a/interface-definitions/policy-route.xml.in +++ b/interface-definitions/policy-route.xml.in @@ -12,8 +12,8 @@ #include - #include #include + #include Policy rule number @@ -67,8 +67,8 @@ #include - #include #include + #include Policy rule number diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py index 4be36b134..a3df6bf4d 100755 --- a/smoketest/scripts/cli/test_policy_route.py +++ b/smoketest/scripts/cli/test_policy_route.py @@ -26,6 +26,7 @@ conn_mark_set = '111' table_mark_offset = 0x7fffffff table_id = '101' interface = 'eth0' +interface_wc = 'ppp*' interface_ip = '172.16.10.1/24' class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): @@ -236,7 +237,8 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'set', 'table', table_id]) self.cli_set(['policy', 'route', 'smoketest', 'interface', interface]) - self.cli_set(['policy', 'route6', 'smoketest6', 'interface', interface]) + self.cli_set(['policy', 'route', 'smoketest', 'interface', interface_wc]) + self.cli_set(['policy', 'route6', 'smoketest6', 'interface', interface_wc]) self.cli_commit() @@ -244,7 +246,7 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): # IPv4 nftables_search = [ - [f'iifname "{interface}"', 'jump VYOS_PBR_smoketest'], + ['iifname { "' + interface + '", "' + interface_wc + '" }', 'jump VYOS_PBR_smoketest'], ['meta l4proto udp', 'drop'], ['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex], ['ct state new', 'tcp dport 22', 'ip saddr 198.51.100.0/24', 'ip ttl > 2', 'meta mark set ' + mark_hex], @@ -256,7 +258,7 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): # IPv6 nftables6_search = [ - [f'iifname "{interface}"', 'jump VYOS_PBR6_smoketest'], + [f'iifname "{interface_wc}"', 'jump VYOS_PBR6_smoketest'], ['meta l4proto udp', 'drop'], ['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex], ['ct state new', 'tcp dport 22', 'ip6 saddr 2001:db8::/64', 'ip6 hoplimit > 2', 'meta mark set ' + mark_hex], -- cgit v1.2.3 From c41af9698abaeb1dc656933570c14fc9d75c9ce5 Mon Sep 17 00:00:00 2001 From: Nicolas Fort Date: Fri, 31 Mar 2023 13:05:50 +0000 Subject: T5128: Add contraint for firewall interface. Also update smoketest to include at least one wildcarded interface --- interface-definitions/firewall.xml.in | 3 +++ smoketest/scripts/cli/test_firewall.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index 624d61759..edbf1e03a 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -349,6 +349,9 @@ + + #include + diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index e071b7df9..99d3b3ca1 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -198,6 +198,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): def test_ipv4_basic_rules(self): name = 'smoketest' interface = 'eth0' + interface_wc = 'l2tp*' mss_range = '501-1460' conn_mark = '555' @@ -240,6 +241,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', name, 'rule', '6', 'connection-mark', conn_mark]) self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) + self.cli_set(['firewall', 'interface', interface_wc, 'in', 'name', name]) self.cli_commit() @@ -247,6 +249,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ [f'iifname "{interface}"', f'jump NAME_{name}'], + [f'iifname "{interface_wc}"', f'jump NAME_{name}'], ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[smoketest-1-A]" log level debug', 'ip ttl 15', 'return'], ['tcp flags syn / syn,ack', 'tcp dport 8888', 'log prefix "[smoketest-2-R]" log level err', 'ip ttl > 102', 'reject'], ['tcp dport 22', 'limit rate 5/minute', 'return'], -- cgit v1.2.3 From 657f5c1a08351c7740ff74cc112321d8f4e2155c Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Fri, 31 Mar 2023 13:09:21 +0000 Subject: T5125: Add op-mode for sFlow based on hsflowd Add op-mode for sFlow based on hsflowd "show sflow" Add machine readable format '--raw' and formatted output --- data/templates/sflow/hsflowd.conf.j2 | 1 + op-mode-definitions/sflow.xml.in | 15 +++++ smoketest/scripts/cli/test_system_sflow.py | 1 + src/op_mode/sflow.py | 102 +++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 op-mode-definitions/sflow.xml.in create mode 100755 src/op_mode/sflow.py diff --git a/data/templates/sflow/hsflowd.conf.j2 b/data/templates/sflow/hsflowd.conf.j2 index 94f5939be..5000956bd 100644 --- a/data/templates/sflow/hsflowd.conf.j2 +++ b/data/templates/sflow/hsflowd.conf.j2 @@ -28,4 +28,5 @@ sflow { {% if drop_monitor_limit is vyos_defined %} dropmon { limit={{ drop_monitor_limit }} start=on sw=on hw=off } {% endif %} + dbus { } } diff --git a/op-mode-definitions/sflow.xml.in b/op-mode-definitions/sflow.xml.in new file mode 100644 index 000000000..9f02dacda --- /dev/null +++ b/op-mode-definitions/sflow.xml.in @@ -0,0 +1,15 @@ + + + + + + + + Show sFlow statistics + + + sudo ${vyos_op_scripts_dir}/sflow.py show + + + + diff --git a/smoketest/scripts/cli/test_system_sflow.py b/smoketest/scripts/cli/test_system_sflow.py index fef88b56a..1aec050a4 100755 --- a/smoketest/scripts/cli/test_system_sflow.py +++ b/smoketest/scripts/cli/test_system_sflow.py @@ -91,6 +91,7 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): self.assertIn(f'collector {{ ip = {server} udpport = {port} }}', hsflowd) self.assertIn(f'collector {{ ip = {local_server} udpport = {default_port} }}', hsflowd) self.assertIn(f'dropmon {{ limit={mon_limit} start=on sw=on hw=off }}', hsflowd) + self.assertIn('dbus { }', hsflowd) for interface in Section.interfaces('ethernet'): self.assertIn(f'pcap {{ dev={interface} }}', hsflowd) diff --git a/src/op_mode/sflow.py b/src/op_mode/sflow.py new file mode 100755 index 000000000..1ff006274 --- /dev/null +++ b/src/op_mode/sflow.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +import dbus +import sys + +from tabulate import tabulate + +from vyos.configquery import ConfigTreeQuery +from vyos.util import cmd + +import vyos.opmode + + +def _get_raw_sflow(): + bus = dbus.SystemBus() + config = ConfigTreeQuery() + + interfaces = config.values('system sflow interface') + servers = config.list_nodes('system sflow server') + + sflow = bus.get_object('net.sflow.hsflowd', '/net/sflow/hsflowd') + sflow_telemetry = dbus.Interface( + sflow, dbus_interface='net.sflow.hsflowd.telemetry') + agent_address = sflow_telemetry.GetAgent() + samples_dropped = int(sflow_telemetry.Get('dropped_samples')) + samples_packet_sent = int(sflow_telemetry.Get('flow_samples')) + samples_counter_sent = int(sflow_telemetry.Get('counter_samples')) + datagrams_sent = int(sflow_telemetry.Get('datagrams')) + rtmetric_samples = int(sflow_telemetry.Get('rtmetric_samples')) + samples_suppressed = int(sflow_telemetry.Get('flow_samples_suppressed')) + counter_samples_suppressed = int( + sflow_telemetry.Get("counter_samples_suppressed")) + version = sflow_telemetry.GetVersion() + + sflow_dict = { + 'agent_address': agent_address, + 'sflow_interfaces': interfaces, + 'sflow_servers': servers, + 'counter_samples_sent': samples_counter_sent, + 'datagrams_sent': datagrams_sent, + 'packet_samples_dropped': samples_dropped, + 'packet_samples_sent': samples_packet_sent, + 'rtmetric_samples': rtmetric_samples, + 'flow_samples_suppressed': samples_suppressed, + 'counter_samples_suppressed': counter_samples_suppressed, + 'hsflowd_version': version + } + return sflow_dict + + +def _get_formatted_sflow(data): + table = [ + ['Agent address', f'{data.get("agent_address")}'], + ['sFlow interfaces', f'{data.get("sflow_interfaces", "n/a")}'], + ['sFlow servers', f'{data.get("sflow_servers", "n/a")}'], + ['Datagrams sent', f'{data.get("datagrams_sent")}'], + ['Packet samples sent', f'{data.get("packet_samples_sent")}'], + ['Packet samples dropped', f'{data.get("packet_samples_dropped")}'], + ['Counter samples sent', f'{data.get("counter_samples_sent")}'], + ['Flow samples suppressed', f'{data.get("flow_samples_suppressed")}'], + ['Counter samples suppressed', f'{data.get("counter_samples_suppressed")}'] + ] + + return tabulate(table) + + +def show(raw: bool): + + config = ConfigTreeQuery() + if not config.exists('system sflow'): + raise vyos.opmode.UnconfiguredSubsystem( + '"system sflow" is not configured!') + + sflow_data = _get_raw_sflow() + if raw: + return sflow_data + else: + return _get_formatted_sflow(sflow_data) + + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) -- cgit v1.2.3 From 11b1d043310833447ddeea3b68fba2a1d1f5799d Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Wed, 29 Mar 2023 19:48:52 -0500 Subject: http-api: T5126: allow restricting client IP address --- data/templates/https/nginx.default.j2 | 6 +++++ interface-definitions/https.xml.in | 1 + interface-definitions/include/allow-client.xml.i | 33 ++++++++++++++++++++++++ src/conf_mode/https.py | 2 ++ 4 files changed, 42 insertions(+) create mode 100644 interface-definitions/include/allow-client.xml.i diff --git a/data/templates/https/nginx.default.j2 b/data/templates/https/nginx.default.j2 index d42b3b389..b541ff309 100644 --- a/data/templates/https/nginx.default.j2 +++ b/data/templates/https/nginx.default.j2 @@ -49,6 +49,12 @@ server { proxy_buffering off; {% else %} return 503; +{% endif %} +{% if server.allow_client %} +{% for client in server.allow_client %} + allow {{ client }}; +{% endfor %} + deny all; {% endif %} } diff --git a/interface-definitions/https.xml.in b/interface-definitions/https.xml.in index 6adb07598..cf30ab2be 100644 --- a/interface-definitions/https.xml.in +++ b/interface-definitions/https.xml.in @@ -60,6 +60,7 @@ + #include diff --git a/interface-definitions/include/allow-client.xml.i b/interface-definitions/include/allow-client.xml.i new file mode 100644 index 000000000..03a0b3ff8 --- /dev/null +++ b/interface-definitions/include/allow-client.xml.i @@ -0,0 +1,33 @@ + + + Restrict to allowed IP client addresses + + + + + Allowed IP client addresses + + ipv4 + IPv4 address + + + ipv6 + IPv6 address + + + ipv4net + IPv4 address and prefix length + + + ipv6net + IPv6 address and prefix length + + + + + + + + + + diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index ce5e63928..b0c38e8d3 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -159,6 +159,8 @@ def generate(https): server_block['port'] = data.get('listen-port', '443') name = data.get('server-name', ['_']) server_block['name'] = name + allow_client = data.get('allow-client', {}) + server_block['allow_client'] = allow_client.get('address', []) server_block_list.append(server_block) # get certificate data -- cgit v1.2.3 From 0993d9ed9fbbd2110a4911d10fc0b42c7ee8856e Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 10:51:09 +0200 Subject: xml: allow-client: T5126: re-use new building block also for NTP service --- interface-definitions/include/allow-client.xml.i | 68 ++++++++++++------------ interface-definitions/ntp.xml.in | 34 +----------- 2 files changed, 36 insertions(+), 66 deletions(-) diff --git a/interface-definitions/include/allow-client.xml.i b/interface-definitions/include/allow-client.xml.i index 03a0b3ff8..1b06e2c17 100644 --- a/interface-definitions/include/allow-client.xml.i +++ b/interface-definitions/include/allow-client.xml.i @@ -1,33 +1,35 @@ - - - Restrict to allowed IP client addresses - - - - - Allowed IP client addresses - - ipv4 - IPv4 address - - - ipv6 - IPv6 address - - - ipv4net - IPv4 address and prefix length - - - ipv6net - IPv6 address and prefix length - - - - - - - - - - + + + + Restrict to allowed IP client addresses + + + + + Allowed IP client addresses + + ipv4 + IPv4 address + + + ipv6 + IPv6 address + + + ipv4net + IPv4 address and prefix length + + + ipv6net + IPv6 address and prefix length + + + + + + + + + + + diff --git a/interface-definitions/ntp.xml.in b/interface-definitions/ntp.xml.in index 287401ed6..558204a06 100644 --- a/interface-definitions/ntp.xml.in +++ b/interface-definitions/ntp.xml.in @@ -57,39 +57,7 @@ - - - Specify NTP clients allowed to access the server - - - - - IP address - - ipv4 - Allowed IPv4 address - - - ipv4net - Allowed IPv4 prefix - - - ipv6 - Allowed IPv6 address - - - ipv6net - Allowed IPv6 prefix - - - - - - - - - - + #include #include #include #include -- cgit v1.2.3 From 0a49c0af4dbdcad9e494d4fba2212f156485fd7d Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 10:51:57 +0200 Subject: xml: T5128: streamline help string for interface CLI node building blocks --- interface-definitions/include/generic-interface-broadcast.xml.i | 2 +- .../include/generic-interface-multi-broadcast.xml.i | 2 +- interface-definitions/include/generic-interface-multi-wildcard.xml.i | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface-definitions/include/generic-interface-broadcast.xml.i b/interface-definitions/include/generic-interface-broadcast.xml.i index 82bfc139b..ac21767d1 100644 --- a/interface-definitions/include/generic-interface-broadcast.xml.i +++ b/interface-definitions/include/generic-interface-broadcast.xml.i @@ -1,7 +1,7 @@ - Interface Name to use + Interface to use diff --git a/interface-definitions/include/generic-interface-multi-broadcast.xml.i b/interface-definitions/include/generic-interface-multi-broadcast.xml.i index 8160f816d..8b0c38761 100644 --- a/interface-definitions/include/generic-interface-multi-broadcast.xml.i +++ b/interface-definitions/include/generic-interface-multi-broadcast.xml.i @@ -1,7 +1,7 @@ - Interface Name to use + Interface to use diff --git a/interface-definitions/include/generic-interface-multi-wildcard.xml.i b/interface-definitions/include/generic-interface-multi-wildcard.xml.i index 354841a85..a93eddbbe 100644 --- a/interface-definitions/include/generic-interface-multi-wildcard.xml.i +++ b/interface-definitions/include/generic-interface-multi-wildcard.xml.i @@ -1,14 +1,13 @@ - - Interface name to apply policy route configuration + Interface to use txt - Interface name + Interface name, wildcard (*) supported #include -- cgit v1.2.3 From 15922541cef35956107e0b32ee952fee05928dbd Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 12:33:21 +0200 Subject: isis: op-mode: T5132: bugfix VRF commands for route and neighbor show isis vrf neighbor|route did not call the vtysh wrapper but instead always called the commands for the default routing table. --- op-mode-definitions/include/isis-common.xml.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 4a2f1e503..0e20861c7 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -94,7 +94,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - vtysh -c "show isis neighbor" + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ @@ -129,7 +129,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - vtysh -c "show isis route" + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ -- cgit v1.2.3 From 2265bb4dc27965da3dce7e3f476366b7d1e911f3 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 13:14:30 +0200 Subject: xml: include building block file name should end with .i and not .in --- interface-definitions/container.xml.in | 2 +- interface-definitions/dhcp-relay.xml.in | 4 ++-- interface-definitions/dns-domain-name.xml.in | 4 ++-- interface-definitions/firewall.xml.in | 2 +- interface-definitions/high-availability.xml.in | 2 +- interface-definitions/include/babel/interface.xml.i | 2 +- interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i | 4 ++-- interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i | 4 ++-- interface-definitions/include/bgp/neighbor-update-source.xml.i | 2 +- interface-definitions/include/bgp/protocol-common-config.xml.i | 4 ++-- .../include/constraint/alpha-numeric-hyphen-underscore.xml.i | 3 +++ .../include/constraint/alpha-numeric-hyphen-underscore.xml.in | 3 --- interface-definitions/include/constraint/host-name.xml.i | 3 +++ interface-definitions/include/constraint/host-name.xml.in | 3 --- .../include/constraint/interface-name-with-wildcard.xml.i | 4 ++++ .../include/constraint/interface-name-with-wildcard.xml.in | 4 ---- interface-definitions/include/constraint/interface-name.xml.i | 4 ++++ interface-definitions/include/constraint/interface-name.xml.in | 4 ---- interface-definitions/include/dhcp-interface-multi.xml.i | 2 +- interface-definitions/include/dhcp-interface.xml.i | 2 +- .../include/generic-interface-broadcast.xml.i | 2 +- .../include/generic-interface-multi-broadcast.xml.i | 2 +- .../include/generic-interface-multi-wildcard.xml.i | 2 +- interface-definitions/include/generic-interface-multi.xml.i | 2 +- interface-definitions/include/generic-interface.xml.i | 2 +- interface-definitions/include/interface/redirect.xml.i | 2 +- .../include/ospf/protocol-common-config.xml.i | 2 +- .../include/ospfv3/protocol-common-config.xml.i | 2 +- interface-definitions/include/rip/interface.xml.i | 2 +- interface-definitions/include/routing-passive-interface.xml.i | 2 +- interface-definitions/include/source-interface.xml.i | 2 +- .../include/static/static-route-interface.xml.i | 2 +- interface-definitions/include/static/static-route.xml.i | 2 +- interface-definitions/include/static/static-route6.xml.i | 2 +- interface-definitions/interfaces-bonding.xml.in | 4 ++-- interface-definitions/policy.xml.in | 8 ++++---- interface-definitions/protocols-babel.xml.in | 4 ++-- interface-definitions/protocols-rip.xml.in | 2 +- interface-definitions/protocols-ripng.xml.in | 2 +- interface-definitions/protocols-static-arp.xml.in | 2 +- interface-definitions/qos.xml.in | 2 +- interface-definitions/service-monitoring-telegraf.xml.in | 10 +++++----- interface-definitions/service-upnp.xml.in | 4 ++-- interface-definitions/system-config-mgmt.xml.in | 2 +- interface-definitions/system-sflow.xml.in | 2 +- 45 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.i delete mode 100644 interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.in create mode 100644 interface-definitions/include/constraint/host-name.xml.i delete mode 100644 interface-definitions/include/constraint/host-name.xml.in create mode 100644 interface-definitions/include/constraint/interface-name-with-wildcard.xml.i delete mode 100644 interface-definitions/include/constraint/interface-name-with-wildcard.xml.in create mode 100644 interface-definitions/include/constraint/interface-name.xml.i delete mode 100644 interface-definitions/include/constraint/interface-name.xml.in diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index 6947ed500..0849af656 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -117,7 +117,7 @@ Container host name - #include + #include Host-name must be alphanumeric and can contain hyphens diff --git a/interface-definitions/dhcp-relay.xml.in b/interface-definitions/dhcp-relay.xml.in index 79ad2c01c..2a2597dd5 100644 --- a/interface-definitions/dhcp-relay.xml.in +++ b/interface-definitions/dhcp-relay.xml.in @@ -21,7 +21,7 @@ Interface name - #include + #include @@ -37,7 +37,7 @@ Interface name - #include + #include diff --git a/interface-definitions/dns-domain-name.xml.in b/interface-definitions/dns-domain-name.xml.in index c0ac16a80..e93c49ebd 100644 --- a/interface-definitions/dns-domain-name.xml.in +++ b/interface-definitions/dns-domain-name.xml.in @@ -25,7 +25,7 @@ - #include + #include @@ -34,7 +34,7 @@ System host name (default: vyos) - #include + #include diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index edbf1e03a..69901e5d3 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -350,7 +350,7 @@ - #include + #include diff --git a/interface-definitions/high-availability.xml.in b/interface-definitions/high-availability.xml.in index 1fa051df9..ce6603796 100644 --- a/interface-definitions/high-availability.xml.in +++ b/interface-definitions/high-availability.xml.in @@ -220,7 +220,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/babel/interface.xml.i b/interface-definitions/include/babel/interface.xml.i index 586eca7a5..a122ef024 100644 --- a/interface-definitions/include/babel/interface.xml.i +++ b/interface-definitions/include/babel/interface.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i b/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i index ee902b0b6..0f760daae 100644 --- a/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i +++ b/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i @@ -15,7 +15,7 @@ Name of IPv4 prefix-list - #include + #include Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores @@ -31,7 +31,7 @@ Name of IPv4 prefix-list - #include + #include Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores diff --git a/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i b/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i index da966f193..268d9cbc0 100644 --- a/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i +++ b/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i @@ -15,7 +15,7 @@ Name of IPv6 prefix-list - #include + #include Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores @@ -31,7 +31,7 @@ Name of IPv6 prefix-list - #include + #include Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores diff --git a/interface-definitions/include/bgp/neighbor-update-source.xml.i b/interface-definitions/include/bgp/neighbor-update-source.xml.i index 0acec4126..c6aa776c2 100644 --- a/interface-definitions/include/bgp/neighbor-update-source.xml.i +++ b/interface-definitions/include/bgp/neighbor-update-source.xml.i @@ -22,7 +22,7 @@ - #include + #include diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index 089c36ef3..a9122db57 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -942,7 +942,7 @@ - #include + #include @@ -1530,7 +1530,7 @@ Name of peer-group - #include + #include diff --git a/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.i b/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.i new file mode 100644 index 000000000..eb568d7d9 --- /dev/null +++ b/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.i @@ -0,0 +1,3 @@ + +[-_a-zA-Z0-9]+ + diff --git a/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.in b/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.in deleted file mode 100644 index eb568d7d9..000000000 --- a/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore.xml.in +++ /dev/null @@ -1,3 +0,0 @@ - -[-_a-zA-Z0-9]+ - diff --git a/interface-definitions/include/constraint/host-name.xml.i b/interface-definitions/include/constraint/host-name.xml.i new file mode 100644 index 000000000..202c200f4 --- /dev/null +++ b/interface-definitions/include/constraint/host-name.xml.i @@ -0,0 +1,3 @@ + +[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9] + diff --git a/interface-definitions/include/constraint/host-name.xml.in b/interface-definitions/include/constraint/host-name.xml.in deleted file mode 100644 index 202c200f4..000000000 --- a/interface-definitions/include/constraint/host-name.xml.in +++ /dev/null @@ -1,3 +0,0 @@ - -[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9] - diff --git a/interface-definitions/include/constraint/interface-name-with-wildcard.xml.i b/interface-definitions/include/constraint/interface-name-with-wildcard.xml.i new file mode 100644 index 000000000..09867b380 --- /dev/null +++ b/interface-definitions/include/constraint/interface-name-with-wildcard.xml.i @@ -0,0 +1,4 @@ + +(bond|br|dum|en|ersp|eth|gnv|ifb|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|veth|vti|vtun|vxlan|wg|wlan|wwan)([0-9]?)(\*?)(.+)?|lo + + diff --git a/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in b/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in deleted file mode 100644 index 09867b380..000000000 --- a/interface-definitions/include/constraint/interface-name-with-wildcard.xml.in +++ /dev/null @@ -1,4 +0,0 @@ - -(bond|br|dum|en|ersp|eth|gnv|ifb|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|veth|vti|vtun|vxlan|wg|wlan|wwan)([0-9]?)(\*?)(.+)?|lo - - diff --git a/interface-definitions/include/constraint/interface-name.xml.i b/interface-definitions/include/constraint/interface-name.xml.i new file mode 100644 index 000000000..e540e4418 --- /dev/null +++ b/interface-definitions/include/constraint/interface-name.xml.i @@ -0,0 +1,4 @@ + +(bond|br|dum|en|ersp|eth|gnv|ifb|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|veth|vti|vtun|vxlan|wg|wlan|wwan)[0-9]+(.\d+)?|lo + + diff --git a/interface-definitions/include/constraint/interface-name.xml.in b/interface-definitions/include/constraint/interface-name.xml.in deleted file mode 100644 index e540e4418..000000000 --- a/interface-definitions/include/constraint/interface-name.xml.in +++ /dev/null @@ -1,4 +0,0 @@ - -(bond|br|dum|en|ersp|eth|gnv|ifb|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|veth|vti|vtun|vxlan|wg|wlan|wwan)[0-9]+(.\d+)?|lo - - diff --git a/interface-definitions/include/dhcp-interface-multi.xml.i b/interface-definitions/include/dhcp-interface-multi.xml.i index e10341037..0db11cf79 100644 --- a/interface-definitions/include/dhcp-interface-multi.xml.i +++ b/interface-definitions/include/dhcp-interface-multi.xml.i @@ -10,7 +10,7 @@ DHCP interface name - #include + #include diff --git a/interface-definitions/include/dhcp-interface.xml.i b/interface-definitions/include/dhcp-interface.xml.i index 24edbbd15..b5c94cb24 100644 --- a/interface-definitions/include/dhcp-interface.xml.i +++ b/interface-definitions/include/dhcp-interface.xml.i @@ -9,7 +9,7 @@ DHCP interface name - #include + #include diff --git a/interface-definitions/include/generic-interface-broadcast.xml.i b/interface-definitions/include/generic-interface-broadcast.xml.i index ac21767d1..e37e75012 100644 --- a/interface-definitions/include/generic-interface-broadcast.xml.i +++ b/interface-definitions/include/generic-interface-broadcast.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/generic-interface-multi-broadcast.xml.i b/interface-definitions/include/generic-interface-multi-broadcast.xml.i index 8b0c38761..ed13cf2cf 100644 --- a/interface-definitions/include/generic-interface-multi-broadcast.xml.i +++ b/interface-definitions/include/generic-interface-multi-broadcast.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/generic-interface-multi-wildcard.xml.i b/interface-definitions/include/generic-interface-multi-wildcard.xml.i index a93eddbbe..6c846a795 100644 --- a/interface-definitions/include/generic-interface-multi-wildcard.xml.i +++ b/interface-definitions/include/generic-interface-multi-wildcard.xml.i @@ -10,7 +10,7 @@ Interface name, wildcard (*) supported - #include + #include diff --git a/interface-definitions/include/generic-interface-multi.xml.i b/interface-definitions/include/generic-interface-multi.xml.i index 1b8dc102b..cfc77af3a 100644 --- a/interface-definitions/include/generic-interface-multi.xml.i +++ b/interface-definitions/include/generic-interface-multi.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/generic-interface.xml.i b/interface-definitions/include/generic-interface.xml.i index 9417f9ef0..65f5bfbb8 100644 --- a/interface-definitions/include/generic-interface.xml.i +++ b/interface-definitions/include/generic-interface.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/interface/redirect.xml.i b/interface-definitions/include/interface/redirect.xml.i index 0421f4074..9b41cd8ff 100644 --- a/interface-definitions/include/interface/redirect.xml.i +++ b/interface-definitions/include/interface/redirect.xml.i @@ -10,7 +10,7 @@ Destination interface name - #include + #include diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 25b54b181..f39b9c5e3 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -358,7 +358,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i index 014bf9e49..1c33ca920 100644 --- a/interface-definitions/include/ospfv3/protocol-common-config.xml.i +++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i @@ -118,7 +118,7 @@ Interface used for routing information exchange - #include + #include diff --git a/interface-definitions/include/rip/interface.xml.i b/interface-definitions/include/rip/interface.xml.i index 0a89f4d92..8007f0208 100644 --- a/interface-definitions/include/rip/interface.xml.i +++ b/interface-definitions/include/rip/interface.xml.i @@ -10,7 +10,7 @@ Interface name - #include + #include diff --git a/interface-definitions/include/routing-passive-interface.xml.i b/interface-definitions/include/routing-passive-interface.xml.i index 715468e59..8fa0d0fe7 100644 --- a/interface-definitions/include/routing-passive-interface.xml.i +++ b/interface-definitions/include/routing-passive-interface.xml.i @@ -16,7 +16,7 @@ (default) - #include + #include diff --git a/interface-definitions/include/source-interface.xml.i b/interface-definitions/include/source-interface.xml.i index c25a6a6d0..40fdc6c5e 100644 --- a/interface-definitions/include/source-interface.xml.i +++ b/interface-definitions/include/source-interface.xml.i @@ -10,7 +10,7 @@ - #include + #include diff --git a/interface-definitions/include/static/static-route-interface.xml.i b/interface-definitions/include/static/static-route-interface.xml.i index db2f0baa6..cb5436847 100644 --- a/interface-definitions/include/static/static-route-interface.xml.i +++ b/interface-definitions/include/static/static-route-interface.xml.i @@ -10,7 +10,7 @@ Gateway interface name - #include + #include diff --git a/interface-definitions/include/static/static-route.xml.i b/interface-definitions/include/static/static-route.xml.i index 34e36f5a7..268cfa005 100644 --- a/interface-definitions/include/static/static-route.xml.i +++ b/interface-definitions/include/static/static-route.xml.i @@ -26,7 +26,7 @@ Gateway interface name - #include + #include diff --git a/interface-definitions/include/static/static-route6.xml.i b/interface-definitions/include/static/static-route6.xml.i index aac02062f..1f8d54108 100644 --- a/interface-definitions/include/static/static-route6.xml.i +++ b/interface-definitions/include/static/static-route6.xml.i @@ -25,7 +25,7 @@ Gateway interface name - #include + #include diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index f5f1eb1b6..14b1036b4 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -199,7 +199,7 @@ Interface name - #include + #include @@ -218,7 +218,7 @@ Interface name - #include + #include diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index 66608be6f..7d5fe79ef 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -242,7 +242,7 @@ BGP extended community-list name - #include + #include Should be an alphanumeric name @@ -291,7 +291,7 @@ BGP large-community-list name - #include + #include Should be an alphanumeric name @@ -340,7 +340,7 @@ Name of IPv4 prefix-list - #include + #include Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores @@ -408,7 +408,7 @@ Name of IPv6 prefix-list - #include + #include Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores diff --git a/interface-definitions/protocols-babel.xml.in b/interface-definitions/protocols-babel.xml.in index b3377aac1..49fffe230 100644 --- a/interface-definitions/protocols-babel.xml.in +++ b/interface-definitions/protocols-babel.xml.in @@ -206,7 +206,7 @@ - #include + #include @@ -234,7 +234,7 @@ - #include + #include diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in index 68d2b64ca..0edd8f2ce 100644 --- a/interface-definitions/protocols-rip.xml.in +++ b/interface-definitions/protocols-rip.xml.in @@ -39,7 +39,7 @@ - #include + #include diff --git a/interface-definitions/protocols-ripng.xml.in b/interface-definitions/protocols-ripng.xml.in index be643896f..9d4d87422 100644 --- a/interface-definitions/protocols-ripng.xml.in +++ b/interface-definitions/protocols-ripng.xml.in @@ -40,7 +40,7 @@ - #include + #include diff --git a/interface-definitions/protocols-static-arp.xml.in b/interface-definitions/protocols-static-arp.xml.in index 63f450bd8..4b338df63 100644 --- a/interface-definitions/protocols-static-arp.xml.in +++ b/interface-definitions/protocols-static-arp.xml.in @@ -20,7 +20,7 @@ Interface name - #include + #include diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in index 9b1430ea0..c7bd8606a 100644 --- a/interface-definitions/qos.xml.in +++ b/interface-definitions/qos.xml.in @@ -17,7 +17,7 @@ Interface name - #include + #include diff --git a/interface-definitions/service-monitoring-telegraf.xml.in b/interface-definitions/service-monitoring-telegraf.xml.in index 5ba932400..ae0bae900 100644 --- a/interface-definitions/service-monitoring-telegraf.xml.in +++ b/interface-definitions/service-monitoring-telegraf.xml.in @@ -74,7 +74,7 @@ Application client id - #include + #include Client-id is limited to alphanumerical characters and can contain hyphen and underscores @@ -83,7 +83,7 @@ Application client secret - #include + #include Client-secret is limited to alphanumerical characters and can contain hyphen and underscores @@ -92,7 +92,7 @@ Set tenant id - #include + #include Tenant-id is limited to alphanumerical characters and can contain hyphen and underscores @@ -107,7 +107,7 @@ Remote database name - #include + #include Database is limited to alphanumerical characters and can contain hyphen and underscores @@ -140,7 +140,7 @@ Table name - #include + #include Table is limited to alphanumerical characters and can contain hyphen and underscores diff --git a/interface-definitions/service-upnp.xml.in b/interface-definitions/service-upnp.xml.in index 9e222d29a..1b2e00d91 100644 --- a/interface-definitions/service-upnp.xml.in +++ b/interface-definitions/service-upnp.xml.in @@ -24,7 +24,7 @@ - #include + #include @@ -119,7 +119,7 @@ - #include + #include diff --git a/interface-definitions/system-config-mgmt.xml.in b/interface-definitions/system-config-mgmt.xml.in index 1f852d284..716332d2a 100644 --- a/interface-definitions/system-config-mgmt.xml.in +++ b/interface-definitions/system-config-mgmt.xml.in @@ -32,7 +32,7 @@ - #include + #include diff --git a/interface-definitions/system-sflow.xml.in b/interface-definitions/system-sflow.xml.in index 335181fe1..9c748c24a 100644 --- a/interface-definitions/system-sflow.xml.in +++ b/interface-definitions/system-sflow.xml.in @@ -42,7 +42,7 @@ Interface name - #include + #include -- cgit v1.2.3 From 86d7b8d1d2b53b9fa93bd456abb4ea1b4f2949b6 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 14:42:45 +0200 Subject: container: T5047: bugfix TypeError: argument of type 'NoneType' is not iterable Commit 52e51ffb ("container: T5047: restart only containers that changed") started to iterate over a NoneType which is invalid. This happened when a network description was changed but no container was due for restart. --- src/conf_mode/container.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index bf83416b2..4e4db7180 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -459,7 +459,8 @@ def apply(container): os.unlink(file_path) continue - if name in dict_search('container_restart', container): + tmp = dict_search('container_restart', container) + if tmp and name in tmp: cmd(f'systemctl restart vyos-container-{name}.service') if disabled_new: -- cgit v1.2.3 From 0ea3e1420c373027bdf57ea9e794b81dd6b6ad4f Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 15:31:46 +0200 Subject: container: T5082: switch to netavark network stack We now support assigning discrete IPv6 addresses to a container. --- data/templates/container/containers.conf.j2 | 2 +- debian/control | 1 + interface-definitions/container.xml.in | 7 ++- src/conf_mode/container.py | 95 +++++++++++++++-------------- 4 files changed, 56 insertions(+), 49 deletions(-) diff --git a/data/templates/container/containers.conf.j2 b/data/templates/container/containers.conf.j2 index 9f66aed27..c635ca213 100644 --- a/data/templates/container/containers.conf.j2 +++ b/data/templates/container/containers.conf.j2 @@ -282,7 +282,7 @@ default_sysctls = [ # Before changing this value all containers must be stopped otherwise it is likely that # iptables rules and network interfaces might leak on the host. A reboot will fix this. # -network_backend = "cni" +network_backend = "netavark" # Path to directory where CNI plugin binaries are located. # diff --git a/debian/control b/debian/control index 028b7cd43..8cd49f62a 100644 --- a/debian/control +++ b/debian/control @@ -99,6 +99,7 @@ Depends: mtr-tiny, ndisc6, ndppd, + netavark, netplug, nfct, nftables (>= 0.9.3), diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index 0849af656..b09536a16 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -191,15 +191,20 @@ - Assign static IP address to container ipv4 IPv4 address + + ipv6 + IPv6 address + + + diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 4e4db7180..5cfbfc30c 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -16,6 +16,7 @@ import os +from hashlib import sha256 from ipaddress import ip_address from ipaddress import ip_network from json import dumps as json_write @@ -27,7 +28,6 @@ from vyos.configdict import node_changed from vyos.configdict import is_node_changed from vyos.util import call from vyos.util import cmd -from vyos.util import dict_search from vyos.util import run from vyos.util import rc_cmd from vyos.util import write_file @@ -166,21 +166,29 @@ def verify(container): raise ConfigError(f'Container network "{network_name}" does not exist!') if 'address' in container_config['network'][network_name]: - address = container_config['network'][network_name]['address'] - network = None - if is_ipv4(address): - network = [x for x in container['network'][network_name]['prefix'] if is_ipv4(x)][0] - elif is_ipv6(address): - network = [x for x in container['network'][network_name]['prefix'] if is_ipv6(x)][0] - - # Specified container IP address must belong to network prefix - if ip_address(address) not in ip_network(network): - raise ConfigError(f'Used container address "{address}" not in network "{network}"!') - - # We can not use the first IP address of a network prefix as this is used by podman - if ip_address(address) == ip_network(network)[1]: - raise ConfigError(f'IP address "{address}" can not be used for a container, '\ - 'reserved for the container engine!') + cnt_ipv4 = 0 + cnt_ipv6 = 0 + for address in container_config['network'][network_name]['address']: + network = None + if is_ipv4(address): + network = [x for x in container['network'][network_name]['prefix'] if is_ipv4(x)][0] + cnt_ipv4 += 1 + elif is_ipv6(address): + network = [x for x in container['network'][network_name]['prefix'] if is_ipv6(x)][0] + cnt_ipv6 += 1 + + # Specified container IP address must belong to network prefix + if ip_address(address) not in ip_network(network): + raise ConfigError(f'Used container address "{address}" not in network "{network}"!') + + # We can not use the first IP address of a network prefix as this is used by podman + if ip_address(address) == ip_network(network)[1]: + raise ConfigError(f'IP address "{address}" can not be used for a container, '\ + 'reserved for the container engine!') + + if cnt_ipv4 > 1 or cnt_ipv6 > 1: + raise ConfigError(f'Only one IP address per address family can be used for '\ + f'container "{name}". {cnt_ipv4} IPv4 and {cnt_ipv6} IPv6 address(es)!') if 'device' in container_config: for dev, dev_config in container_config['device'].items(): @@ -338,9 +346,13 @@ def generate_run_arguments(name, container_config): ip_param = '' networks = ",".join(container_config['network']) for network in container_config['network']: - if 'address' in container_config['network'][network]: - address = container_config['network'][network]['address'] - ip_param = f'--ip {address}' + if 'address' not in container_config['network'][network]: + continue + for address in container_config['network'][network]['address']: + if is_ipv6(address): + ip_param += f' --ip6 {address}' + else: + ip_param += f' --ip {address}' return f'{container_base_cmd} --net {networks} {ip_param} {entrypoint} {image} {command} {command_arguments}'.strip() @@ -355,33 +367,26 @@ def generate(container): if 'network' in container: for network, network_config in container['network'].items(): tmp = { - 'cniVersion' : '0.4.0', - 'name' : network, - 'plugins' : [{ - 'type': 'bridge', - 'bridge': f'cni-{network}', - 'isGateway': True, - 'ipMasq': False, - 'hairpinMode': False, - 'ipam' : { - 'type': 'host-local', - 'routes': [], - 'ranges' : [], - }, - }] + 'name': network, + 'id' : sha256(f'{network}'.encode()).hexdigest(), + 'driver': 'bridge', + 'network_interface': f'podman-{network}', + 'subnets': [], + 'ipv6_enabled': False, + 'internal': False, + 'dns_enabled': False, + 'ipam_options': { + 'driver': 'host-local' + } } - for prefix in network_config['prefix']: - net = [{'gateway' : inc_ip(prefix, 1), 'subnet' : prefix}] - tmp['plugins'][0]['ipam']['ranges'].append(net) + net = {'subnet' : prefix, 'gateway' : inc_ip(prefix, 1)} + tmp['subnets'].append(net) - # install per address-family default orutes - default_route = '0.0.0.0/0' if is_ipv6(prefix): - default_route = '::/0' - tmp['plugins'][0]['ipam']['routes'].append({'dst': default_route}) + tmp['ipv6_enabled'] = True - write_file(f'/etc/cni/net.d/{network}.conflist', json_write(tmp, indent=2)) + write_file(f'/etc/containers/networks/{network}.json', json_write(tmp, indent=2)) if 'registry' in container: cmd = f'podman logout --all' @@ -432,10 +437,7 @@ def apply(container): # Delete old networks if needed if 'network_remove' in container: for network in container['network_remove']: - call(f'podman network rm {network}') - tmp = f'/etc/cni/net.d/{network}.conflist' - if os.path.exists(tmp): - os.unlink(tmp) + call(f'podman network rm {network} >/dev/null 2>&1') # Add container disabled_new = False @@ -459,8 +461,7 @@ def apply(container): os.unlink(file_path) continue - tmp = dict_search('container_restart', container) - if tmp and name in tmp: + if 'container_restart' in container and name in container['container_restart']: cmd(f'systemctl restart vyos-container-{name}.service') if disabled_new: -- cgit v1.2.3 From b53c25a7bcd0a825cadf0e6c754297004ed3f0e4 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 1 Apr 2023 18:56:02 +0200 Subject: container: T4959: bugfix credential validation on registries Commit fe82d86d ("container: T4959: add registry authentication option") looked up the wrong config dict level when validating that both username and password need to be specified when registries are in use. --- src/conf_mode/container.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 5cfbfc30c..3827f4c70 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -258,9 +258,11 @@ def verify(container): if 'network' in container_config and network in container_config['network']: raise ConfigError(f'Can not remove network "{network}", used by container "{container}"!') - if 'registry' in container and 'authentication' in container['registry']: - for registry, registry_config in container['registry']['authentication'].items(): - if not {'username', 'password'} <= set(registry_config): + if 'registry' in container: + for registry, registry_config in container['registry'].items(): + if 'authentication' not in registry_config: + continue + if not {'username', 'password'} <= set(registry_config['authentication']): raise ConfigError('If registry username or or password is defined, so must be the other!') return None -- cgit v1.2.3 From 7d6731435410b16a2497dc0bc156fbde77797fb3 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Sat, 1 Apr 2023 18:44:25 +0000 Subject: T5125: Extend op-mode show sflow add new metric Add new metric, the number of packet-drop-events sent --- src/op_mode/sflow.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/op_mode/sflow.py b/src/op_mode/sflow.py index 1ff006274..ddb8bf44d 100755 --- a/src/op_mode/sflow.py +++ b/src/op_mode/sflow.py @@ -37,6 +37,7 @@ def _get_raw_sflow(): sflow, dbus_interface='net.sflow.hsflowd.telemetry') agent_address = sflow_telemetry.GetAgent() samples_dropped = int(sflow_telemetry.Get('dropped_samples')) + samples_drop_events_sent = int(sflow_telemetry.Get('event_samples')) samples_packet_sent = int(sflow_telemetry.Get('flow_samples')) samples_counter_sent = int(sflow_telemetry.Get('counter_samples')) datagrams_sent = int(sflow_telemetry.Get('datagrams')) @@ -52,6 +53,7 @@ def _get_raw_sflow(): 'sflow_servers': servers, 'counter_samples_sent': samples_counter_sent, 'datagrams_sent': datagrams_sent, + 'samples_drop_events_sent': samples_drop_events_sent, 'packet_samples_dropped': samples_dropped, 'packet_samples_sent': samples_packet_sent, 'rtmetric_samples': rtmetric_samples, @@ -67,10 +69,11 @@ def _get_formatted_sflow(data): ['Agent address', f'{data.get("agent_address")}'], ['sFlow interfaces', f'{data.get("sflow_interfaces", "n/a")}'], ['sFlow servers', f'{data.get("sflow_servers", "n/a")}'], + ['Counter samples sent', f'{data.get("counter_samples_sent")}'], ['Datagrams sent', f'{data.get("datagrams_sent")}'], ['Packet samples sent', f'{data.get("packet_samples_sent")}'], ['Packet samples dropped', f'{data.get("packet_samples_dropped")}'], - ['Counter samples sent', f'{data.get("counter_samples_sent")}'], + ['Samples drop events sent', f'{data.get("samples_drop_events_sent")}'], ['Flow samples suppressed', f'{data.get("flow_samples_suppressed")}'], ['Counter samples suppressed', f'{data.get("counter_samples_suppressed")}'] ] -- cgit v1.2.3 From 809f28f2b95a788d23db006a041955e7167a285d Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sun, 2 Apr 2023 09:25:35 +0200 Subject: xml: re-use generic-description.xml.i building block whenever possible Remove redundant XML CLI node definitions for the common description node by referencing the common building block. --- interface-definitions/bcast-relay.xml.in | 6 +----- interface-definitions/container.xml.in | 6 +----- interface-definitions/load-balancing-wan.xml.in | 10 +--------- interface-definitions/nat66.xml.in | 12 ++---------- interface-definitions/pki.xml.in | 12 ++---------- interface-definitions/service-webproxy.xml.in | 12 ++---------- interface-definitions/snmp.xml.in | 10 +--------- interface-definitions/vpn-l2tp.xml.in | 6 +----- 8 files changed, 11 insertions(+), 63 deletions(-) diff --git a/interface-definitions/bcast-relay.xml.in b/interface-definitions/bcast-relay.xml.in index aeaa5ab37..e2993f3f3 100644 --- a/interface-definitions/bcast-relay.xml.in +++ b/interface-definitions/bcast-relay.xml.in @@ -34,11 +34,7 @@ - - - Description - - + #include #include #include diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index b09536a16..b52054dd0 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -348,11 +348,7 @@ Network name cannot be longer than 11 characters - - - Network description - - + #include Prefix which allocated to that network diff --git a/interface-definitions/load-balancing-wan.xml.in b/interface-definitions/load-balancing-wan.xml.in index 2b812eb4d..c1d7e2c67 100644 --- a/interface-definitions/load-balancing-wan.xml.in +++ b/interface-definitions/load-balancing-wan.xml.in @@ -191,15 +191,7 @@ - - - Description for this rule - - txt - Description for this rule - - - + #include Destination diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in index 6ea611789..7a8970bdf 100644 --- a/interface-definitions/nat66.xml.in +++ b/interface-definitions/nat66.xml.in @@ -24,11 +24,7 @@ NAT66 rule number must be between 1 and 999999 - - - Rule description - - + #include Disable NAT66 rule @@ -156,11 +152,7 @@ NAT66 rule number must be between 1 and 999999 - - - Rule description - - + #include Disable NAT66 rule diff --git a/interface-definitions/pki.xml.in b/interface-definitions/pki.xml.in index c4fde2c78..a13a357fd 100644 --- a/interface-definitions/pki.xml.in +++ b/interface-definitions/pki.xml.in @@ -16,11 +16,7 @@ CA certificate in PEM format - - - Description - - + #include CA private key in PEM format @@ -63,11 +59,7 @@ Certificate in PEM format - - - Description - - + #include Certificate private key diff --git a/interface-definitions/service-webproxy.xml.in b/interface-definitions/service-webproxy.xml.in index a315aa2ef..b24997816 100644 --- a/interface-definitions/service-webproxy.xml.in +++ b/interface-definitions/service-webproxy.xml.in @@ -538,11 +538,7 @@ - - - Description for source-group - - + #include Domain for source-group @@ -644,11 +640,7 @@ - - - Time-period description - - + #include diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in index 592db7f4e..559e09388 100644 --- a/interface-definitions/snmp.xml.in +++ b/interface-definitions/snmp.xml.in @@ -78,15 +78,7 @@ Contact information is limited to 255 characters or less - - - Description information - - .{1,255} - - Description is limited to 255 characters or less - - + #include IP address to listen for incoming SNMP requests diff --git a/interface-definitions/vpn-l2tp.xml.in b/interface-definitions/vpn-l2tp.xml.in index 0a92017bd..6b64c5f5d 100644 --- a/interface-definitions/vpn-l2tp.xml.in +++ b/interface-definitions/vpn-l2tp.xml.in @@ -124,11 +124,7 @@ #include - - - Description for L2TP remote-access settings - - + #include #include -- cgit v1.2.3 From b65296a0ff39e66d87e916971477cce351f6d5a5 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sun, 2 Apr 2023 09:27:03 +0200 Subject: container: T5134: support binding container network to specific VRF Container networks now can be bound to a specific VRF instance. set vrf name table set container network vrf --- interface-definitions/container.xml.in | 1 + src/conf_mode/container.py | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index b52054dd0..9b6d2369d 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -367,6 +367,7 @@ + #include diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 3827f4c70..05595f86f 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -26,6 +26,8 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import node_changed from vyos.configdict import is_node_changed +from vyos.configverify import verify_vrf +from vyos.ifconfig import Interface from vyos.util import call from vyos.util import cmd from vyos.util import run @@ -250,6 +252,8 @@ def verify(container): if v6_prefix > 1: raise ConfigError(f'Only one IPv6 prefix can be defined for network "{network}"!') + # Verify VRF exists + verify_vrf(network_config) # A network attached to a container can not be deleted if {'network_remove', 'name'} <= set(container): @@ -469,6 +473,15 @@ def apply(container): if disabled_new: call('systemctl daemon-reload') + # Start network and assign it to given VRF if requested. this can only be done + # after the containers got started as the podman network interface will + # only be enabled by the first container and yet I do not know how to enable + # the network interface in advance + if 'network' in container: + for network, network_config in container['network'].items(): + tmp = Interface(f'podman-{network}') + tmp.set_vrf(network_config.get('vrf', '')) + return None if __name__ == '__main__': -- cgit v1.2.3 From 1b7534855f92ea307059bd01258746e45d6f79a5 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 3 Apr 2023 09:44:18 +0000 Subject: T5125: Sflow op-mode add event_samples_suppressed option Add "Packet drops suppressed" option Rename "Samples drop events sent" to "Packet drops sent" --- src/op_mode/sflow.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/op_mode/sflow.py b/src/op_mode/sflow.py index ddb8bf44d..88f70d6bd 100755 --- a/src/op_mode/sflow.py +++ b/src/op_mode/sflow.py @@ -37,11 +37,12 @@ def _get_raw_sflow(): sflow, dbus_interface='net.sflow.hsflowd.telemetry') agent_address = sflow_telemetry.GetAgent() samples_dropped = int(sflow_telemetry.Get('dropped_samples')) - samples_drop_events_sent = int(sflow_telemetry.Get('event_samples')) + packet_drop_sent = int(sflow_telemetry.Get('event_samples')) samples_packet_sent = int(sflow_telemetry.Get('flow_samples')) samples_counter_sent = int(sflow_telemetry.Get('counter_samples')) datagrams_sent = int(sflow_telemetry.Get('datagrams')) rtmetric_samples = int(sflow_telemetry.Get('rtmetric_samples')) + event_samples_suppressed = int(sflow_telemetry.Get('event_samples_suppressed')) samples_suppressed = int(sflow_telemetry.Get('flow_samples_suppressed')) counter_samples_suppressed = int( sflow_telemetry.Get("counter_samples_suppressed")) @@ -53,10 +54,11 @@ def _get_raw_sflow(): 'sflow_servers': servers, 'counter_samples_sent': samples_counter_sent, 'datagrams_sent': datagrams_sent, - 'samples_drop_events_sent': samples_drop_events_sent, + 'packet_drop_sent': packet_drop_sent, 'packet_samples_dropped': samples_dropped, 'packet_samples_sent': samples_packet_sent, 'rtmetric_samples': rtmetric_samples, + 'event_samples_suppressed': event_samples_suppressed, 'flow_samples_suppressed': samples_suppressed, 'counter_samples_suppressed': counter_samples_suppressed, 'hsflowd_version': version @@ -73,7 +75,8 @@ def _get_formatted_sflow(data): ['Datagrams sent', f'{data.get("datagrams_sent")}'], ['Packet samples sent', f'{data.get("packet_samples_sent")}'], ['Packet samples dropped', f'{data.get("packet_samples_dropped")}'], - ['Samples drop events sent', f'{data.get("samples_drop_events_sent")}'], + ['Packet drops sent', f'{data.get("packet_drop_sent")}'], + ['Packet drops suppressed', f'{data.get("event_samples_suppressed")}'], ['Flow samples suppressed', f'{data.get("flow_samples_suppressed")}'], ['Counter samples suppressed', f'{data.get("counter_samples_suppressed")}'] ] -- cgit v1.2.3 From 16a1a69d6e74166001b296a8f66c26c8c00be1f1 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 3 Apr 2023 10:48:16 +0000 Subject: T5139: IPSec add IKE lifetime 0 for no rekeying IKE lifetime should starting from 0 for disabling rekeying --- interface-definitions/vpn-ipsec.xml.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface-definitions/vpn-ipsec.xml.in b/interface-definitions/vpn-ipsec.xml.in index 1b3a5532e..64cfbda08 100644 --- a/interface-definitions/vpn-ipsec.xml.in +++ b/interface-definitions/vpn-ipsec.xml.in @@ -357,11 +357,11 @@ IKE lifetime - u32:30-86400 + u32:0-86400 IKE lifetime in seconds - + 28800 -- cgit v1.2.3 From 1a1f425f869f94c7c7a9d57b71555e9e13796c9e Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 3 Apr 2023 11:41:47 +0000 Subject: T5141: Add numbers for dhclient-exit-hooks.d to enforce order Add numbers for all dhclient-exit-hooks.d to enforce script order execution Also, move '99-run-user-hooks' to '98-run-user-hooks' due to vyatta-dhclient-hook bug and exit with 'exit 1' it is described in the https://vyos.dev/T4856, so we should move this hook to the end. Rename 'vyatta-dhclient-hook' to '99-vyatta-dhclient-hook' --- .../dhclient-exit-hooks.d/03-vyatta-dhclient-hook | 44 +++++++++++ .../dhcp/dhclient-exit-hooks.d/98-run-user-hooks | 5 ++ .../dhclient-exit-hooks.d/99-ipsec-dhclient-hook | 86 ++++++++++++++++++++++ .../dhcp/dhclient-exit-hooks.d/99-run-user-hooks | 5 -- .../dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook | 86 ---------------------- .../dhclient-exit-hooks.d/vyatta-dhclient-hook | 44 ----------- 6 files changed, 135 insertions(+), 135 deletions(-) create mode 100644 src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook create mode 100755 src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks create mode 100755 src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook delete mode 100755 src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks delete mode 100755 src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook delete mode 100644 src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook new file mode 100644 index 000000000..49bb18372 --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/03-vyatta-dhclient-hook @@ -0,0 +1,44 @@ +#!/bin/sh + +# Author: Stig Thormodsrud +# Date: 2007 +# Description: dhcp client hook + +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 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. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc. +# All Rights Reserved. +# **** End License **** + +# To enable this script set the following variable to "yes" +RUN="yes" + +proto="" +if [[ $reason =~ ^(REBOOT6|INIT6|EXPIRE6|RELEASE6|STOP6|INFORM6|BOUND6|REBIND6|DELEGATED6)$ ]]; then + proto="v6" +fi + +if [ "$RUN" = "yes" ]; then + LOG=/var/lib/dhcp/dhclient_"$interface"."$proto"lease + echo `date` > $LOG + + for i in reason interface new_expiry new_dhcp_lease_time medium \ + alias_ip_address new_ip_address new_broadcast_address \ + new_subnet_mask new_domain_name new_network_number \ + new_domain_name_servers new_routers new_static_routes \ + new_dhcp_server_identifier new_dhcp_message_type \ + old_ip_address old_subnet_mask old_domain_name \ + old_domain_name_servers old_routers \ + old_static_routes; do + echo $i=\'${!i}\' >> $LOG + done +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks b/src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks new file mode 100755 index 000000000..442419d79 --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks @@ -0,0 +1,5 @@ +#!/bin/bash +DHCP_POST_HOOKS="/config/scripts/dhcp-client/post-hooks.d/" +if [ -d "${DHCP_POST_HOOKS}" ] ; then + run-parts "${DHCP_POST_HOOKS}" +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook new file mode 100755 index 000000000..1f1926e17 --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/99-ipsec-dhclient-hook @@ -0,0 +1,86 @@ +#!/bin/bash +# +# Copyright (C) 2021 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 +# 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 . + +if [ "$reason" == "REBOOT" ] || [ "$reason" == "EXPIRE" ]; then + exit 0 +fi + +DHCP_HOOK_IFLIST="/tmp/ipsec_dhcp_waiting" + +if [ -f $DHCP_HOOK_IFLIST ] && [ "$reason" == "BOUND" ]; then + if grep -qw $interface $DHCP_HOOK_IFLIST; then + sudo rm $DHCP_HOOK_IFLIST + sudo /usr/libexec/vyos/conf_mode/vpn_ipsec.py + exit 0 + fi +fi + +if [ "$old_ip_address" == "$new_ip_address" ] && [ "$reason" == "BOUND" ]; then + exit 0 +fi + +python3 - < 0: + regex_match = re.search(r'(peer_[^:\[]+)', line) + if regex_match: + connection_name = regex_match[1] + break + if connection_name: + call(f'sudo ipsec down {connection_name}') + +if __name__ == '__main__': + interface = os.getenv('interface') + new_ip = os.getenv('new_ip_address') + old_ip = os.getenv('old_ip_address') + + if os.path.exists(SWANCTL_CONF): + conf_lines = read_file(SWANCTL_CONF) + found = False + to_match = f'# dhcp:{interface}' + + for i, line in enumerate(conf_lines): + if line.find(to_match) > 0: + conf_lines[i] = line.replace(old_ip, new_ip) + found = True + + for i, line in enumerate(secrets_lines): + if line.find(to_match) > 0: + secrets_lines[i] = line.replace(old_ip, new_ip) + + if found: + write_file(SWANCTL_CONF, conf_lines) + ipsec_down(old_ip) + call('sudo ipsec rereadall') + call('sudo ipsec reload') + call('sudo swanctl -q') + + exit(0) +PYEND \ No newline at end of file diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks b/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks deleted file mode 100755 index 442419d79..000000000 --- a/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -DHCP_POST_HOOKS="/config/scripts/dhcp-client/post-hooks.d/" -if [ -d "${DHCP_POST_HOOKS}" ] ; then - run-parts "${DHCP_POST_HOOKS}" -fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook deleted file mode 100755 index 1f1926e17..000000000 --- a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2021 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 -# 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 . - -if [ "$reason" == "REBOOT" ] || [ "$reason" == "EXPIRE" ]; then - exit 0 -fi - -DHCP_HOOK_IFLIST="/tmp/ipsec_dhcp_waiting" - -if [ -f $DHCP_HOOK_IFLIST ] && [ "$reason" == "BOUND" ]; then - if grep -qw $interface $DHCP_HOOK_IFLIST; then - sudo rm $DHCP_HOOK_IFLIST - sudo /usr/libexec/vyos/conf_mode/vpn_ipsec.py - exit 0 - fi -fi - -if [ "$old_ip_address" == "$new_ip_address" ] && [ "$reason" == "BOUND" ]; then - exit 0 -fi - -python3 - < 0: - regex_match = re.search(r'(peer_[^:\[]+)', line) - if regex_match: - connection_name = regex_match[1] - break - if connection_name: - call(f'sudo ipsec down {connection_name}') - -if __name__ == '__main__': - interface = os.getenv('interface') - new_ip = os.getenv('new_ip_address') - old_ip = os.getenv('old_ip_address') - - if os.path.exists(SWANCTL_CONF): - conf_lines = read_file(SWANCTL_CONF) - found = False - to_match = f'# dhcp:{interface}' - - for i, line in enumerate(conf_lines): - if line.find(to_match) > 0: - conf_lines[i] = line.replace(old_ip, new_ip) - found = True - - for i, line in enumerate(secrets_lines): - if line.find(to_match) > 0: - secrets_lines[i] = line.replace(old_ip, new_ip) - - if found: - write_file(SWANCTL_CONF, conf_lines) - ipsec_down(old_ip) - call('sudo ipsec rereadall') - call('sudo ipsec reload') - call('sudo swanctl -q') - - exit(0) -PYEND \ No newline at end of file diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook deleted file mode 100644 index 49bb18372..000000000 --- a/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -# Author: Stig Thormodsrud -# Date: 2007 -# Description: dhcp client hook - -# **** License **** -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 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. -# -# This code was originally developed by Vyatta, Inc. -# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc. -# All Rights Reserved. -# **** End License **** - -# To enable this script set the following variable to "yes" -RUN="yes" - -proto="" -if [[ $reason =~ ^(REBOOT6|INIT6|EXPIRE6|RELEASE6|STOP6|INFORM6|BOUND6|REBIND6|DELEGATED6)$ ]]; then - proto="v6" -fi - -if [ "$RUN" = "yes" ]; then - LOG=/var/lib/dhcp/dhclient_"$interface"."$proto"lease - echo `date` > $LOG - - for i in reason interface new_expiry new_dhcp_lease_time medium \ - alias_ip_address new_ip_address new_broadcast_address \ - new_subnet_mask new_domain_name new_network_number \ - new_domain_name_servers new_routers new_static_routes \ - new_dhcp_server_identifier new_dhcp_message_type \ - old_ip_address old_subnet_mask old_domain_name \ - old_domain_name_servers old_routers \ - old_static_routes; do - echo $i=\'${!i}\' >> $LOG - done -fi -- cgit v1.2.3 From 3f3621b6874354fbf824171bfe2e3aed6360482f Mon Sep 17 00:00:00 2001 From: Indrajit Raychaudhuri Date: Mon, 3 Apr 2023 18:24:29 -0500 Subject: dns: T5144: Improve dns dynamic status output Improve and fix the output of dynamic dns status to be compatible with new ddclient cache format. Additional details: - The status output is now formatted as a table with per-host dual-stack information in rows. Columns not having actual value present in the output will be kept empty. - The 'Last update' column is now formatted in Local time format instead of UTC. --- src/op_mode/dynamic_dns.py | 72 +++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/src/op_mode/dynamic_dns.py b/src/op_mode/dynamic_dns.py index 263a3b6a5..2cba33cc8 100755 --- a/src/op_mode/dynamic_dns.py +++ b/src/op_mode/dynamic_dns.py @@ -16,69 +16,63 @@ import os import argparse -import jinja2 import sys import time +from tabulate import tabulate from vyos.config import Config from vyos.util import call cache_file = r'/run/ddclient/ddclient.cache' -OUT_TMPL_SRC = """ -{% for entry in hosts %} -ip address : {{ entry.ip }} -host-name : {{ entry.host }} -last update : {{ entry.time }} -update-status: {{ entry.status }} +columns = { + 'host': 'Hostname', + 'ipv4': 'IPv4 address', + 'status-ipv4': 'IPv4 status', + 'ipv6': 'IPv6 address', + 'status-ipv6': 'IPv6 status', + 'mtime': 'Last update', +} + + +def _get_formatted_host_records(host_data): + data_entries = [] + for entry in host_data: + data_entries.append([entry.get(key) for key in columns.keys()]) + + header = columns.values() + output = tabulate(data_entries, header, numalign='left') + return output -{% endfor %} -""" def show_status(): # A ddclient status file must not always exist if not os.path.exists(cache_file): sys.exit(0) - data = { - 'hosts': [] - } + data = [] with open(cache_file, 'r') as f: for line in f: if line.startswith('#'): continue - outp = { - 'host': '', - 'ip': '', - 'time': '' - } - - if 'host=' in line: - host = line.split('host=')[1] - if host: - outp['host'] = host.split(',')[0] - - if 'ip=' in line: - ip = line.split('ip=')[1] - if ip: - outp['ip'] = ip.split(',')[0] - - if 'mtime=' in line: - mtime = line.split('mtime=')[1] - if mtime: - outp['time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(mtime.split(',')[0], base=10))) + props = {} + # ddclient cache rows have properties in 'key=value' format separated by comma + # we pick up the ones we are interested in + for kvraw in line.split(' ')[0].split(','): + k, v = kvraw.split('=') + if k in columns.keys(): + props[k] = v - if 'status=' in line: - status = line.split('status=')[1] - if status: - outp['status'] = status.split(',')[0] + # Convert mtime to human readable format + if 'mtime' in props: + props['mtime'] = time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(int(props['mtime'], base=10))) - data['hosts'].append(outp) + data.append(props) - tmpl = jinja2.Template(OUT_TMPL_SRC) - print(tmpl.render(data)) + print(_get_formatted_host_records(data)) def update_ddns(): -- cgit v1.2.3 From d6ef0c54ad8c8f9f2c5f1811781dba6111201fe4 Mon Sep 17 00:00:00 2001 From: Cheeze_It Date: Sun, 19 Mar 2023 19:24:50 -0600 Subject: T5081: ISIS and OSPF syncronization with IGP-LDP sync --- data/templates/frr/isisd.frr.j2 | 11 ++++++ data/templates/frr/ospfd.frr.j2 | 11 ++++++ .../include/isis/protocol-common-config.xml.i | 4 +- .../include/ldp-sync-interface.xml.i | 22 +++++++++++ .../include/ldp-sync-protocol.xml.i | 21 +++++++++++ .../include/ospf/protocol-common-config.xml.i | 4 +- op-mode-definitions/include/isis-common.xml.i | 26 ++++++++++++- op-mode-definitions/include/ospf-common.xml.i | 26 ++++++++++++- smoketest/scripts/cli/test_protocols_isis.py | 43 ++++++++++++++++++++++ smoketest/scripts/cli/test_protocols_ospf.py | 41 +++++++++++++++++++++ 10 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 interface-definitions/include/ldp-sync-interface.xml.i create mode 100644 interface-definitions/include/ldp-sync-protocol.xml.i diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2 index 8df1e9513..3c37e28b9 100644 --- a/data/templates/frr/isisd.frr.j2 +++ b/data/templates/frr/isisd.frr.j2 @@ -25,6 +25,12 @@ interface {{ iface }} {% if iface_config.hello_padding is vyos_defined %} isis hello padding {% endif %} +{% if iface_config.ldp_sync.disable is vyos_defined %} + no isis mpls ldp-sync +{% elif iface_config.ldp_sync.holddown is vyos_defined %} + isis mpls ldp-sync + isis mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }} +{% endif %} {% if iface_config.metric is vyos_defined %} isis metric {{ iface_config.metric }} {% endif %} @@ -84,6 +90,11 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} {% if max_lsp_lifetime is vyos_defined %} max-lsp-lifetime {{ max_lsp_lifetime }} {% endif %} +{% if ldp_sync.holddown is vyos_defined %} + mpls ldp-sync holddown {{ ldp_sync.holddown }} +{% elif ldp_sync is vyos_defined %} + mpls ldp-sync +{% endif %} {% if spf_interval is vyos_defined %} spf-interval {{ spf_interval }} {% endif %} diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 index 8c4a81c57..3f97b7325 100644 --- a/data/templates/frr/ospfd.frr.j2 +++ b/data/templates/frr/ospfd.frr.j2 @@ -44,6 +44,12 @@ interface {{ iface }} {% if iface_config.bfd.profile is vyos_defined %} ip ospf bfd profile {{ iface_config.bfd.profile }} {% endif %} +{% if iface_config.ldp_sync.disable is vyos_defined %} + no ip ospf mpls ldp-sync +{% elif iface_config.ldp_sync.holddown is vyos_defined %} + ip ospf mpls ldp-sync + ip ospf mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }} +{% endif %} {% if iface_config.mtu_ignore is vyos_defined %} ip ospf mtu-ignore {% endif %} @@ -133,6 +139,11 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if maximum_paths is vyos_defined %} maximum-paths {{ maximum_paths }} {% endif %} +{% if ldp_sync.holddown is vyos_defined %} + mpls ldp-sync holddown {{ ldp_sync.holddown }} +{% elif ldp_sync is vyos_defined %} + mpls ldp-sync +{% endif %} {% if distance.global is vyos_defined %} distance {{ distance.global }} {% endif %} diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 0e6f19480..983a085ec 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -152,6 +152,7 @@ +#include A Network Entity Title for this process (ISO only) @@ -172,7 +173,7 @@ - Show IS-IS neighbor adjacencies + IS-IS traffic engineering extensions @@ -631,6 +632,7 @@ #include + #include Set network type diff --git a/interface-definitions/include/ldp-sync-interface.xml.i b/interface-definitions/include/ldp-sync-interface.xml.i new file mode 100644 index 000000000..b24831bbe --- /dev/null +++ b/interface-definitions/include/ldp-sync-interface.xml.i @@ -0,0 +1,22 @@ + + + + LDP-IGP synchronization configuration for interface + + + #include + + + Hold down timer for LDP-IGP cost restoration + + u32:0-10000 + Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost + + + + + + + + + diff --git a/interface-definitions/include/ldp-sync-protocol.xml.i b/interface-definitions/include/ldp-sync-protocol.xml.i new file mode 100644 index 000000000..c82c811f6 --- /dev/null +++ b/interface-definitions/include/ldp-sync-protocol.xml.i @@ -0,0 +1,21 @@ + + + + Protocol wide LDP-IGP synchronization configuration + + + + + Protocol wide hold down timer for LDP-IGP cost restoration + + u32:0-10000 + Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost + + + + + + + + + diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 25b54b181..c2a910710 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -331,6 +331,7 @@ +#include Administrative distance @@ -385,6 +386,7 @@ #include #include #include + #include Interface bandwidth (Mbit/s) @@ -875,4 +877,4 @@ - + \ No newline at end of file diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 95a171515..7b4d31029 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -54,6 +54,30 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show IS-IS MPLS specific information + + + + + Show IS-IS LDP-IGP synchronization information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show specific IS-IS LDP-IGP synchronization for an interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + Show IS-IS MPLS traffic engineering information @@ -176,4 +200,4 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + \ No newline at end of file diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index 098254f4e..7d9e541cf 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -517,6 +517,30 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show OSPF MPLS specific information + + + + + Show OSPF LDP-IGP synchronization information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show specific OSPF LDP-IGP synchronization for an interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + Show IPv4 OSPF neighbor information @@ -547,4 +571,4 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + \ No newline at end of file diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index d11d80a1f..61e29c449 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -308,5 +308,48 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' segment-routing prefix {prefix_three} absolute {prefix_three_value} explicit-null', tmp) self.assertIn(f' segment-routing prefix {prefix_four} absolute {prefix_four_value} no-php-flag', tmp) + def test_isis_08_ldp_sync(self): + holddown = "500" + interface = 'lo' + + self.cli_set(base_path + ['net', net]) + self.cli_set(base_path + ['interface', interface]) + self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) + + # Commit main ISIS changes + self.cli_commit() + + # Verify main ISIS changes + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') + self.assertIn(f' net {net}', tmp) + self.assertIn(f' mpls ldp-sync', tmp) + self.assertIn(f' mpls ldp-sync holddown {holddown}', tmp) + + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) + + # Commit interface changes for holddown + self.cli_commit() + + # Verify interface changes for holddown + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f'interface {interface}', tmp) + self.assertIn(f' ip router isis {domain}', tmp) + self.assertIn(f' ipv6 router isis {domain}', tmp) + self.assertIn(f' isis mpls ldp-sync holddown {holddown}', tmp) + + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) + + # Commit interface changes for disable + self.cli_commit() + + # Verify interface changes for disable + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f'interface {interface}', tmp) + self.assertIn(f' ip router isis {domain}', tmp) + self.assertIn(f' ipv6 router isis {domain}', tmp) + self.assertIn(f' no isis mpls ldp-sync', tmp) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 581959b15..d4c85f2b2 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -434,6 +434,47 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' segment-routing prefix {prefix_one} index {prefix_one_value} explicit-null', frrconfig) self.assertIn(f' segment-routing prefix {prefix_two} index {prefix_two_value} no-php-flag', frrconfig) + def test_ospf_15_ldp_sync(self): + holddown = "500" + interface = 'lo' + interfaces = Section.interfaces('ethernet') + + self.cli_set(base_path + ['interface', interface]) + self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) + + # Commit main OSPF changes + self.cli_commit() + + # Verify main OSPF changes + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) + self.assertIn(f' mpls ldp-sync holddown {holddown}', frrconfig) + + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) + + # Commit interface changes for holddown + self.cli_commit() + + # Verify interface changes for holddown + config = self.getFRRconfig(f'interface {interface}') + self.assertIn(f'interface {interface}', config) + self.assertIn(f' ip ospf dead-interval 40', config) + self.assertIn(f' ip ospf mpls ldp-sync', config) + self.assertIn(f' ip ospf mpls ldp-sync holddown {holddown}', config) + + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) + + # Commit interface changes for disable + self.cli_commit() + + # Verify interface changes for disable + config = self.getFRRconfig(f'interface {interface}') + self.assertIn(f'interface {interface}', config) + self.assertIn(f' ip ospf dead-interval 40', config) + self.assertIn(f' no ip ospf mpls ldp-sync', config) if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From 8afe702361df75049329c0db3ce7f91127498f54 Mon Sep 17 00:00:00 2001 From: Indrajit Raychaudhuri Date: Mon, 3 Apr 2023 16:07:55 -0500 Subject: dns: T5143: Apply constraint for domain name in DNS forwarding This will prevent arbitrary strings from being entered as domain names. Additionally, reuse the fqdn validator instead of a custom regex. --- interface-definitions/dns-forwarding.xml.in | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index 14b38b24d..2b6892ce5 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -83,6 +83,13 @@ Domain to forward to a custom DNS server + + text + An absolute DNS domain name + + + + #include @@ -105,10 +112,10 @@ Domain to host authoritative records for text - An absolute DNS name + An absolute DNS domain name - [-_a-zA-Z0-9.]{1,63} + -- cgit v1.2.3 From a3ce38b4a2901745cb1e2fd3271673ee98ba4214 Mon Sep 17 00:00:00 2001 From: aapostoliuk Date: Tue, 4 Apr 2023 13:00:20 +0300 Subject: opennhrp: T5135: Rewritten opennhrp script using vyos.ipsec Rewritten opennhrp script using vyos.ipsec library --- src/etc/opennhrp/opennhrp-script.py | 39 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/etc/opennhrp/opennhrp-script.py b/src/etc/opennhrp/opennhrp-script.py index bf25a7331..688c7af2a 100755 --- a/src/etc/opennhrp/opennhrp-script.py +++ b/src/etc/opennhrp/opennhrp-script.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -17,7 +17,7 @@ import os import re import sys -import vici +import vyos.ipsec from json import loads from pathlib import Path @@ -51,9 +51,8 @@ def vici_get_ipsec_uniqueid(conn: str, src_nbma: str, logger.info( f'Resolving IKE unique ids for: conn: {conn}, ' f'src_nbma: {src_nbma}, dst_nbma: {dst_nbma}') - session: vici.Session = vici.Session() list_ikeid: list[str] = [] - list_sa = session.list_sas({'ike': conn}) + list_sa: list = vyos.ipsec.get_vici_sas_by_name(conn, None) for sa in list_sa: if sa[conn]['local-host'].decode('ascii') == src_nbma \ and sa[conn]['remote-host'].decode('ascii') == dst_nbma: @@ -78,16 +77,7 @@ def vici_ike_terminate(list_ikeid: list[str]) -> bool: return False try: - session = vici.Session() - for ikeid in list_ikeid: - logger.info(f'Terminating IKE SA with id {ikeid}') - session_generator = session.terminate( - {'ike-id': ikeid, 'timeout': '-1'}) - # a dummy `for` loop is required because of requirements - # from vici. Without a full iteration on the output, the - # command to vici may not be executed completely - for _ in session_generator: - pass + vyos.ipsec.terminate_vici_ikeid_list(list_ikeid) return True except Exception as err: logger.error(f'Failed to terminate SA for IKE ids {list_ikeid}: {err}') @@ -180,19 +170,7 @@ def vici_initiate(conn: str, child_sa: str, src_addr: str, f'Trying to initiate connection. Name: {conn}, child sa: {child_sa}, ' f'src_addr: {src_addr}, dst_addr: {dest_addr}') try: - session = vici.Session() - session_generator = session.initiate({ - 'ike': conn, - 'child': child_sa, - 'timeout': '-1', - 'my-host': src_addr, - 'other-host': dest_addr - }) - # a dummy `for` loop is required because of requirements - # from vici. Without a full iteration on the output, the - # command to vici may not be executed completely - for _ in session_generator: - pass + vyos.ipsec.vici_initiate(conn, child_sa, src_addr, dest_addr) return True except Exception as err: logger.error(f'Unable to initiate connection {err}') @@ -218,8 +196,11 @@ def vici_terminate(conn: str, src_addr: str, dest_addr: str) -> None: f'No active sessions found for IKE profile {conn}, ' f'local NBMA {src_addr}, remote NBMA {dest_addr}') else: - vici_ike_terminate(ikeid_list) - + try: + vyos.ipsec.terminate_vici_ikeid_list(ikeid_list) + except Exception as err: + logger.error( + f'Failed to terminate SA for IKE ids {ikeid_list}: {err}') def iface_up(interface: str) -> None: """Proceed tunnel interface UP event -- cgit v1.2.3 From f72fa135986186544b6125481bae4691ddd4dded Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 4 Apr 2023 10:36:24 +0000 Subject: T5142: Add audit tool to monitor security-relevant events --- debian/control | 2 ++ op-mode-definitions/show-log.xml.in | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/debian/control b/debian/control index 8cd49f62a..856f57030 100644 --- a/debian/control +++ b/debian/control @@ -35,6 +35,7 @@ Architecture: amd64 arm64 Depends: ${python3:Depends}, accel-ppp, + auditd, avahi-daemon, beep, bmon, @@ -80,6 +81,7 @@ Depends: lcdproc, lcdproc-extra-drivers, libatomic1, + libauparse0, libbpf1 [amd64], libcharon-extra-plugins (>=5.9), libcharon-extauth-plugins (>=5.9), diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 7f6469ca9..7663e4c00 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -8,6 +8,12 @@ journalctl --no-hostname --boot + + + Show audit logs + + cat /var/log/audit/audit.log + Show contents of all master log files -- cgit v1.2.3 From a1ffb5e73760e0caaca2deb8fc5a18840f968f1c Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 4 Apr 2023 14:10:56 +0000 Subject: T5145: Add maximum number of all logins on system maxsyslogins maximum number of all logins on system; user is not allowed to log-in if total number of all user logins is greater than specified number (this limit does not apply to user with uid=0) set system login max-login-session 2 --- data/templates/login/limits.j2 | 5 +++++ interface-definitions/system-login.xml.in | 13 +++++++++++++ smoketest/scripts/cli/test_system_login.py | 23 ++++++++++++++++++++++- src/conf_mode/system-login.py | 14 +++++++++++++- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 data/templates/login/limits.j2 diff --git a/data/templates/login/limits.j2 b/data/templates/login/limits.j2 new file mode 100644 index 000000000..5e2c11f35 --- /dev/null +++ b/data/templates/login/limits.j2 @@ -0,0 +1,5 @@ +# Generated by /usr/libexec/vyos/conf_mode/system-login.py + +{% if max_login_session is vyos_defined %} +* - maxsyslogins {{ max_login_session }} +{% endif %} diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in index b00741ffe..258913929 100644 --- a/interface-definitions/system-login.xml.in +++ b/interface-definitions/system-login.xml.in @@ -225,6 +225,19 @@ #include + + + Maximum number of all login sessions + + u32:1-65536 + Maximum number of all login sessions + + + + + Maximum logins must be between 1 and 65536 + + Session timeout diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 6006fe0f6..a1d2ba2ad 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-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 @@ -264,5 +264,26 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): tmp = re.findall(r'group:\s+mapname\s+files', nsswitch_conf) self.assertTrue(tmp) + def test_system_login_max_login_session(self): + max_logins = '2' + timeout = '600' + + self.cli_set(base_path + ['max-login-session', max_logins]) + + # 'max-login-session' must be only with 'timeout' option + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['timeout', timeout]) + + self.cli_commit() + + security_limits = read_file('/etc/security/limits.d/10-vyos.conf') + self.assertIn(f'* - maxsyslogins {max_logins}', security_limits) + + self.cli_delete(base_path + ['timeout']) + self.cli_delete(base_path + ['max-login-session']) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index d15fe399d..fbb013cf3 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2022 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 @@ -40,6 +40,7 @@ from vyos import airbag airbag.enable() autologout_file = "/etc/profile.d/autologout.sh" +limits_file = "/etc/security/limits.d/10-vyos.conf" radius_config_file = "/etc/pam_radius_auth.conf" # LOGIN_TIMEOUT from /etc/loign.defs minus 10 sec @@ -164,6 +165,9 @@ def verify(login): if ipv6_count > 1: raise ConfigError('Only one IPv6 source-address can be set!') + if 'max_login_session' in login and 'timeout' not in login: + raise ConfigError('"login timeout" must be configured!') + return None @@ -226,6 +230,14 @@ def generate(login): if os.path.isfile(radius_config_file): os.unlink(radius_config_file) + # /etc/security/limits.d/10-vyos.conf + if 'max_login_session' in login: + render(limits_file, 'login/limits.j2', login, + permission=0o644, user='root', group='root') + else: + if os.path.isfile(limits_file): + os.unlink(limits_file) + if 'timeout' in login: render(autologout_file, 'login/autologout.j2', login, permission=0o755, user='root', group='root') -- cgit v1.2.3 From 3ffb5ff16543576e73f23125e4590fa57b02f0b7 Mon Sep 17 00:00:00 2001 From: Cheeze_It Date: Sun, 19 Mar 2023 19:24:50 -0600 Subject: T5081: ISIS and OSPF syncronization with IGP-LDP sync --- data/templates/frr/isisd.frr.j2 | 11 ++++++ data/templates/frr/ospfd.frr.j2 | 11 ++++++ .../include/isis/protocol-common-config.xml.i | 4 +- .../include/ldp-sync-interface.xml.i | 22 +++++++++++ .../include/ldp-sync-protocol.xml.i | 21 +++++++++++ .../include/ospf/protocol-common-config.xml.i | 4 +- op-mode-definitions/include/isis-common.xml.i | 26 ++++++++++++- op-mode-definitions/include/ospf-common.xml.i | 26 ++++++++++++- smoketest/scripts/cli/test_protocols_isis.py | 43 ++++++++++++++++++++++ smoketest/scripts/cli/test_protocols_ospf.py | 41 +++++++++++++++++++++ 10 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 interface-definitions/include/ldp-sync-interface.xml.i create mode 100644 interface-definitions/include/ldp-sync-protocol.xml.i diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2 index 8df1e9513..3c37e28b9 100644 --- a/data/templates/frr/isisd.frr.j2 +++ b/data/templates/frr/isisd.frr.j2 @@ -25,6 +25,12 @@ interface {{ iface }} {% if iface_config.hello_padding is vyos_defined %} isis hello padding {% endif %} +{% if iface_config.ldp_sync.disable is vyos_defined %} + no isis mpls ldp-sync +{% elif iface_config.ldp_sync.holddown is vyos_defined %} + isis mpls ldp-sync + isis mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }} +{% endif %} {% if iface_config.metric is vyos_defined %} isis metric {{ iface_config.metric }} {% endif %} @@ -84,6 +90,11 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} {% if max_lsp_lifetime is vyos_defined %} max-lsp-lifetime {{ max_lsp_lifetime }} {% endif %} +{% if ldp_sync.holddown is vyos_defined %} + mpls ldp-sync holddown {{ ldp_sync.holddown }} +{% elif ldp_sync is vyos_defined %} + mpls ldp-sync +{% endif %} {% if spf_interval is vyos_defined %} spf-interval {{ spf_interval }} {% endif %} diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 index 8c4a81c57..3f97b7325 100644 --- a/data/templates/frr/ospfd.frr.j2 +++ b/data/templates/frr/ospfd.frr.j2 @@ -44,6 +44,12 @@ interface {{ iface }} {% if iface_config.bfd.profile is vyos_defined %} ip ospf bfd profile {{ iface_config.bfd.profile }} {% endif %} +{% if iface_config.ldp_sync.disable is vyos_defined %} + no ip ospf mpls ldp-sync +{% elif iface_config.ldp_sync.holddown is vyos_defined %} + ip ospf mpls ldp-sync + ip ospf mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }} +{% endif %} {% if iface_config.mtu_ignore is vyos_defined %} ip ospf mtu-ignore {% endif %} @@ -133,6 +139,11 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if maximum_paths is vyos_defined %} maximum-paths {{ maximum_paths }} {% endif %} +{% if ldp_sync.holddown is vyos_defined %} + mpls ldp-sync holddown {{ ldp_sync.holddown }} +{% elif ldp_sync is vyos_defined %} + mpls ldp-sync +{% endif %} {% if distance.global is vyos_defined %} distance {{ distance.global }} {% endif %} diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 0e6f19480..983a085ec 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -152,6 +152,7 @@ +#include A Network Entity Title for this process (ISO only) @@ -172,7 +173,7 @@ - Show IS-IS neighbor adjacencies + IS-IS traffic engineering extensions @@ -631,6 +632,7 @@ #include + #include Set network type diff --git a/interface-definitions/include/ldp-sync-interface.xml.i b/interface-definitions/include/ldp-sync-interface.xml.i new file mode 100644 index 000000000..b24831bbe --- /dev/null +++ b/interface-definitions/include/ldp-sync-interface.xml.i @@ -0,0 +1,22 @@ + + + + LDP-IGP synchronization configuration for interface + + + #include + + + Hold down timer for LDP-IGP cost restoration + + u32:0-10000 + Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost + + + + + + + + + diff --git a/interface-definitions/include/ldp-sync-protocol.xml.i b/interface-definitions/include/ldp-sync-protocol.xml.i new file mode 100644 index 000000000..c82c811f6 --- /dev/null +++ b/interface-definitions/include/ldp-sync-protocol.xml.i @@ -0,0 +1,21 @@ + + + + Protocol wide LDP-IGP synchronization configuration + + + + + Protocol wide hold down timer for LDP-IGP cost restoration + + u32:0-10000 + Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost + + + + + + + + + diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index f39b9c5e3..425d3b01c 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -331,6 +331,7 @@ +#include Administrative distance @@ -385,6 +386,7 @@ #include #include #include + #include Interface bandwidth (Mbit/s) @@ -875,4 +877,4 @@ - + \ No newline at end of file diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 0e20861c7..53e85a7ef 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -54,6 +54,30 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show IS-IS MPLS specific information + + + + + Show IS-IS LDP-IGP synchronization information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show specific IS-IS LDP-IGP synchronization for an interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + Show IS-IS MPLS traffic engineering information @@ -176,4 +200,4 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + \ No newline at end of file diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index 098254f4e..7d9e541cf 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -517,6 +517,30 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show OSPF MPLS specific information + + + + + Show OSPF LDP-IGP synchronization information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show specific OSPF LDP-IGP synchronization for an interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + Show IPv4 OSPF neighbor information @@ -547,4 +571,4 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + \ No newline at end of file diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index d11d80a1f..61e29c449 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -308,5 +308,48 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' segment-routing prefix {prefix_three} absolute {prefix_three_value} explicit-null', tmp) self.assertIn(f' segment-routing prefix {prefix_four} absolute {prefix_four_value} no-php-flag', tmp) + def test_isis_08_ldp_sync(self): + holddown = "500" + interface = 'lo' + + self.cli_set(base_path + ['net', net]) + self.cli_set(base_path + ['interface', interface]) + self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) + + # Commit main ISIS changes + self.cli_commit() + + # Verify main ISIS changes + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') + self.assertIn(f' net {net}', tmp) + self.assertIn(f' mpls ldp-sync', tmp) + self.assertIn(f' mpls ldp-sync holddown {holddown}', tmp) + + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) + + # Commit interface changes for holddown + self.cli_commit() + + # Verify interface changes for holddown + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f'interface {interface}', tmp) + self.assertIn(f' ip router isis {domain}', tmp) + self.assertIn(f' ipv6 router isis {domain}', tmp) + self.assertIn(f' isis mpls ldp-sync holddown {holddown}', tmp) + + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) + + # Commit interface changes for disable + self.cli_commit() + + # Verify interface changes for disable + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f'interface {interface}', tmp) + self.assertIn(f' ip router isis {domain}', tmp) + self.assertIn(f' ipv6 router isis {domain}', tmp) + self.assertIn(f' no isis mpls ldp-sync', tmp) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 581959b15..d4c85f2b2 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -434,6 +434,47 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' segment-routing prefix {prefix_one} index {prefix_one_value} explicit-null', frrconfig) self.assertIn(f' segment-routing prefix {prefix_two} index {prefix_two_value} no-php-flag', frrconfig) + def test_ospf_15_ldp_sync(self): + holddown = "500" + interface = 'lo' + interfaces = Section.interfaces('ethernet') + + self.cli_set(base_path + ['interface', interface]) + self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) + + # Commit main OSPF changes + self.cli_commit() + + # Verify main OSPF changes + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) + self.assertIn(f' mpls ldp-sync holddown {holddown}', frrconfig) + + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) + + # Commit interface changes for holddown + self.cli_commit() + + # Verify interface changes for holddown + config = self.getFRRconfig(f'interface {interface}') + self.assertIn(f'interface {interface}', config) + self.assertIn(f' ip ospf dead-interval 40', config) + self.assertIn(f' ip ospf mpls ldp-sync', config) + self.assertIn(f' ip ospf mpls ldp-sync holddown {holddown}', config) + + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) + + # Commit interface changes for disable + self.cli_commit() + + # Verify interface changes for disable + config = self.getFRRconfig(f'interface {interface}') + self.assertIn(f'interface {interface}', config) + self.assertIn(f' ip ospf dead-interval 40', config) + self.assertIn(f' no ip ospf mpls ldp-sync', config) if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From 5f94bde6d6024b753765d28d2fdb69806f1968b5 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 6 Apr 2023 08:05:19 +0200 Subject: container: T5147: ensure container network exists before VRF operation Networks are started only as soon as there is a consumer. If only a network is created in the first place, no need to assign it to a VRF as there's no consumer, yet. --- src/conf_mode/container.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 05595f86f..4b7ab3444 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -479,8 +479,13 @@ def apply(container): # the network interface in advance if 'network' in container: for network, network_config in container['network'].items(): - tmp = Interface(f'podman-{network}') - tmp.set_vrf(network_config.get('vrf', '')) + network_name = f'podman-{network}' + # T5147: Networks are started only as soon as there is a consumer. + # If only a network is created in the first place, no need to assign + # it to a VRF as there's no consumer, yet. + if os.path.exists(f'/sys/class/net/{network_name}'): + tmp = Interface(network_name) + tmp.set_vrf(network_config.get('vrf', '')) return None -- cgit v1.2.3 From f14de93cdb1d1e366603d10d8d51994d9eb4bb8b Mon Sep 17 00:00:00 2001 From: mkorobeinikov <92354771+mkorobeinikov@users.noreply.github.com> Date: Sun, 2 Apr 2023 07:29:14 +0300 Subject: T5137: refactoring the tech-support command Refactoring the tech-support command from .sh to .py --- op-mode-definitions/show-techsupport_report.xml.in | 17 + src/op_mode/show_techsupport_report.py | 438 +++++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100644 op-mode-definitions/show-techsupport_report.xml.in create mode 100644 src/op_mode/show_techsupport_report.py diff --git a/op-mode-definitions/show-techsupport_report.xml.in b/op-mode-definitions/show-techsupport_report.xml.in new file mode 100644 index 000000000..6f38105f8 --- /dev/null +++ b/op-mode-definitions/show-techsupport_report.xml.in @@ -0,0 +1,17 @@ + + + + + + + + + Show consolidated tech-support report (contains private information) + + ${vyos_op_scripts_dir}/show_techsupport_report.py + + + + + + diff --git a/src/op_mode/show_techsupport_report.py b/src/op_mode/show_techsupport_report.py new file mode 100644 index 000000000..13ed9a3c1 --- /dev/null +++ b/src/op_mode/show_techsupport_report.py @@ -0,0 +1,438 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +from vyos.util import call +import os + + +def header(cmd): + print(16 * '-' + '\n' + cmd + '\n' + 16 * '-') + return + + +# get intefaces info +interfaces_list = os.popen('ls /sys/class/net/ | grep eth').read().split() +bridges_list = os.popen('ls /sys/class/net/ | grep br').read().split() + +###################### THE PART OF CONFIGURATION ###################### + +cmd_list_conf = [ + "VyOS Version and Package Changes%/opt/vyatta/bin/vyatta-op-cmd-wrapper show version all", + "Configuration File%cat /opt/vyatta/etc/config/config.boot", + "Running configuration%/opt/vyatta/bin/vyatta-op-cmd-wrapper show configuration", + "Package Repository Configuration File%cat /etc/apt/sources.list", + "User Startup Scripts%cat /etc/rc.local", + "Quagga Configuration%vtysh -c 'show run'" +] + + +def CONFIGURATION(cmd): + for command_line in cmd: + line = command_line.split('%') + head = line[0] + command = line[1] + header(head) + call(command) + return + + +###################### THE PART OF INTERFACES ###################### + +cmd_list_int = [ + "Interfaces%/opt/vyatta/bin/vyatta-op-cmd-wrapper show interfaces", + "Ethernet", + "Interface statistics%ip -s link show", + "Physical Interface statistics for%ethtool -S", + "Physical Interface Details for %/opt/vyatta/bin/vyatta-op-cmd-wrapper show interfaces ethernet%ethtool -k $eth", + "ARP Table (Total entries)%/opt/vyatta/bin/vyatta-op-cmd-wrapper show arp", + "Number of incomplete entries in ARP table%show arp | grep incomplete | wc -l", + "Bridges" +] + + +def INTERFACES(cmd): + for command_line in cmd: + line = command_line.split('%') + head = line[0] + if command_line.startswith("Ethernet"): + header(command_line) + elif command_line.startswith("Physical Interface statistics"): + for command_interface in interfaces_list: + header(f'{head} {command_interface}') + call(f'{line[1]} {command_interface}') + elif command_line.startswith("Physical Interface Details"): + for command_interface in interfaces_list: + header(f'{head} {command_interface}') + call(f'{line[1]} {command_interface} physical') + call(f'{line[2]} {command_interface}') + elif command_line.startswith("Bridges"): + header(command_line) + for command_interface in bridges_list: + header(f'Information for {command_interface}') + call(f'/sbin/brctl showstp {command_interface}') + call(f'/sbin/brctl showmacs {command_interface}') + else: + command = line[1] + header(head) + call(command) + return + + +###################### THE PART OF ROUTING ###################### + +cmd_list_route = [ + "show ip route bgp", + "show ip route cache", + "show ip route connected", + "show ip route forward", + "show ip route isis", + "show ip route kernel", + "show ip route ospf", + "show ip route rip", + "show ip route static", + "show ip route summary", + "show ip route supernets-only", + "show ip route table", + "show ip route tag", + "show ip route vrf", + "show ipv6 route bgp", + "show ipv6 route cache", + "show ipv6 route connected", + "show ipv6 route forward", + "show ipv6 route isis", + "show ipv6 route kernel", + "show ipv6 route ospf", + "show ipv6 route rip", + "show ipv6 route static", + "show ipv6 route summary", + "show ipv6 route supernets-only", + "show ipv6 route table", + "show ipv6 route tag", + "show ipv6 route vrf", +] + + +def ROUTING(cmd): + for command_line in cmd: + head = command_line + command = command_line + header(head) + call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command}') + return + + +###################### THE PART OF IPTABLES ###################### + +cmd_list_iptables = [ + "Filter Chain Details%sudo /sbin/iptables -L -vn", + "Nat Chain Details%sudo /sbin/iptables -t nat -L -vn", + "Mangle Chain Details%sudo /sbin/iptables -t mangle -L -vn", + "Raw Chain Details%sudo /sbin/iptables -t raw -L -vn", + "Save Iptables Rule-Set%sudo iptables-save -c" +] + + +def IPTABLES(cmd): + for command_line in cmd: + line = command_line.split('%') + head = line[0] + command = line[1] + header(head) + call(command) + return + + +###################### THE PART OF SYSTEM ###################### + +cmd_list_system = [ + "Show System Image Version%show system image version", + "Show System Image Storage%show system image storage", + "Current Time%date", + "Installed Packages%dpkg -l", + "Loaded Modules%cat /proc/modules", + "CPU", + "Installed CPU/s%lscpu", + "Cumulative CPU Time Used by Running Processes%top -n1 -b -S", + "Hardware Interrupt Counters%cat /proc/interrupts", + "Load Average%cat /proc/loadavg" +] + + +def SYSTEM(cmd): + for command_line in cmd: + line = command_line.split('%') + head = line[0] + if command_line.startswith("CPU"): + header(command_line) + elif line[1].startswith("show"): + header(head) + command = line[1] + call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command}') + else: + header(head) + command = line[1] + call(command) + return + + +###################### THE PART OF PROCESSES ###################### + +cmd_list_processes = [ + "Running Processes%ps -ef", + "Memory", + "Installed Memory%cat /proc/meminfo", + " Memory Usage%free", + "Storage", + "Devices%cat /proc/devices", + "Partitions%cat /proc/partitions", + "Partitioning for disks%fdisk -l /dev/" +] + + +def PROCESSES(cmd): + for command_line in cmd: + line = command_line.split('%') + head = line[0] + if command_line.startswith("Memory"): + header(command_line) + elif command_line.startswith("Storage"): + header(command_line) + elif command_line.startswith("Partitioning for disks"): + header(head) + disks = set() + with open('/proc/partitions') as partitions_file: + for line in partitions_file: + fields = line.strip().split() + if len(fields) == 4 and fields[3].isalpha() and fields[3] != 'name': + disks.add(fields[3]) + for disk in disks: + call(f'fdisk -l /dev/{disk}') + else: + header(head) + command = line[1] + call(command) + return + + +###################### THE PART OF CORE SECTION ###################### + +cmd_list_core = [ + "Mounts%cat /proc/mounts", + "Diskstats%cat /proc/diskstats", + "Hard Drive Usage%df -h -x squashfs", + # "General System", + "Boot Messages%cat /var/log/dmesg", + "Recent Kernel messages (dmesg)%dmesg", + "PCI Info%sudo lspci -vvx", + "PCI Vendor and Device Codes%sudo lspci -nn", + # "System Info%${vyatta_bindir}/vyatta-show-dmi", + "GRUB Command line%cat /proc/cmdline", + "Open Ports%sudo lsof -P -n -i", + "System Startup Files%ls -l /etc/rc?.d", + "Login History%last -ix", + "Recent Log Messages%tail -n 250 /var/log/messages", + "NTP%/opt/vyatta/bin/vyatta-op-cmd-wrapper show ntp", +] + + +def CORE(cmd): + for command_line in cmd: + line = command_line.split('%') + command = line[1] + header(line[0]) + call(command) + return + + +###################### THE PART OF VyOS INFORMATION ###################### + +cmd_list_vyos = [ + "BGP", + "header BGP Summary", + "show ip bgp summary", + "header BGP Neighbors", + "show ip bgp neighbors", + "header BGP Debugging Information", + "show monitoring protocols bgp", + "CLUSTERING", + "Cluster Status", + "show cluster status", + "DHCP Server", + "DHCP Leases", + "show dhcp server leases", + "DHCP Statistics", + "show dhcp server statistics", + "DHCP Client", + "DHCP Client Leases", + "show dhcp client leases", + "DHCPV6 Server", + "DHCPV6 Server Status", + "show dhcpv6 server status", + "DHCPV6 Server Leases", + "show dhcpv6 server leases", + "DHCPV6 Relay", + "DHCPV6 Relay Status", + "show dhcpv6 relay-agent status", + "DHCPV6 Client", + "DHCPV6 Client Leases", + "show dhcpv6 client leases", + "DNS", + "DNS Dynamic Status", + "show dns dynamic status", + "DNS Forwarding Statistics", + "show dns forwarding statistics", + "DNS Forwarding Nameservers", + "show dns forwarding nameservers", + "FIREWALL", + "Firewall Group", + "show firewall group", + "Firewall Summary", + "show firewall summary", + "Firewall Statistics", + "show firewall statistics", + "IPSec", + "IPSec Status", + "show vpn ipsec status", + "IPSec sa", + "show vpn ipsec sa", + "IPSec sa Detail", + "show vpn ipsec sa detail", + "IPSec sa Statistics", + "show vpn ipsec sa statistics", + "/etc/ipsec.conf", + "cat /etc/ipsec.conf", + "/etc/ipsec.secrets", + "cat /etc/ipsec.secrets", + "NAT", + "NAT Rules", + "show nat rules", + "NAT Statistics", + "show nat statistics", + "NAT Translations Detail", + "show nat translations detail", + "FlowAccounting", + "show flow-accounting", + "OPENVPN", + "OpenVPN Interfaces", + "show interfaces openvpn detail", + "OpenVPN Server Status", + "show openvpn status server", + "OSPF", + "OSPF Neighbor", + "show ip ospf neighbor", + "OSPF Route", + "show ip ospf route", + "OSPF Debugging Information", + "show monitoring protocols ospf", + "OSPFV3", + "OSPFV3 Debugging Information", + "show monitoring protocols ospfv3", + "Policy", + "IP Route Maps", + "show ip protocol", + "Route-Map", + "show route-map", + # header IP Access Lists + # show ip access-lists + "IP Community List", + "show ip community-list", + "Traffic Policy", + "Current Traffic Policies", + "show queueing", + "RIP", + "IP RIP", + "show ip rip", + "RIP Status", + "show ip rip status", + "RIP Debugging Information", + "show monitoring protocols rip", + "RIPNG", + "RIPNG Debugging Information", + "show monitoring protocols ripng", + "VPN-L2TP", + "VPN ike secrets", + "show vpn ike secrets", + "VPN rsa-keys", + "show vpn ike rsa-keys", + "VPN ike sa", + "show vpn ike sa", + "VPN ike Status", + "show vpn ike status", + "VPN Remote-Access", + "show vpn remote-access", + "VPN Debug Detail", + "show vpn debug detail", + "VPN-PPTP", + "VPN Remote-Access", + "show vpn remote-access", + "VRRP", + # XXX: not checking if configured, we'd have to walk all VIFs + "show vrrp detail", + "WAN LOAD BALANCING", + "Wan Load Balance", + "show wan-load-balance", + "Wan Load Balance Status", + "show wan-load-balance status", + "Wan Load Balance Connection", + "show wan-load-balance connection", + "WEBPROXY/URL-FILTERING", + "WebProxy Blacklist Categories", + "show webproxy blacklist categories", + "WebProxy Blacklist Domains", + "show webproxy blacklist domains", + "WebProxy Blacklist URLs", + "show webproxy blacklist urls", + "WebProxy Blacklist Log", + "show webproxy blacklist log summary", +] + + +def VyOS(cmd): + for command_line in cmd: + if command_line.startswith("show"): + call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command_line}') + elif command_line.startswith("cat"): + call(command_line) + else: + header(command_line) + return + + +###################### execute all the commands ###################### + +header('CONFIGURATION') +CONFIGURATION(cmd_list_conf) + +header('INTERFACES') +INTERFACES(cmd_list_int) + +header('ROUTING') +ROUTING(cmd_list_route) + +header('IPTABLES') +IPTABLES(cmd_list_iptables) + +header('SYSTEM') +SYSTEM(cmd_list_system) + +header('PROCESSES') +PROCESSES(cmd_list_processes) + +header('CORE') +CORE(cmd_list_core) + +header('VyOS Information') +VyOS(cmd_list_vyos) -- cgit v1.2.3 From 1a402dd93974840e1039972276e8dbf1cf8694fe Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Thu, 6 Apr 2023 12:24:52 +0000 Subject: T1237: Failover route add checks for multiple targets There is only one target for checking ICMP/ARP Extend it for checking multiple targets set protocols failover route 192.0.2.55/32 next-hop 192.168.122.1 check target '203.0.113.1' set protocols failover route 192.0.2.55/32 next-hop 192.168.122.1 check target '203.0.113.11' The route will be installed only if all targets are 'alive' --- interface-definitions/protocols-failover.xml.in | 1 + src/helpers/vyos-failover.py | 69 ++++++++++++++++--------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/interface-definitions/protocols-failover.xml.in b/interface-definitions/protocols-failover.xml.in index 900c76eab..a8c5c717f 100644 --- a/interface-definitions/protocols-failover.xml.in +++ b/interface-definitions/protocols-failover.xml.in @@ -48,6 +48,7 @@ + diff --git a/src/helpers/vyos-failover.py b/src/helpers/vyos-failover.py index 0de945f20..03fb42f57 100755 --- a/src/helpers/vyos-failover.py +++ b/src/helpers/vyos-failover.py @@ -30,7 +30,7 @@ my_name = Path(__file__).stem def is_route_exists(route, gateway, interface, metric): """Check if route with expected gateway, dev and metric exists""" - rc, data = rc_cmd(f'sudo ip --json route show protocol failover {route} ' + rc, data = rc_cmd(f'ip --json route show protocol failover {route} ' f'via {gateway} dev {interface} metric {metric}') if rc == 0: data = json.loads(data) @@ -72,6 +72,7 @@ def get_best_route_options(route, debug=False): f'best_metric: {best_metric}, best_iface: {best_interface}') return best_gateway, best_interface, best_metric + def is_port_open(ip, port): """ Check connection to remote host and port @@ -91,32 +92,54 @@ def is_port_open(ip, port): finally: s.close() -def is_target_alive(target=None, iface='', proto='icmp', port=None, debug=False): - """ - Host availability check by ICMP, ARP, TCP - Return True if target checks is successful - % is_target_alive('192.0.2.1', 'eth1', proto='arp') - True +def is_target_alive(target_list=None, iface='', proto='icmp', port=None, debug=False): + """Check the availability of each target in the target_list using + the specified protocol ICMP, ARP, TCP + + Args: + target_list (list): A list of IP addresses or hostnames to check. + iface (str): The name of the network interface to use for the check. + proto (str): The protocol to use for the check. Options are 'icmp', 'arp', or 'tcp'. + port (int): The port number to use for the TCP check. Only applicable if proto is 'tcp'. + debug (bool): If True, print debug information during the check. + + Returns: + bool: True if all targets are reachable, False otherwise. + + Example: + % is_target_alive(['192.0.2.1', '192.0.2.5'], 'eth1', proto='arp') + True """ if iface != '': iface = f'-I {iface}' - if proto == 'icmp': - command = f'/usr/bin/ping -q {target} {iface} -n -c 2 -W 1' - rc, response = rc_cmd(command) - if debug: print(f' [ CHECK-TARGET ]: [{command}] -- return-code [RC: {rc}]') - if rc == 0: - return True - elif proto == 'arp': - command = f'/usr/bin/arping -b -c 2 -f -w 1 -i 1 {iface} {target}' - rc, response = rc_cmd(command) - if debug: print(f' [ CHECK-TARGET ]: [{command}] -- return-code [RC: {rc}]') - if rc == 0: - return True - elif proto == 'tcp' and port is not None: - return True if is_port_open(target, port) else False - else: - return False + + for target in target_list: + match proto: + case 'icmp': + command = f'/usr/bin/ping -q {target} {iface} -n -c 2 -W 1' + rc, response = rc_cmd(command) + if debug: + print(f' [ CHECK-TARGET ]: [{command}] -- return-code [RC: {rc}]') + if rc != 0: + return False + + case 'arp': + command = f'/usr/bin/arping -b -c 2 -f -w 1 -i 1 {iface} {target}' + rc, response = rc_cmd(command) + if debug: + print(f' [ CHECK-TARGET ]: [{command}] -- return-code [RC: {rc}]') + if rc != 0: + return False + + case _ if proto == 'tcp' and port is not None: + if not is_port_open(target, port): + return False + + case _: + return False + + return True if __name__ == '__main__': -- cgit v1.2.3 From d5eafd464047ee293c68c2fe6e1ba4e6e4d60585 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 7 Apr 2023 13:20:53 -0500 Subject: openvpn: T5149: do not raise error in case of disabled interface --- src/op_mode/openvpn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/op_mode/openvpn.py b/src/op_mode/openvpn.py index 37fdbcbeb..5a1a4914d 100755 --- a/src/op_mode/openvpn.py +++ b/src/op_mode/openvpn.py @@ -63,7 +63,7 @@ def _get_interface_status(mode: str, interface: str) -> dict: } if not os.path.exists(status_file): - raise vyos.opmode.DataUnavailable('No information for interface {interface}') + return data with open(status_file, 'r') as f: lines = f.readlines() -- cgit v1.2.3 From c53d73cd8958a71b853d13b1515f89c5f35bdae4 Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Sun, 9 Apr 2023 12:22:16 -0400 Subject: eapol: T5151: Allow TLSv1.0/1.1 for EAP-TLS The Debian 12 upgrade in T5003 caused a regression for connecting to legacy networks that only support TLSv1.0/1.1 for EAP-TLS. Debian allows this by default in their wpa_supplicant package, but their `allow-tlsv1.patch` patch does not work properly with VyOS' newer wpa_supplicant package, which is based on the latest code in git. As a result, wpa_supplicant always respects the system-wide openssl crypto policy, disallowing TLSv1. The commit uses the documented way of allowing TLSv1, which takes precedence over the system crypto policy. Signed-off-by: Andrew Gunnerson --- data/templates/ethernet/wpa_supplicant.conf.j2 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/templates/ethernet/wpa_supplicant.conf.j2 b/data/templates/ethernet/wpa_supplicant.conf.j2 index 8f140f6cb..cd35d6d1e 100644 --- a/data/templates/ethernet/wpa_supplicant.conf.j2 +++ b/data/templates/ethernet/wpa_supplicant.conf.j2 @@ -67,6 +67,11 @@ network={ # discards such frames to protect against potential attacks by rogue # devices, but this option can be used to disable that protection for cases # where the server/authenticator does not need to be authenticated. - phase1="allow_canned_success=1" + # + # "tls_disable_tlsv1_0=0" is used to allow TLSv1 for compatibility with + # legacy networks. This follows the behavior of Debian's wpa_supplicant, + # which includes a custom patch for allowing TLSv1, but the patch currently + # does not work for VyOS' git builds of wpa_supplicant. + phase1="allow_canned_success=1 tls_disable_tlsv1_0=0" } -- cgit v1.2.3 From 4fac9c122887c91af4e6d51b4e2eb01977196852 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Fri, 7 Apr 2023 12:28:46 +0000 Subject: T4770: Ability to get OpenVPN iface state and description for raw --- src/op_mode/openvpn.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/op_mode/openvpn.py b/src/op_mode/openvpn.py index 37fdbcbeb..6ef80919b 100755 --- a/src/op_mode/openvpn.py +++ b/src/op_mode/openvpn.py @@ -16,6 +16,7 @@ # # +import json import os import sys import typing @@ -25,6 +26,7 @@ import vyos.opmode from vyos.util import bytes_to_human from vyos.util import commit_in_progress from vyos.util import call +from vyos.util import rc_cmd from vyos.config import Config ArgMode = typing.Literal['client', 'server', 'site_to_site'] @@ -142,6 +144,25 @@ def _get_interface_status(mode: str, interface: str) -> dict: return data + +def _get_interface_state(iface): + rc, out = rc_cmd(f'ip --json link show dev {iface}') + try: + data = json.loads(out) + except: + return 'DOWN' + return data[0].get('operstate', 'DOWN') + + +def _get_interface_description(iface): + rc, out = rc_cmd(f'ip --json link show dev {iface}') + try: + data = json.loads(out) + except: + return '' + return data[0].get('ifalias', '') + + def _get_raw_data(mode: str) -> list: data: list = [] conf = Config() @@ -154,6 +175,8 @@ def _get_raw_data(mode: str) -> list: conf_dict[x]['mode'].replace('-', '_') == mode] for intf in interfaces: d = _get_interface_status(mode, intf) + d['state'] = _get_interface_state(intf) + d['description'] = _get_interface_description(intf) d['local_host'] = conf_dict[intf].get('local-host', '') d['local_port'] = conf_dict[intf].get('local-port', '') if conf.exists(f'interfaces openvpn {intf} server client'): -- cgit v1.2.3 From c6f23303112e68d34bc4d8efd49217629d86296b Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 10 Apr 2023 10:29:16 +0000 Subject: T5148: Fix OpenVPN plugin dir variable Jinja2 template uses {{ plugin_dir }} that it gets from the interface-openvpn.py variable 'plugin_dir' but the correct var should be as part of 'openvpn' dictionary i.e. openvpn['plugin_dir'] --- src/conf_mode/interfaces-openvpn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 13d84a6fe..6f227b0d1 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-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 @@ -597,7 +597,7 @@ def generate_pki_files(openvpn): def generate(openvpn): interface = openvpn['ifname'] directory = os.path.dirname(cfg_file.format(**openvpn)) - plugin_dir = '/usr/lib/openvpn' + openvpn['plugin_dir'] = '/usr/lib/openvpn' # create base config directory on demand makedir(directory, user, group) # enforce proper permissions on /run/openvpn -- cgit v1.2.3 From 6efdab7cccdd697b4479c9af9f000369c3729011 Mon Sep 17 00:00:00 2001 From: Tobias Fiebig Date: Fri, 10 Mar 2023 12:48:09 +0100 Subject: T5078: Added filtered-routes BGP command --- op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i | 6 ++++++ op-mode-definitions/include/bgp/show-ip-bgp-common.xml.i | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i index 7dbc4fde5..820d507fd 100644 --- a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i +++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i @@ -195,6 +195,12 @@ + + + Show filtered routes from BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + Show received routes from BGP neighbor diff --git a/op-mode-definitions/include/bgp/show-ip-bgp-common.xml.i b/op-mode-definitions/include/bgp/show-ip-bgp-common.xml.i index 36cc9a3fa..db9021f3e 100644 --- a/op-mode-definitions/include/bgp/show-ip-bgp-common.xml.i +++ b/op-mode-definitions/include/bgp/show-ip-bgp-common.xml.i @@ -93,6 +93,12 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + Show the filtered routes from neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + Show the received routes from neighbor -- cgit v1.2.3 From 8e4b8d1468c0a293cd0062f60718873ba8e4fe21 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 10 Apr 2023 13:50:12 +0000 Subject: T5148: Add smoketest for plugin openvpn-otp OpenVPN --- smoketest/scripts/cli/test_interfaces_openvpn.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py index b2143d16e..c80c7cf80 100755 --- a/smoketest/scripts/cli/test_interfaces_openvpn.py +++ b/smoketest/scripts/cli/test_interfaces_openvpn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2022 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 @@ -368,6 +368,7 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): self.cli_set(path + ['hash', auth_hash]) self.cli_set(path + ['mode', 'server']) self.cli_set(path + ['local-port', port]) + self.cli_set(path + ['server', 'mfa', 'totp']) self.cli_set(path + ['server', 'subnet', subnet]) self.cli_set(path + ['server', 'topology', 'subnet']) self.cli_set(path + ['keep-alive', 'failure-count', '5']) @@ -388,6 +389,7 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): for ii in num_range: interface = f'vtun{ii}' + plugin = f'plugin "/usr/lib/openvpn/openvpn-otp.so" "otp_secrets=/config/auth/openvpn/{interface}-otp-secrets otp_slop=180 totp_t0=0 totp_step=30 totp_digits=6 password_is_cr=1"' subnet = f'192.0.{ii}.0/24' start_addr = inc_ip(subnet, '2') @@ -411,6 +413,7 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): self.assertIn(f'topology subnet', config) self.assertIn(f'lport {port}', config) self.assertIn(f'push "redirect-gateway def1"', config) + self.assertIn(f'{plugin}', config) self.assertIn(f'keepalive 5 25', config) # TLS options -- cgit v1.2.3 From 8eb85739c9656ba1447d61364117c9c06b0f867b Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Mon, 10 Apr 2023 13:19:30 -0400 Subject: hostapd: T5151: Override ConditionFileNotEmpty Debian's `debian/2%2.10-12` update of the hostap packaging added a ConditionFileNotEmpty directive for `/etc/hostapd/<...>` paths, which doesn't match the `/run/hostapd/<...>` paths that VyOS uses. This commit updates the override file to use the proper VyOS paths. https://salsa.debian.org/debian/wpa/-/commit/d204ceb5a2dc33db888eb55b5fee542a1005e69c Signed-off-by: Andrew Gunnerson --- src/etc/systemd/system/hostapd@.service.d/override.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/etc/systemd/system/hostapd@.service.d/override.conf b/src/etc/systemd/system/hostapd@.service.d/override.conf index bb8e81d7a..926c07f94 100644 --- a/src/etc/systemd/system/hostapd@.service.d/override.conf +++ b/src/etc/systemd/system/hostapd@.service.d/override.conf @@ -1,6 +1,8 @@ [Unit] After= After=vyos-router.service +ConditionFileNotEmpty= +ConditionFileNotEmpty=/run/hostapd/%i.conf [Service] WorkingDirectory=/run/hostapd -- cgit v1.2.3 From 8ef944b854de54bce95b91257d7a3cd22ed48064 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 10 Apr 2023 17:55:48 +0000 Subject: T5065: Add verify for firewall port-group and port We cannot use both 'port' and 'port-group' for the same direction in one rule at the same time Otherwise it generates wrong rules that don't block anything set P_pgrp { type inet_service flags interval auto-merge elements = { 101-105 } } chain NAME_foo { tcp dport 22 tcp dport @P_pgrp counter drop comment "foo-10" counter return comment "foo default-action accept" } --- src/conf_mode/firewall.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index c41a442df..190587980 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -282,6 +282,9 @@ def verify_rule(firewall, rule_conf, ipv6): if rule_conf['protocol'] not in ['tcp', 'udp', 'tcp_udp']: raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group') + if 'port' in side_conf and dict_search_args(side_conf, 'group', 'port_group'): + raise ConfigError(f'{side} port-group and port cannot both be defined') + if 'log_options' in rule_conf: if 'log' not in rule_conf or 'enable' not in rule_conf['log']: raise ConfigError('log-options defined, but log is not enable') -- cgit v1.2.3 From 2179cf45d606d23abfcb96c000db5c9316c48a59 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 11 Apr 2023 09:02:08 +0000 Subject: T5152: Get default hostname for telegraf from FQDN or hostname Fix for Telegraf agent hostname isn't qualified Try to get hostname from FQDN and then from hostname Used for metrics You may have more than one machine with different domain names r1 domain-name foo.local, hostname myhost r2 domain-name bar.local, hostname myhost It helps to detect from which exectly host we get metric for InfluxDB2 --- data/templates/telegraf/telegraf.j2 | 2 +- src/conf_mode/service_monitoring_telegraf.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/data/templates/telegraf/telegraf.j2 b/data/templates/telegraf/telegraf.j2 index c9f402281..5852d6232 100644 --- a/data/templates/telegraf/telegraf.j2 +++ b/data/templates/telegraf/telegraf.j2 @@ -12,7 +12,7 @@ debug = false quiet = false logfile = "" - hostname = "" + hostname = "{{ hostname }}" omit_hostname = false {% if azure_data_explorer is vyos_defined %} ### Azure Data Explorer ### diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py index 363408679..47510ce80 100755 --- a/src/conf_mode/service_monitoring_telegraf.py +++ b/src/conf_mode/service_monitoring_telegraf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -15,6 +15,7 @@ # along with this program. If not, see . import os +import socket import json from sys import exit @@ -57,6 +58,13 @@ def get_nft_filter_chains(): return chain_list +def get_hostname() -> str: + try: + hostname = socket.getfqdn() + except socket.gaierror: + hostname = socket.gethostname() + return hostname + def get_config(config=None): if config: conf = config @@ -79,6 +87,7 @@ def get_config(config=None): monitoring = dict_merge(default_values, monitoring) monitoring['custom_scripts_dir'] = custom_scripts_dir + monitoring['hostname'] = get_hostname() monitoring['interfaces_ethernet'] = Section.interfaces('ethernet', vlan=False) monitoring['nft_chains'] = get_nft_filter_chains() -- cgit v1.2.3 From 9347bfa209626167f7f04856a81fc4ccab1aaccd Mon Sep 17 00:00:00 2001 From: Cheeze_It Date: Sun, 9 Apr 2023 17:38:36 -0600 Subject: T5081: ISIS and OSPF syncronization with IGP-LDP sync --- op-mode-definitions/include/isis-common.xml.i | 22 +++------------------- op-mode-definitions/include/ldp-sync.xml.i | 19 +++++++++++++++++++ op-mode-definitions/include/ospf-common.xml.i | 20 ++------------------ 3 files changed, 24 insertions(+), 37 deletions(-) create mode 100644 op-mode-definitions/include/ldp-sync.xml.i diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 53e85a7ef..b5b4f9b5d 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -56,31 +56,15 @@ - Show IS-IS MPLS specific information + Show MPLS information - - - Show IS-IS LDP-IGP synchronization information - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Show specific IS-IS LDP-IGP synchronization for an interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - + #include - Show IS-IS MPLS traffic engineering information + Show MPLS traffic engineering information diff --git a/op-mode-definitions/include/ldp-sync.xml.i b/op-mode-definitions/include/ldp-sync.xml.i new file mode 100644 index 000000000..b3be8f503 --- /dev/null +++ b/op-mode-definitions/include/ldp-sync.xml.i @@ -0,0 +1,19 @@ + + + + Show LDP-IGP synchronization information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show specific LDP-IGP synchronization for an interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + \ No newline at end of file diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index 7d9e541cf..d1a62b690 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -519,26 +519,10 @@ - Show OSPF MPLS specific information + Show MPLS information - - - Show OSPF LDP-IGP synchronization information - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Show specific OSPF LDP-IGP synchronization for an interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - + #include -- cgit v1.2.3 From f62dffaa3121261925b4850fe0400dd33449e5f5 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 11 Apr 2023 20:20:19 +0000 Subject: T4727: Change and fix RADIUS rate-limit option for pptp Initially the option 'rate-limit' was implemented with the wrong place in the CLI: set vpn pptp remote-access authentication rate-limit Expected under 'radius' section: set vpn pptp remote-access authentication radius rate-limit Configuration for 'rate-limit' (Jinja2 template) never worked for pptp, fix it. --- data/templates/accel-ppp/pptp.config.j2 | 7 ++++++- interface-definitions/vpn-pptp.xml.in | 6 +++++- src/conf_mode/vpn_pptp.py | 23 ++++++++++++++--------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/data/templates/accel-ppp/pptp.config.j2 b/data/templates/accel-ppp/pptp.config.j2 index 442830b6b..78a629d2d 100644 --- a/data/templates/accel-ppp/pptp.config.j2 +++ b/data/templates/accel-ppp/pptp.config.j2 @@ -93,10 +93,15 @@ bind={{ radius_source_address }} gw-ip-address={{ gw_ip }} {% endif %} -{% if radius_shaper_attr %} +{% if radius_shaper_enable %} [shaper] verbose=1 +{% if radius_shaper_attr %} attr={{ radius_shaper_attr }} +{% endif %} +{% if radius_shaper_multiplier %} +rate-multiplier={{ radius_shaper_multiplier }} +{% endif %} {% if radius_shaper_vendor %} vendor={{ radius_shaper_vendor }} {% endif %} diff --git a/interface-definitions/vpn-pptp.xml.in b/interface-definitions/vpn-pptp.xml.in index 00ffd26f9..5a8b4a78a 100644 --- a/interface-definitions/vpn-pptp.xml.in +++ b/interface-definitions/vpn-pptp.xml.in @@ -108,9 +108,13 @@ + + + #include + + #include #include - #include diff --git a/src/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py index 7550c411e..986a19972 100755 --- a/src/conf_mode/vpn_pptp.py +++ b/src/conf_mode/vpn_pptp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -44,6 +44,8 @@ default_pptp = { 'radius_nas_ip' : '', 'radius_source_address' : '', 'radius_shaper_attr' : '', + 'radius_shaper_enable': False, + 'radius_shaper_multiplier': '', 'radius_shaper_vendor': '', 'radius_dynamic_author' : '', 'chap_secrets_file': pptp_chap_secrets, # used in Jinja2 template @@ -183,15 +185,18 @@ def get_config(config=None): pptp['radius_dynamic_author'] = dae + # Rate limit + if conf.exists(['rate-limit', 'attribute']): + pptp['radius_shaper_attr'] = conf.return_value(['rate-limit', 'attribute']) + if conf.exists(['rate-limit', 'enable']): - pptp['radius_shaper_attr'] = 'Filter-Id' - c_attr = ['rate-limit', 'enable', 'attribute'] - if conf.exists(c_attr): - pptp['radius_shaper_attr'] = conf.return_value(c_attr) - - c_vendor = ['rate-limit', 'enable', 'vendor'] - if conf.exists(c_vendor): - pptp['radius_shaper_vendor'] = conf.return_value(c_vendor) + pptp['radius_shaper_enable'] = True + + if conf.exists(['rate-limit', 'multiplier']): + pptp['radius_shaper_multiplier'] = conf.return_value(['rate-limit', 'multiplier']) + + if conf.exists(['rate-limit', 'vendor']): + pptp['radius_shaper_vendor'] = conf.return_value(['rate-limit', 'vendor']) conf.set_level(base_path) if conf.exists(['client-ip-pool']): -- cgit v1.2.3 From 8cb0b59fce842c9e69ebf1b9099abce2c6e21447 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 12 Apr 2023 21:36:27 +0200 Subject: xml: T5081: generate common holddown XML building block for IS-IS and OSPF --- .../include/isis/ldp-sync-holddown.xml.i | 14 ++++++++++++++ .../include/isis/ldp-sync-interface.xml.i | 11 +++++++++++ .../include/isis/ldp-sync-protocol.xml.i | 10 ++++++++++ .../include/isis/protocol-common-config.xml.i | 4 ++-- .../include/ldp-sync-interface.xml.i | 22 ---------------------- .../include/ldp-sync-protocol.xml.i | 21 --------------------- .../include/ospf/protocol-common-config.xml.i | 4 ++-- 7 files changed, 39 insertions(+), 47 deletions(-) create mode 100644 interface-definitions/include/isis/ldp-sync-holddown.xml.i create mode 100644 interface-definitions/include/isis/ldp-sync-interface.xml.i create mode 100644 interface-definitions/include/isis/ldp-sync-protocol.xml.i delete mode 100644 interface-definitions/include/ldp-sync-interface.xml.i delete mode 100644 interface-definitions/include/ldp-sync-protocol.xml.i diff --git a/interface-definitions/include/isis/ldp-sync-holddown.xml.i b/interface-definitions/include/isis/ldp-sync-holddown.xml.i new file mode 100644 index 000000000..15ac26f07 --- /dev/null +++ b/interface-definitions/include/isis/ldp-sync-holddown.xml.i @@ -0,0 +1,14 @@ + + + + Hold down timer for LDP-IGP cost restoration + + u32:0-10000 + Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost + + + + + + + diff --git a/interface-definitions/include/isis/ldp-sync-interface.xml.i b/interface-definitions/include/isis/ldp-sync-interface.xml.i new file mode 100644 index 000000000..222a35256 --- /dev/null +++ b/interface-definitions/include/isis/ldp-sync-interface.xml.i @@ -0,0 +1,11 @@ + + + + LDP-IGP synchronization configuration for interface + + + #include + #include + + + diff --git a/interface-definitions/include/isis/ldp-sync-protocol.xml.i b/interface-definitions/include/isis/ldp-sync-protocol.xml.i new file mode 100644 index 000000000..b2e696a70 --- /dev/null +++ b/interface-definitions/include/isis/ldp-sync-protocol.xml.i @@ -0,0 +1,10 @@ + + + + Protocol wide LDP-IGP synchronization configuration + + + #include + + + diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 983a085ec..8103b5c5d 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -152,7 +152,7 @@ -#include +#include A Network Entity Title for this process (ISO only) @@ -632,7 +632,7 @@ #include - #include + #include Set network type diff --git a/interface-definitions/include/ldp-sync-interface.xml.i b/interface-definitions/include/ldp-sync-interface.xml.i deleted file mode 100644 index b24831bbe..000000000 --- a/interface-definitions/include/ldp-sync-interface.xml.i +++ /dev/null @@ -1,22 +0,0 @@ - - - - LDP-IGP synchronization configuration for interface - - - #include - - - Hold down timer for LDP-IGP cost restoration - - u32:0-10000 - Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost - - - - - - - - - diff --git a/interface-definitions/include/ldp-sync-protocol.xml.i b/interface-definitions/include/ldp-sync-protocol.xml.i deleted file mode 100644 index c82c811f6..000000000 --- a/interface-definitions/include/ldp-sync-protocol.xml.i +++ /dev/null @@ -1,21 +0,0 @@ - - - - Protocol wide LDP-IGP synchronization configuration - - - - - Protocol wide hold down timer for LDP-IGP cost restoration - - u32:0-10000 - Time to wait in seconds for LDP-IGP synchronization to occur before restoring interface cost - - - - - - - - - diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 425d3b01c..e400119dd 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -331,7 +331,7 @@ -#include +#include Administrative distance @@ -386,7 +386,7 @@ #include #include #include - #include + #include Interface bandwidth (Mbit/s) -- cgit v1.2.3 From 47bd0d8ab940bd8bb9b7c852ac80e0d9a3728a82 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 12 Apr 2023 21:46:07 +0200 Subject: xml: op-mode: T5081: re-use vtysh-generic-detail building block --- op-mode-definitions/include/isis-common.xml.i | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index b5b4f9b5d..53be33b68 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -4,12 +4,7 @@ Show IS-IS link state database - - - Show detailed information - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ @@ -36,12 +31,7 @@ - - - Show detailed information - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ @@ -95,12 +85,7 @@ Show IS-IS neighbor adjacencies - - - Show detailed information - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ -- cgit v1.2.3 From 23c757dae9b164cdaeba334b509b4def9c71f9b3 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 12 Apr 2023 21:47:31 +0200 Subject: xml: op-mode: T5081: introduce new FRR tagNode interface building block --- op-mode-definitions/include/isis-common.xml.i | 20 ++------------------ op-mode-definitions/include/ldp-sync.xml.i | 10 +--------- op-mode-definitions/include/ospf-common.xml.i | 10 +--------- .../include/vtysh-generic-interface-tagNode.xml.i | 11 +++++++++++ 4 files changed, 15 insertions(+), 36 deletions(-) create mode 100644 op-mode-definitions/include/vtysh-generic-interface-tagNode.xml.i diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i index 53be33b68..e94d868e8 100644 --- a/op-mode-definitions/include/isis-common.xml.i +++ b/op-mode-definitions/include/isis-common.xml.i @@ -35,15 +35,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - Show specific IS-IS interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - +#include Show MPLS information @@ -69,15 +61,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - Show specific IS-IS interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include diff --git a/op-mode-definitions/include/ldp-sync.xml.i b/op-mode-definitions/include/ldp-sync.xml.i index b3be8f503..b7b04e7e5 100644 --- a/op-mode-definitions/include/ldp-sync.xml.i +++ b/op-mode-definitions/include/ldp-sync.xml.i @@ -5,15 +5,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - Show specific LDP-IGP synchronization for an interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include \ No newline at end of file diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index d1a62b690..aebbae5ff 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -508,15 +508,7 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - Show IPv4 OSPF information for specified interface - - - - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - +#include Show MPLS information diff --git a/op-mode-definitions/include/vtysh-generic-interface-tagNode.xml.i b/op-mode-definitions/include/vtysh-generic-interface-tagNode.xml.i new file mode 100644 index 000000000..e95961177 --- /dev/null +++ b/op-mode-definitions/include/vtysh-generic-interface-tagNode.xml.i @@ -0,0 +1,11 @@ + + + + Show information about specific interface + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + -- cgit v1.2.3 From 8993298bc2c9d3e796d658dc71ba6ae6afedc4c3 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 13 Apr 2023 09:01:05 +0200 Subject: eigrp: T2472: remove pprint debug statement --- src/conf_mode/protocols_eigrp.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/conf_mode/protocols_eigrp.py b/src/conf_mode/protocols_eigrp.py index c1a1a45e1..6e75e34ff 100755 --- a/src/conf_mode/protocols_eigrp.py +++ b/src/conf_mode/protocols_eigrp.py @@ -69,8 +69,6 @@ def get_config(config=None): # Merge policy dict into "regular" config dict eigrp = dict_merge(tmp, eigrp) - import pprint - pprint.pprint(eigrp) return eigrp def verify(eigrp): -- cgit v1.2.3 From 3f4de1390d6459cdd17dd1b6f22b1a3aec002671 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 8 Apr 2023 22:09:04 +0200 Subject: T5150: initial implementation of new Kernel/Zebra route-map support It is possible to install a route-map which filters the routes between routing daemons and the OS kernel (zebra) As of now this can be done by e.g. * set protocols ospf route-map foo * set protocols ospfv3 route-map foo * set protocols bgp route-map foo Which in turn will install the following lines into FRR * ip protocol ospf route-map foo * ipv6 protocol ospf6 route-map foo * ip protocol bgp route-map foo The current state of the VyOS CLI is incomplete as there is no way to: * Install a filter for BGP IPv6 routes * Install a filter for static routes * Install a filter for connected routes Thus the CLI should be redesigned to close match what FRR does for both the default and any other VRF * set system ip protocol ospf route-map foo * set system ipv6 protocol ospfv3 route-map foo * set system ip protocol bgp route-map foo * set system ipv6 protocol bgp route-map foo The configuration can be migrated accordingly. This commit does not come with the migrator, it will be comitted later. --- data/templates/frr/zebra.route-map.frr.j2 | 21 ++++++++ .../include/system-ip-protocol.xml.i | 56 ++++++++++++++++++++++ .../include/system-ipv6-protocol.xml.i | 52 ++++++++++++++++++++ interface-definitions/system-ip.xml.in | 1 + interface-definitions/system-ipv6.xml.in | 1 + interface-definitions/vrf.xml.in | 2 + smoketest/scripts/cli/test_system_ip.py | 29 ++++++++++- smoketest/scripts/cli/test_system_ipv6.py | 34 ++++++++++++- src/conf_mode/protocols_static.py | 7 --- src/conf_mode/system-ip.py | 38 +++++++++++++-- src/conf_mode/system-ipv6.py | 38 +++++++++++++-- 11 files changed, 264 insertions(+), 15 deletions(-) create mode 100644 data/templates/frr/zebra.route-map.frr.j2 create mode 100644 interface-definitions/include/system-ip-protocol.xml.i create mode 100644 interface-definitions/include/system-ipv6-protocol.xml.i diff --git a/data/templates/frr/zebra.route-map.frr.j2 b/data/templates/frr/zebra.route-map.frr.j2 new file mode 100644 index 000000000..bd461d904 --- /dev/null +++ b/data/templates/frr/zebra.route-map.frr.j2 @@ -0,0 +1,21 @@ +! +{% if vrf is vyos_defined %} +vrf {{ vrf }} +{% if protocol is vyos_defined %} +{% for prot, prot_config in protocol.items() %} + {{ afi }} protocol {{ protocol }} route-map {{ prot_config.route_map }} +{% endfor %} +{% endif %} + exit-vrf +! +{% else %} +{% if protocol is vyos_defined %} +{% for prot, prot_config in protocol.items() %} +{% if prot is vyos_defined('ospfv3') %} +{% set prot = 'ospf6' %} +{% endif %} +{{ afi }} protocol {{ prot }} route-map {{ prot_config.route_map }} +{% endfor %} +{% endif %} +{% endif %} +! diff --git a/interface-definitions/include/system-ip-protocol.xml.i b/interface-definitions/include/system-ip-protocol.xml.i new file mode 100644 index 000000000..c630eb3f7 --- /dev/null +++ b/interface-definitions/include/system-ip-protocol.xml.i @@ -0,0 +1,56 @@ + + + + Filter routing info exchanged between routing protocol and zebra + + any babel bgp connected eigrp isis kernel ospf rip static table + + + any + Any of the above protocols + + + babel + Babel routing protocol + + + bgp + Border Gateway Protocol + + + connected + Connected routes (directly attached subnet or host) + + + eigrp + Enhanced Interior Gateway Routing Protocol + + + isis + Intermediate System to Intermediate System + + + kernel + Kernel routes (not installed via the zebra RIB) + + + ospf + Open Shortest Path First (OSPFv2) + + + rip + Routing Information Protocol + + + static + Statically configured routes + + + (any|babel|bgp|connected|eigrp|isis|kernel|ospf|rip|static|table) + + + + #include + + + \ No newline at end of file diff --git a/interface-definitions/include/system-ipv6-protocol.xml.i b/interface-definitions/include/system-ipv6-protocol.xml.i new file mode 100644 index 000000000..485776a71 --- /dev/null +++ b/interface-definitions/include/system-ipv6-protocol.xml.i @@ -0,0 +1,52 @@ + + + + Filter routing info exchanged between routing protocol and zebra + + any babel bgp connected isis kernel ospfv3 ripng static table + + + any + Any of the above protocols + + + babel + Babel routing protocol + + + bgp + Border Gateway Protocol + + + connected + Connected routes (directly attached subnet or host) + + + isis + Intermediate System to Intermediate System + + + kernel + Kernel routes (not installed via the zebra RIB) + + + ospfv3 + Open Shortest Path First (OSPFv3) + + + ripng + Routing Information Protocol next-generation + + + static + Statically configured routes + + + (any|babel|bgp|connected|isis|kernel|ospfv3|ripng|static|table) + + + + #include + + + diff --git a/interface-definitions/system-ip.xml.in b/interface-definitions/system-ip.xml.in index e00dbf252..abdede979 100644 --- a/interface-definitions/system-ip.xml.in +++ b/interface-definitions/system-ip.xml.in @@ -48,6 +48,7 @@ + #include diff --git a/interface-definitions/system-ipv6.xml.in b/interface-definitions/system-ipv6.xml.in index 63260d00c..e17e1c01c 100644 --- a/interface-definitions/system-ipv6.xml.in +++ b/interface-definitions/system-ipv6.xml.in @@ -36,6 +36,7 @@ #include + #include Disable IPv6 operation on interface when DAD fails on LL addr diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in index 96c6d8be2..028b31f7b 100644 --- a/interface-definitions/vrf.xml.in +++ b/interface-definitions/vrf.xml.in @@ -34,6 +34,7 @@ #include + #include @@ -42,6 +43,7 @@ #include + #include diff --git a/smoketest/scripts/cli/test_system_ip.py b/smoketest/scripts/cli/test_system_ip.py index f71ef5b3f..e7f7e3345 100755 --- a/smoketest/scripts/cli/test_system_ip.py +++ b/smoketest/scripts/cli/test_system_ip.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 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 @@ -17,6 +17,7 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.configsession import ConfigSessionError from vyos.util import read_file base_path = ['system', 'ip'] @@ -82,5 +83,31 @@ class TestSystemIP(VyOSUnitTestSHIM.TestCase): self.assertEqual(read_file(gc_thresh2), str(size // 2)) self.assertEqual(read_file(gc_thresh1), str(size // 8)) + def test_system_ip_protocol_route_map(self): + protocols = ['any', 'babel', 'bgp', 'connected', 'eigrp', 'isis', + 'kernel', 'ospf', 'rip', 'static', 'table'] + + for protocol in protocols: + self.cli_set(['policy', 'route-map', f'route-map-{protocol}', 'rule', '10', 'action', 'permit']) + self.cli_set(base_path + ['protocol', protocol, 'route-map', f'route-map-{protocol}']) + + self.cli_commit() + + # Verify route-map properly applied to FRR + frrconfig = self.getFRRconfig('ip protocol', end='', daemon='zebra') + for protocol in protocols: + self.assertIn(f'ip protocol {protocol} route-map route-map-{protocol}', frrconfig) + + def test_system_ip_protocol_non_existing_route_map(self): + non_existing = 'non-existing' + self.cli_set(base_path + ['protocol', 'static', 'route-map', non_existing]) + + # VRF does yet not exist - an error must be thrown + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(['policy', 'route-map', non_existing, 'rule', '10', 'action', 'deny']) + # Commit again + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index c8aea9100..e91b924fc 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -18,6 +18,7 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.configsession import ConfigSessionError from vyos.template import is_ipv4 from vyos.util import read_file from vyos.util import get_interface_config @@ -88,5 +89,36 @@ class TestSystemIPv6(VyOSUnitTestSHIM.TestCase): self.assertEqual(read_file(gc_thresh2), str(size // 2)) self.assertEqual(read_file(gc_thresh1), str(size // 8)) + def test_system_ipv6_protocol_route_map(self): + protocols = ['any', 'babel', 'bgp', 'connected', 'isis', + 'kernel', 'ospfv3', 'ripng', 'static', 'table'] + + for protocol in protocols: + route_map = 'route-map-' + protocol.replace('ospfv3', 'ospf6') + + self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) + self.cli_set(base_path + ['protocol', protocol, 'route-map', route_map]) + + self.cli_commit() + + # Verify route-map properly applied to FRR + frrconfig = self.getFRRconfig('ipv6 protocol', end='', daemon='zebra') + for protocol in protocols: + # VyOS and FRR use a different name for OSPFv3 (IPv6) + if protocol == 'ospfv3': + protocol = 'ospf6' + self.assertIn(f'ipv6 protocol {protocol} route-map route-map-{protocol}', frrconfig) + + def test_system_ipv6_protocol_non_existing_route_map(self): + non_existing = 'non-existing6' + self.cli_set(base_path + ['protocol', 'static', 'route-map', non_existing]) + + # VRF does yet not exist - an error must be thrown + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(['policy', 'route-map', non_existing, 'rule', '10', 'action', 'deny']) + # Commit again + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 3e5ebb805..3eabf24bc 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -105,17 +105,10 @@ def generate(static): def apply(static): static_daemon = 'staticd' - zebra_daemon = 'zebra' # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - # The route-map used for the FIB (zebra) is part of the zebra daemon - frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'^ip protocol static route-map [-a-zA-Z0-9.]+', '') - frr_cfg.commit_configuration(zebra_daemon) - frr_cfg.load_configuration(static_daemon) - if 'vrf' in static: vrf = static['vrf'] frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit', remove_stop_mark=True) diff --git a/src/conf_mode/system-ip.py b/src/conf_mode/system-ip.py index 0c5063ed3..95865c690 100755 --- a/src/conf_mode/system-ip.py +++ b/src/conf_mode/system-ip.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-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 @@ -18,12 +18,15 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_route_map +from vyos.template import render_to_string from vyos.util import call from vyos.util import dict_search from vyos.util import sysctl_write from vyos.util import write_file from vyos.xml import defaults from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() @@ -40,13 +43,30 @@ def get_config(config=None): default_values = defaults(base) opt = dict_merge(default_values, opt) + # When working with FRR we need to know the corresponding address-family + opt['afi'] = 'ip' + + # We also need the route-map information from the config + # + # XXX: one MUST always call this without the key_mangling() option! See + # vyos.configverify.verify_common_route_maps() for more information. + tmp = {'policy' : {'route-map' : conf.get_config_dict(['policy', 'route-map'], + get_first_key=True)}} + # Merge policy dict into "regular" config dict + opt = dict_merge(tmp, opt) return opt def verify(opt): - pass + if 'protocol' in opt: + for protocol, protocol_options in opt['protocol'].items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], opt) + return def generate(opt): - pass + if 'protocol' in opt: + opt['frr_zebra_config'] = render_to_string('frr/zebra.route-map.frr.j2', opt) + return def apply(opt): # Apply ARP threshold values @@ -78,6 +98,18 @@ def apply(opt): value = '1' if (tmp != None) else '0' sysctl_write('net.ipv4.fib_multipath_hash_policy', value) + if 'protocol' in opt: + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section(r'ip protocol \w+ route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in opt: + frr_cfg.add_before(frr.default_add_before, opt['frr_zebra_config']) + frr_cfg.commit_configuration(zebra_daemon) + if __name__ == '__main__': try: c = get_config() diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py index 26aacf46b..b6d3a79c3 100755 --- a/src/conf_mode/system-ipv6.py +++ b/src/conf_mode/system-ipv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-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,11 +19,14 @@ import os from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_route_map +from vyos.template import render_to_string from vyos.util import dict_search from vyos.util import sysctl_write from vyos.util import write_file from vyos.xml import defaults from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() @@ -41,13 +44,30 @@ def get_config(config=None): default_values = defaults(base) opt = dict_merge(default_values, opt) + # When working with FRR we need to know the corresponding address-family + opt['afi'] = 'ipv6' + + # We also need the route-map information from the config + # + # XXX: one MUST always call this without the key_mangling() option! See + # vyos.configverify.verify_common_route_maps() for more information. + tmp = {'policy' : {'route-map' : conf.get_config_dict(['policy', 'route-map'], + get_first_key=True)}} + # Merge policy dict into "regular" config dict + opt = dict_merge(tmp, opt) return opt def verify(opt): - pass + if 'protocol' in opt: + for protocol, protocol_options in opt['protocol'].items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], opt) + return def generate(opt): - pass + if 'protocol' in opt: + opt['frr_zebra_config'] = render_to_string('frr/zebra.route-map.frr.j2', opt) + return def apply(opt): # configure multipath @@ -78,6 +98,18 @@ def apply(opt): if name == 'accept_dad': write_file(os.path.join(root, name), value) + if 'protocol' in opt: + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section(r'ipv6 protocol \w+ route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in opt: + frr_cfg.add_before(frr.default_add_before, opt['frr_zebra_config']) + frr_cfg.commit_configuration(zebra_daemon) + if __name__ == '__main__': try: c = get_config() -- cgit v1.2.3 From f9aa4c6312a773c216e65400db7e66849d5a02c7 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 8 Apr 2023 22:15:41 +0200 Subject: T5150: do not apply zebra route-map from routing-daemon config level --- data/templates/frr/vrf.route-map.frr.j2 | 10 ---------- data/templates/frr/vrf.route-map.v6.frr.j2 | 10 ---------- .../include/bgp/protocol-common-config.xml.i | 1 - .../include/eigrp/protocol-common-config.xml.i | 1 - .../include/isis/protocol-common-config.xml.i | 1 - .../include/ospf/protocol-common-config.xml.i | 1 - .../include/ospfv3/protocol-common-config.xml.i | 1 - smoketest/scripts/cli/test_protocols_bgp.py | 21 --------------------- src/conf_mode/protocols_bgp.py | 11 ----------- src/conf_mode/protocols_eigrp.py | 10 ---------- src/conf_mode/protocols_isis.py | 14 ++------------ src/conf_mode/protocols_ospf.py | 11 +---------- src/conf_mode/protocols_ospfv3.py | 10 ---------- src/conf_mode/protocols_static.py | 1 + 14 files changed, 4 insertions(+), 99 deletions(-) delete mode 100644 data/templates/frr/vrf.route-map.frr.j2 delete mode 100644 data/templates/frr/vrf.route-map.v6.frr.j2 diff --git a/data/templates/frr/vrf.route-map.frr.j2 b/data/templates/frr/vrf.route-map.frr.j2 deleted file mode 100644 index 5e0c56a7b..000000000 --- a/data/templates/frr/vrf.route-map.frr.j2 +++ /dev/null @@ -1,10 +0,0 @@ -! -{% if vrf is vyos_defined and route_map is vyos_defined %} -vrf {{ vrf }} - ip protocol {{ protocol }} route-map {{ route_map }} - exit-vrf -! -{% elif route_map is vyos_defined %} -ip protocol {{ protocol }} route-map {{ route_map }} -{% endif %} -! diff --git a/data/templates/frr/vrf.route-map.v6.frr.j2 b/data/templates/frr/vrf.route-map.v6.frr.j2 deleted file mode 100644 index 7dc59a046..000000000 --- a/data/templates/frr/vrf.route-map.v6.frr.j2 +++ /dev/null @@ -1,10 +0,0 @@ -! -{% if vrf is vyos_defined and route_map is vyos_defined %} -vrf {{ vrf }} - ipv6 protocol {{ protocol }} route-map {{ route_map }} - exit-vrf -! -{% elif route_map is vyos_defined %} -ipv6 protocol {{ protocol }} route-map {{ route_map }} -{% endif %} -! diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index a9122db57..527eaf991 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -1565,7 +1565,6 @@ #include -#include BGP protocol timers diff --git a/interface-definitions/include/eigrp/protocol-common-config.xml.i b/interface-definitions/include/eigrp/protocol-common-config.xml.i index 88365187a..a21d18424 100644 --- a/interface-definitions/include/eigrp/protocol-common-config.xml.i +++ b/interface-definitions/include/eigrp/protocol-common-config.xml.i @@ -107,7 +107,6 @@ -#include #include diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 8103b5c5d..4ca7061db 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -687,5 +687,4 @@ -#include diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index e400119dd..b7f22cb88 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -816,7 +816,6 @@ -#include Adjust routing timers diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i index 1c33ca920..a7de50638 100644 --- a/interface-definitions/include/ospfv3/protocol-common-config.xml.i +++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i @@ -256,5 +256,4 @@ -#include diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index f6eede87a..ce9590fc2 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -713,7 +713,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): for prefix in listen_ranges: self.assertIn(f' bgp listen range {prefix} peer-group {peer_group}', frrconfig) - def test_bgp_07_l2vpn_evpn(self): vnis = ['10010', '10020', '10030'] neighbors = ['192.0.2.10', '192.0.2.20', '192.0.2.30'] @@ -743,26 +742,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' advertise-default-gw', vniconfig) self.assertIn(f' advertise-svi-ip', vniconfig) - def test_bgp_08_zebra_route_map(self): - # Implemented because of T3328 - self.cli_set(base_path + ['route-map', route_map_in]) - # commit changes - self.cli_commit() - - # Verify FRR configuration - zebra_route_map = f'ip protocol bgp route-map {route_map_in}' - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertIn(zebra_route_map, frrconfig) - - # Remove the route-map again - self.cli_delete(base_path + ['route-map']) - # commit changes - self.cli_commit() - - # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertNotIn(zebra_route_map, frrconfig) - def test_bgp_09_distance_and_flowspec(self): distance_external = '25' distance_internal = '30' diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index cf553f0e8..66505e58d 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -484,26 +484,15 @@ def generate(bgp): if not bgp or 'deleted' in bgp: return None - bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.j2 - bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', bgp) bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.j2', bgp) - return None def apply(bgp): bgp_daemon = 'bgpd' - zebra_daemon = 'zebra' # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - # The route-map used for the FIB (zebra) is part of the zebra daemon - frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') - if 'frr_zebra_config' in bgp: - frr_cfg.add_before(frr.default_add_before, bgp['frr_zebra_config']) - frr_cfg.commit_configuration(zebra_daemon) - # Generate empty helper string which can be ammended to FRR commands, it # will be either empty (default VRF) or contain the "vrf Date: Mon, 10 Apr 2023 10:57:34 +0200 Subject: T5150: initial VRF support for Kernel/Zebra route-map filtering --- data/configd-include.json | 1 - data/templates/frr/vrf-vni.frr.j2 | 9 --- data/templates/frr/zebra.route-map.frr.j2 | 26 +++------ data/templates/frr/zebra.vrf.route-map.frr.j2 | 24 ++++++++ interface-definitions/vrf.xml.in | 15 +---- smoketest/scripts/cli/test_protocols_bgp.py | 11 ---- smoketest/scripts/cli/test_vrf.py | 80 ++++++++++++++++++++++++++- src/conf_mode/protocols_static.py | 2 +- src/conf_mode/vrf.py | 49 ++++++++++++++-- src/conf_mode/vrf_vni.py | 65 ---------------------- 10 files changed, 155 insertions(+), 127 deletions(-) delete mode 100644 data/templates/frr/vrf-vni.frr.j2 create mode 100644 data/templates/frr/zebra.vrf.route-map.frr.j2 delete mode 100755 src/conf_mode/vrf_vni.py diff --git a/data/configd-include.json b/data/configd-include.json index 456211caa..1c843e9fa 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -86,5 +86,4 @@ "vpn_pptp.py", "vpn_sstp.py", "vrf.py", -"vrf_vni.py" ] diff --git a/data/templates/frr/vrf-vni.frr.j2 b/data/templates/frr/vrf-vni.frr.j2 deleted file mode 100644 index e5f4810a1..000000000 --- a/data/templates/frr/vrf-vni.frr.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{% if name is vyos_defined %} -{% for vrf, vrf_config in name.items() %} -vrf {{ vrf }} -{% if vrf_config.vni is vyos_defined %} - vni {{ vrf_config.vni }} -{% endif %} - exit-vrf -{% endfor %} -{% endif %} diff --git a/data/templates/frr/zebra.route-map.frr.j2 b/data/templates/frr/zebra.route-map.frr.j2 index bd461d904..8e18abbde 100644 --- a/data/templates/frr/zebra.route-map.frr.j2 +++ b/data/templates/frr/zebra.route-map.frr.j2 @@ -1,21 +1,9 @@ ! -{% if vrf is vyos_defined %} -vrf {{ vrf }} -{% if protocol is vyos_defined %} -{% for prot, prot_config in protocol.items() %} - {{ afi }} protocol {{ protocol }} route-map {{ prot_config.route_map }} -{% endfor %} -{% endif %} - exit-vrf -! -{% else %} -{% if protocol is vyos_defined %} -{% for prot, prot_config in protocol.items() %} -{% if prot is vyos_defined('ospfv3') %} -{% set prot = 'ospf6' %} -{% endif %} -{{ afi }} protocol {{ prot }} route-map {{ prot_config.route_map }} -{% endfor %} -{% endif %} +{% if protocol is vyos_defined %} +{% for protocol_name, protocol_config in protocol.items() %} +{% if protocol_name is vyos_defined('ospfv3') %} +{% set protocol_name = 'ospf6' %} +{% endif %} +{{ afi }} protocol {{ protocol_name }} route-map {{ protocol_config.route_map }} +{% endfor %} {% endif %} -! diff --git a/data/templates/frr/zebra.vrf.route-map.frr.j2 b/data/templates/frr/zebra.vrf.route-map.frr.j2 new file mode 100644 index 000000000..eb6abd8e7 --- /dev/null +++ b/data/templates/frr/zebra.vrf.route-map.frr.j2 @@ -0,0 +1,24 @@ +! +{% if name is vyos_defined %} +{% for vrf, vrf_config in name.items() %} +vrf {{ vrf }} +{% if vrf_config.ip.protocol is vyos_defined %} +{% for protocol_name, protocol_config in vrf_config.ip.protocol.items() %} + ip protocol {{ protocol_name }} route-map {{ protocol_config.route_map }} +{% endfor %} +{% endif %} +{% if vrf_config.ipv6.protocol is vyos_defined %} +{% for protocol_name, protocol_config in vrf_config.ipv6.protocol.items() %} +{% if protocol_name is vyos_defined('ospfv3') %} +{% set protocol_name = 'ospf6' %} +{% endif %} + ipv6 protocol {{ protocol_name }} route-map {{ protocol_config.route_map }} +{% endfor %} +{% endif %} +{% if vrf_config.vni is vyos_defined %} + vni {{ vrf_config.vni }} +{% endif %} +{% endfor %} + exit-vrf +! +{% endif %} diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in index 028b31f7b..a7efe146a 100644 --- a/interface-definitions/vrf.xml.in +++ b/interface-definitions/vrf.xml.in @@ -121,20 +121,7 @@ VRF routing table must be in range from 100 to 65535 - - - Virtual Network Identifier - - 822 - - u32:0-16777214 - VXLAN virtual network identifier - - - - - - + #include diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index ce9590fc2..2fd5d0c9b 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -809,7 +809,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(vrf_base + ['table', table]) self.cli_set(vrf_base + ['protocols', 'bgp', 'system-as', ASN]) self.cli_set(vrf_base + ['protocols', 'bgp', 'parameters', 'router-id', router_id]) - self.cli_set(vrf_base + ['protocols', 'bgp', 'route-map', route_map_in]) table = str(int(table) + 1000) # import VRF routes do main RIB @@ -822,7 +821,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f'router bgp {ASN}', frrconfig) self.assertIn(f' address-family ipv6 unicast', frrconfig) - for vrf in vrfs: self.assertIn(f' import vrf {vrf}', frrconfig) @@ -831,15 +829,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f'router bgp {ASN} vrf {vrf}', frr_vrf_config) self.assertIn(f' bgp router-id {router_id}', frr_vrf_config) - # XXX: Currently this is not working as FRR() class does not support - # route-maps for multiple vrfs because the modify_section() only works - # on lines and not text blocks. - # - # vrfconfig = self.getFRRconfig(f'vrf {vrf}') - # zebra_route_map = f' ip protocol bgp route-map {route_map_in}' - # self.assertIn(zebra_route_map, vrfconfig) - - def test_bgp_11_confederation(self): router_id = '127.10.10.2' confed_id = str(int(ASN) + 1) diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py index 176c095fb..8016c0105 100755 --- a/smoketest/scripts/cli/test_vrf.py +++ b/smoketest/scripts/cli/test_vrf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2022 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 @@ -33,6 +33,8 @@ from vyos.validate import is_intf_addr_assigned base_path = ['vrf'] vrfs = ['red', 'green', 'blue', 'foo-bar', 'baz_foo'] +v4_protocols = ['any', 'babel', 'bgp', 'connected', 'eigrp', 'isis', 'kernel', 'ospf', 'rip', 'static', 'table'] +v6_protocols = ['any', 'babel', 'bgp', 'connected', 'isis', 'kernel', 'ospfv3', 'ripng', 'static', 'table'] class VRFTest(VyOSUnitTestSHIM.TestCase): _interfaces = [] @@ -291,5 +293,81 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): self.assertEqual(read_file(f'/proc/sys/net/ipv4/conf/{vrf}/forwarding'), '0') self.assertEqual(read_file(f'/proc/sys/net/ipv6/conf/{vrf}/forwarding'), '0') + def test_vrf_ip_protocol_route_map(self): + table = '6000' + + for vrf in vrfs: + base = base_path + ['name', vrf] + self.cli_set(base + ['table', table]) + + for protocol in v4_protocols: + self.cli_set(['policy', 'route-map', f'route-map-{vrf}-{protocol}', 'rule', '10', 'action', 'permit']) + self.cli_set(base + ['ip', 'protocol', protocol, 'route-map', f'route-map-{vrf}-{protocol}']) + + table = str(int(table) + 1) + + self.cli_commit() + + # Verify route-map properly applied to FRR + for vrf in vrfs: + frrconfig = self.getFRRconfig(f'vrf {vrf}', daemon='zebra') + self.assertIn(f'vrf {vrf}', frrconfig) + for protocol in v4_protocols: + self.assertIn(f' ip protocol {protocol} route-map route-map-{vrf}-{protocol}', frrconfig) + + def test_vrf_ip_ipv6_protocol_non_existing_route_map(self): + table = '6100' + non_existing = 'non-existing' + + for vrf in vrfs: + base = base_path + ['name', vrf] + self.cli_set(base + ['table', table]) + for protocol in v4_protocols: + self.cli_set(base + ['ip', 'protocol', protocol, 'route-map', f'v4-{non_existing}']) + for protocol in v6_protocols: + self.cli_set(base + ['ipv6', 'protocol', protocol, 'route-map', f'v6-{non_existing}']) + + table = str(int(table) + 1) + + # Both v4 and v6 route-maps do not exist yet + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(['policy', 'route-map', f'v4-{non_existing}', 'rule', '10', 'action', 'deny']) + + # v6 route-map does not exist yet + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(['policy', 'route-map', f'v6-{non_existing}', 'rule', '10', 'action', 'deny']) + + # Commit again + self.cli_commit() + + def test_vrf_ipv6_protocol_route_map(self): + table = '6200' + + for vrf in vrfs: + base = base_path + ['name', vrf] + self.cli_set(base + ['table', table]) + + for protocol in v6_protocols: + route_map = f'route-map-{vrf}-{protocol.replace("ospfv3", "ospf6")}' + self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) + self.cli_set(base + ['ipv6', 'protocol', protocol, 'route-map', route_map]) + + table = str(int(table) + 1) + + self.cli_commit() + + # Verify route-map properly applied to FRR + for vrf in vrfs: + frrconfig = self.getFRRconfig(f'vrf {vrf}', daemon='zebra') + self.assertIn(f'vrf {vrf}', frrconfig) + for protocol in v6_protocols: + # VyOS and FRR use a different name for OSPFv3 (IPv6) + if protocol == 'ospfv3': + protocol = 'ospf6' + route_map = f'route-map-{vrf}-{protocol}' + self.assertIn(f' ipv6 protocol {protocol} route-map {route_map}', frrconfig) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 5122f60b2..7b6150696 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -112,7 +112,7 @@ def apply(static): if 'vrf' in static: vrf = static['vrf'] - frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit', remove_stop_mark=True) + frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit-vrf', remove_stop_mark=True) else: frr_cfg.modify_section(r'^ip route .*') frr_cfg.modify_section(r'^ipv6 route .*') diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index c17cca3bd..a7ef4cb5c 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -20,9 +20,12 @@ from sys import exit from json import loads from vyos.config import Config +from vyos.configdict import dict_merge from vyos.configdict import node_changed +from vyos.configverify import verify_route_map from vyos.ifconfig import Interface from vyos.template import render +from vyos.template import render_to_string from vyos.util import call from vyos.util import cmd from vyos.util import dict_search @@ -99,6 +102,14 @@ def get_config(config=None): routes = vrf_routing(conf, name) if routes: vrf['vrf_remove'][name]['route'] = routes + # We also need the route-map information from the config + # + # XXX: one MUST always call this without the key_mangling() option! See + # vyos.configverify.verify_common_route_maps() for more information. + tmp = {'policy' : {'route-map' : conf.get_config_dict(['policy', 'route-map'], + get_first_key=True)}} + # Merge policy dict into "regular" config dict + vrf = dict_merge(tmp, vrf) return vrf def verify(vrf): @@ -116,35 +127,50 @@ def verify(vrf): reserved_names = ["add", "all", "broadcast", "default", "delete", "dev", "get", "inet", "mtu", "link", "type", "vrf"] table_ids = [] - for name, config in vrf['name'].items(): + for name, vrf_config in vrf['name'].items(): # Reserved VRF names if name in reserved_names: raise ConfigError(f'VRF name "{name}" is reserved and connot be used!') # table id is mandatory - if 'table' not in config: + if 'table' not in vrf_config: raise ConfigError(f'VRF "{name}" table id is mandatory!') # routing table id can't be changed - OS restriction if os.path.isdir(f'/sys/class/net/{name}'): tmp = str(dict_search('linkinfo.info_data.table', get_interface_config(name))) - if tmp and tmp != config['table']: + if tmp and tmp != vrf_config['table']: raise ConfigError(f'VRF "{name}" table id modification not possible!') # VRf routing table ID must be unique on the system - if config['table'] in table_ids: + if vrf_config['table'] in table_ids: raise ConfigError(f'VRF "{name}" table id is not unique!') - table_ids.append(config['table']) + table_ids.append(vrf_config['table']) + + tmp = dict_search('ip.protocol', vrf_config) + if tmp != None: + for protocol, protocol_options in tmp.items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], vrf) + + tmp = dict_search('ipv6.protocol', vrf_config) + if tmp != None: + for protocol, protocol_options in tmp.items(): + if 'route_map' in protocol_options: + verify_route_map(protocol_options['route_map'], vrf) return None def generate(vrf): + # Render iproute2 VR helper names render(config_file, 'iproute2/vrf.conf.j2', vrf) # Render nftables zones config render(nft_vrf_config, 'firewall/nftables-vrf-zones.j2', vrf) - return None + # Render VRF Kernel/Zebra route-map filters + vrf['frr_zebra_config'] = render_to_string('frr/zebra.vrf.route-map.frr.j2', vrf) + return None def apply(vrf): # Documentation @@ -249,6 +275,17 @@ def apply(vrf): nft_add_element = f'add element inet vrf_zones ct_iface_map {{ "{name}" : {table} }}' cmd(f'nft {nft_add_element}') + # Apply FRR filters + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section(f'^vrf .+', stop_pattern='^exit-vrf', remove_stop_mark=True) + if 'frr_zebra_config' in vrf: + frr_cfg.add_before(frr.default_add_before, vrf['frr_zebra_config']) + frr_cfg.commit_configuration(zebra_daemon) # return to default lookup preference when no VRF is configured if 'name' not in vrf: diff --git a/src/conf_mode/vrf_vni.py b/src/conf_mode/vrf_vni.py deleted file mode 100755 index 585fdbebf..000000000 --- a/src/conf_mode/vrf_vni.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020-2021 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 -# 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 . - -from sys import argv -from sys import exit - -from vyos.config import Config -from vyos.template import render_to_string -from vyos import ConfigError -from vyos import frr -from vyos import airbag -airbag.enable() - -frr_daemon = 'zebra' - -def get_config(config=None): - if config: - conf = config - else: - conf = Config() - - base = ['vrf'] - vrf = conf.get_config_dict(base, get_first_key=True) - return vrf - -def verify(vrf): - return None - -def generate(vrf): - vrf['new_frr_config'] = render_to_string('frr/vrf-vni.frr.j2', vrf) - return None - -def apply(vrf): - # add configuration to FRR - frr_cfg = frr.FRRConfig() - frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section(f'^vrf .+', stop_pattern='^exit-vrf', remove_stop_mark=True) - if 'new_frr_config' in vrf: - frr_cfg.add_before(frr.default_add_before, vrf['new_frr_config']) - frr_cfg.commit_configuration(frr_daemon) - - return None - -if __name__ == '__main__': - try: - c = get_config() - verify(c) - generate(c) - apply(c) - except ConfigError as e: - print(e) - exit(1) -- cgit v1.2.3 From 7d642a2862dcd0c7c2f80ac42ea9427970804d06 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 12 Apr 2023 21:11:50 +0200 Subject: T5150: migrate CLI configs to new Kernel/Zebra route-map support --- .../include/version/bgp-version.xml.i | 2 +- .../include/version/isis-version.xml.i | 2 +- .../include/version/ospf-version.xml.i | 2 +- .../include/version/quagga-version.xml.i | 2 +- .../include/version/rip-version.xml.i | 3 + interface-definitions/xml-component-version.xml.in | 1 + smoketest/configs/egb-igp-route-maps | 127 +++++++++++++++++++++ src/migration-scripts/bgp/3-to-4 | 64 +++++++++++ src/migration-scripts/isis/2-to-3 | 63 ++++++++++ src/migration-scripts/ospf/1-to-2 | 80 +++++++++++++ src/migration-scripts/quagga/10-to-11 | 51 +++++++++ src/migration-scripts/rip/0-to-1 | 51 +++++++++ 12 files changed, 444 insertions(+), 4 deletions(-) create mode 100644 interface-definitions/include/version/rip-version.xml.i create mode 100644 smoketest/configs/egb-igp-route-maps create mode 100755 src/migration-scripts/bgp/3-to-4 create mode 100755 src/migration-scripts/isis/2-to-3 create mode 100755 src/migration-scripts/ospf/1-to-2 create mode 100755 src/migration-scripts/quagga/10-to-11 create mode 100755 src/migration-scripts/rip/0-to-1 diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i index ced49e729..1386ea9bc 100644 --- a/interface-definitions/include/version/bgp-version.xml.i +++ b/interface-definitions/include/version/bgp-version.xml.i @@ -1,3 +1,3 @@ - + diff --git a/interface-definitions/include/version/isis-version.xml.i b/interface-definitions/include/version/isis-version.xml.i index 7bf12e81a..f50329b09 100644 --- a/interface-definitions/include/version/isis-version.xml.i +++ b/interface-definitions/include/version/isis-version.xml.i @@ -1,3 +1,3 @@ - + diff --git a/interface-definitions/include/version/ospf-version.xml.i b/interface-definitions/include/version/ospf-version.xml.i index 755965daa..df108837b 100644 --- a/interface-definitions/include/version/ospf-version.xml.i +++ b/interface-definitions/include/version/ospf-version.xml.i @@ -1,3 +1,3 @@ - + diff --git a/interface-definitions/include/version/quagga-version.xml.i b/interface-definitions/include/version/quagga-version.xml.i index f9944acce..23d884cd4 100644 --- a/interface-definitions/include/version/quagga-version.xml.i +++ b/interface-definitions/include/version/quagga-version.xml.i @@ -1,3 +1,3 @@ - + diff --git a/interface-definitions/include/version/rip-version.xml.i b/interface-definitions/include/version/rip-version.xml.i new file mode 100644 index 000000000..30ace486a --- /dev/null +++ b/interface-definitions/include/version/rip-version.xml.i @@ -0,0 +1,3 @@ + + + diff --git a/interface-definitions/xml-component-version.xml.in b/interface-definitions/xml-component-version.xml.in index 2e6506efc..e05f64643 100644 --- a/interface-definitions/xml-component-version.xml.in +++ b/interface-definitions/xml-component-version.xml.in @@ -33,6 +33,7 @@ #include #include #include + #include #include #include #include diff --git a/smoketest/configs/egb-igp-route-maps b/smoketest/configs/egb-igp-route-maps new file mode 100644 index 000000000..ca36691d4 --- /dev/null +++ b/smoketest/configs/egb-igp-route-maps @@ -0,0 +1,127 @@ +interfaces { + ethernet eth0 { + address 192.0.2.1/25 + duplex auto + smp-affinity auto + speed auto + } + ethernet eth1 { + address 192.0.2.129/25 + address 2001:db8::1234/64 + duplex auto + smp-affinity auto + speed auto + } + loopback lo { + } +} +policy { + route-map zebra-bgp { + rule 10 { + action permit + } + } + route-map zebra-isis { + rule 10 { + action permit + } + } + route-map zebra-ospf { + rule 10 { + action permit + } + } + route-map zebra-ospfv3 { + rule 10 { + action permit + } + } + route-map zebra-ripng { + rule 10 { + action permit + } + } + route-map zebra-static { + rule 10 { + action permit + } + } +} +protocols { + bgp 100 { + route-map zebra-bgp + } + isis { + interface eth0 { + } + net 49.0001.1921.6800.1002.00 + route-map zebra-isis + } + ospf { + area 0 { + network 192.0.2.0/25 + network 192.0.2.128/25 + } + log-adjacency-changes { + } + parameters { + abr-type cisco + router-id 1.1.1.1 + } + passive-interface default + passive-interface-exclude eth0 + passive-interface-exclude eth1 + route-map zebra-ospf + } + ospfv3 { + area 0 { + interface eth1 + } + parameters { + router-id 1.1.1.1 + } + route-map zebra-ospfv3 + } + ripng { + interface eth1 + route-map zebra-ripng + } + static { + route-map zebra-static + } +} +system { + config-management { + commit-revisions 100 + } + console { + device ttyS0 { + speed 115200 + } + } + host-name vyos + login { + user vyos { + authentication { + encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 + plaintext-password "" + } + } + } + name-server 192.168.0.1 + syslog { + global { + archive { + file 5 + size 512 + } + facility all { + level info + } + } + } + time-zone Europe/Berlin +} +// Warning: Do not remove the following line. +// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1" +// Release version: 1.3.2 diff --git a/src/migration-scripts/bgp/3-to-4 b/src/migration-scripts/bgp/3-to-4 new file mode 100755 index 000000000..0df2fbec4 --- /dev/null +++ b/src/migration-scripts/bgp/3-to-4 @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +# T5150: Rework CLI definitions to apply route-maps between routing daemons +# and zebra/kernel + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +bgp_base = ['protocols', 'bgp'] +# Check if BGP is configured - if so, migrate the CLI node +if config.exists(bgp_base): + if config.exists(bgp_base + ['route-map']): + tmp = config.return_value(bgp_base + ['route-map']) + + config.set(['system', 'ip', 'protocol', 'bgp', 'route-map'], value=tmp) + config.set_tag(['system', 'ip', 'protocol']) + config.delete(bgp_base + ['route-map']) + + +# Check if vrf names are configured. Check if BGP is configured - if so, migrate +# the CLI node(s) +if config.exists(['vrf', 'name']): + for vrf in config.list_nodes(['vrf', 'name']): + vrf_base = ['vrf', 'name', vrf] + if config.exists(vrf_base + ['protocols', 'bgp', 'route-map']): + tmp = config.return_value(vrf_base + ['protocols', 'bgp', 'route-map']) + + config.set(vrf_base + ['ip', 'protocol', 'bgp', 'route-map'], value=tmp) + config.set_tag(vrf_base + ['ip', 'protocol', 'bgp']) + config.delete(vrf_base + ['protocols', 'bgp', 'route-map']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/isis/2-to-3 b/src/migration-scripts/isis/2-to-3 new file mode 100755 index 000000000..4490feb0a --- /dev/null +++ b/src/migration-scripts/isis/2-to-3 @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +# T5150: Rework CLI definitions to apply route-maps between routing daemons +# and zebra/kernel + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +isis_base = ['protocols', 'isis'] +# Check if IS-IS is configured - if so, migrate the CLI node +if config.exists(isis_base): + if config.exists(isis_base + ['route-map']): + tmp = config.return_value(isis_base + ['route-map']) + + config.set(['system', 'ip', 'protocol', 'isis', 'route-map'], value=tmp) + config.set_tag(['system', 'ip', 'protocol']) + config.delete(isis_base + ['route-map']) + +# Check if vrf names are configured. Check if IS-IS is configured - if so, +# migrate the CLI node(s) +if config.exists(['vrf', 'name']): + for vrf in config.list_nodes(['vrf', 'name']): + vrf_base = ['vrf', 'name', vrf] + if config.exists(vrf_base + ['protocols', 'isis', 'route-map']): + tmp = config.return_value(vrf_base + ['protocols', 'isis', 'route-map']) + + config.set(vrf_base + ['ip', 'protocol', 'isis', 'route-map'], value=tmp) + config.set_tag(vrf_base + ['ip', 'protocol', 'isis']) + config.delete(vrf_base + ['protocols', 'isis', 'route-map']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/ospf/1-to-2 b/src/migration-scripts/ospf/1-to-2 new file mode 100755 index 000000000..a6beaf04e --- /dev/null +++ b/src/migration-scripts/ospf/1-to-2 @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +# T5150: Rework CLI definitions to apply route-maps between routing daemons +# and zebra/kernel + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +ospf_base = ['protocols', 'ospf'] +# Check if OSPF is configured - if so, migrate the CLI node +if config.exists(ospf_base): + if config.exists(ospf_base + ['route-map']): + tmp = config.return_value(ospf_base + ['route-map']) + + config.set(['system', 'ip', 'protocol', 'ospf', 'route-map'], value=tmp) + config.set_tag(['system', 'ip', 'protocol']) + config.delete(ospf_base + ['route-map']) + +ospfv3_base = ['protocols', 'ospfv3'] +# Check if OSPFv3 is configured - if so, migrate the CLI node +if config.exists(ospfv3_base): + if config.exists(ospfv3_base + ['route-map']): + tmp = config.return_value(ospfv3_base + ['route-map']) + + config.set(['system', 'ipv6', 'protocol', 'ospfv3', 'route-map'], value=tmp) + config.set_tag(['system', 'ipv6', 'protocol']) + config.delete(ospfv3_base + ['route-map']) + +# Check if vrf names are configured. Check if OSPF/OSPFv3 is configured - if so, +# migrate the CLI node(s) +if config.exists(['vrf', 'name']): + for vrf in config.list_nodes(['vrf', 'name']): + vrf_base = ['vrf', 'name', vrf] + if config.exists(vrf_base + ['protocols', 'ospf', 'route-map']): + tmp = config.return_value(vrf_base + ['protocols', 'ospf', 'route-map']) + + config.set(vrf_base + ['ip', 'protocol', 'ospf', 'route-map'], value=tmp) + config.set_tag(vrf_base + ['ip', 'protocol', 'ospf']) + config.delete(vrf_base + ['protocols', 'ospf', 'route-map']) + + if config.exists(vrf_base + ['protocols', 'ospfv3', 'route-map']): + tmp = config.return_value(vrf_base + ['protocols', 'ospfv3', 'route-map']) + + config.set(vrf_base + ['ipv6', 'protocol', 'ospfv3', 'route-map'], value=tmp) + config.set_tag(vrf_base + ['ipv6', 'protocol', 'ospfv6']) + config.delete(vrf_base + ['protocols', 'ospfv3', 'route-map']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/quagga/10-to-11 b/src/migration-scripts/quagga/10-to-11 new file mode 100755 index 000000000..04fc16f79 --- /dev/null +++ b/src/migration-scripts/quagga/10-to-11 @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +# T5150: Rework CLI definitions to apply route-maps between routing daemons +# and zebra/kernel + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +static_base = ['protocols', 'static'] +# Check if static routes are configured - if so, migrate the CLI node +if config.exists(static_base): + if config.exists(static_base + ['route-map']): + tmp = config.return_value(static_base + ['route-map']) + + config.set(['system', 'ip', 'protocol', 'static', 'route-map'], value=tmp) + config.set_tag(['system', 'ip', 'protocol']) + config.delete(static_base + ['route-map']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/rip/0-to-1 b/src/migration-scripts/rip/0-to-1 new file mode 100755 index 000000000..60d510001 --- /dev/null +++ b/src/migration-scripts/rip/0-to-1 @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 . + +# T5150: Rework CLI definitions to apply route-maps between routing daemons +# and zebra/kernel + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +ripng_base = ['protocols', 'ripng'] +# Check if RIPng is configured - if so, migrate the CLI node +if config.exists(ripng_base): + if config.exists(ripng_base + ['route-map']): + tmp = config.return_value(ripng_base + ['route-map']) + + config.set(['system', 'ipv6', 'protocol', 'ripng', 'route-map'], value=tmp) + config.set_tag(['system', 'ipv6', 'protocol']) + config.delete(ripng_base + ['route-map']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) -- cgit v1.2.3 From 64871ad75ab028cbc6d8fcbb5e334c8944954162 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 13 Apr 2023 09:04:08 +0200 Subject: xml: dns: T5143: valueHelp format should be txt instead of text The (v)bash completion helpers trigger on the "txt" keyword for the valueHelp strings when asking for the tab completion helper. Replace text -> txt --- interface-definitions/dns-forwarding.xml.in | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index 2b6892ce5..6b7344b1d 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -84,7 +84,7 @@ Domain to forward to a custom DNS server - text + txt An absolute DNS domain name @@ -111,7 +111,7 @@ Domain to host authoritative records for - text + txt An absolute DNS domain name @@ -128,7 +128,7 @@ "A" record - text + txt A DNS name relative to the root record @@ -165,7 +165,7 @@ "AAAA" record - text + txt A DNS name relative to the root record @@ -202,7 +202,7 @@ "CNAME" record - text + txt A DNS name relative to the root record @@ -234,7 +234,7 @@ "MX" record - text + txt A DNS name relative to the root record @@ -281,7 +281,7 @@ "PTR" record - text + txt A DNS name relative to the root record @@ -313,7 +313,7 @@ "TXT" record - text + txt A DNS name relative to the root record @@ -329,7 +329,7 @@ Record contents - text + txt Record contents @@ -343,7 +343,7 @@ "SPF" record (type=SPF) - text + txt A DNS name relative to the root record @@ -359,7 +359,7 @@ Record contents - text + txt Record contents @@ -372,7 +372,7 @@ "SRV" record - text + txt A DNS name relative to the root record @@ -456,7 +456,7 @@ "NAPTR" record - text + txt A DNS name relative to the root record -- cgit v1.2.3 From 78d846824df05682f63c2dc7d894aa501ed9f63f Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 13 Apr 2023 09:08:10 +0200 Subject: xml: T5137: fix empty node.def files --- Makefile | 1 + op-mode-definitions/show-techsupport_report.xml.in | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4f49f0d27..e130bec70 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,7 @@ op_mode_definitions: $(op_xml_obj) rm -f $(OP_TMPL_DIR)/set/node.def rm -f $(OP_TMPL_DIR)/show/node.def rm -f $(OP_TMPL_DIR)/show/system/node.def + rm -f $(OP_TMPL_DIR)/show/tech-support/node.def # XXX: ping and traceroute must be able to recursivly call itself as the # options are provided from the script itself diff --git a/op-mode-definitions/show-techsupport_report.xml.in b/op-mode-definitions/show-techsupport_report.xml.in index 6f38105f8..aa51eacd9 100644 --- a/op-mode-definitions/show-techsupport_report.xml.in +++ b/op-mode-definitions/show-techsupport_report.xml.in @@ -2,7 +2,7 @@ - + -- cgit v1.2.3 From 2a876059826927ef204e359a40395955f27503ce Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Fri, 14 Apr 2023 08:22:52 +0200 Subject: container: T5082: shorten container network prefix to allow longer names If the name of the network + the length of the podman- prefix exceeds the maximum supported length of netavark we get an error: Error: netavark: get bridge interface: Netlink error: Numerical result out of range (os error 34) --- src/conf_mode/container.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 4b7ab3444..cb39f19b6 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -376,7 +376,7 @@ def generate(container): 'name': network, 'id' : sha256(f'{network}'.encode()).hexdigest(), 'driver': 'bridge', - 'network_interface': f'podman-{network}', + 'network_interface': f'pod-{network}', 'subnets': [], 'ipv6_enabled': False, 'internal': False, @@ -479,7 +479,7 @@ def apply(container): # the network interface in advance if 'network' in container: for network, network_config in container['network'].items(): - network_name = f'podman-{network}' + network_name = f'pod-{network}' # T5147: Networks are started only as soon as there is a consumer. # If only a network is created in the first place, no need to assign # it to a VRF as there's no consumer, yet. -- cgit v1.2.3 From 42775f287cca3e08dc8b2e58958018ecd1c626c9 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Fri, 14 Apr 2023 08:29:50 +0200 Subject: container: T5082: enable aardvark-dns support With commit 0ea3e1420 ("container: T5082: switch to netavark network stack") moving to a new network stack we should also enable the new DNS plugin provided by default. TODO: add CLI nodes to manually disable DNS and/or supply external DNS servers to the container. --- debian/control | 1 + src/conf_mode/container.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 856f57030..3126e6ad9 100644 --- a/debian/control +++ b/debian/control @@ -34,6 +34,7 @@ Package: vyos-1x Architecture: amd64 arm64 Depends: ${python3:Depends}, + aardvark-dns, accel-ppp, auditd, avahi-daemon, diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index cb39f19b6..aceb27fb0 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -380,7 +380,7 @@ def generate(container): 'subnets': [], 'ipv6_enabled': False, 'internal': False, - 'dns_enabled': False, + 'dns_enabled': True, 'ipam_options': { 'driver': 'host-local' } -- cgit v1.2.3 From 4f2bcebb7f44633fa5adfd62ddd88098832025ed Mon Sep 17 00:00:00 2001 From: KyleM <103862795+ServerForge@users.noreply.github.com> Date: Fri, 14 Apr 2023 15:18:22 -0400 Subject: T5162: Updated configd-include.json to remove extra comma. removed extra comma invalidating json. --- data/configd-include.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/configd-include.json b/data/configd-include.json index 1c843e9fa..2f1d39006 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -85,5 +85,5 @@ "vpn_l2tp.py", "vpn_pptp.py", "vpn_sstp.py", -"vrf.py", +"vrf.py" ] -- cgit v1.2.3 From 7700da10b8d1d1b3d0db914ab48aebf8ff536da1 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 15 Apr 2023 15:29:53 +0200 Subject: vyos.ifconfig: T2104: support adding and removing VLANs in one call. VLANIf('eth0.10').remove() will create and remove the VLAN in one command. Thus one can ensure when calling remove() on a VLAN it will always succeed. --- python/vyos/ifconfig/interface.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index fc33430eb..f62b9f7d2 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1709,6 +1709,14 @@ class VLANIf(Interface): if self.exists(f'{self.ifname}'): return + # If source_interface or vlan_id was not explicitly defined (e.g. when + # calling VLANIf('eth0.1').remove() we can define source_interface and + # vlan_id here, as it's quiet obvious that it would be eth0 in that case. + if 'source_interface' not in self.config: + self.config['source_interface'] = '.'.join(self.ifname.split('.')[:-1]) + if 'vlan_id' not in self.config: + self.config['vlan_id'] = self.ifname.split('.')[-1] + cmd = 'ip link add link {source_interface} name {ifname} type vlan id {vlan_id}' if 'protocol' in self.config: cmd += ' protocol {protocol}' -- cgit v1.2.3 From 8550b8dbdd445399e7f97f76319df7d66fcc2502 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sat, 15 Apr 2023 22:14:25 +0200 Subject: smoketest: T5150: remove deprecated tests There is no need for protocol specific embedded smoketests as the route-map option got removed. Tests are now conducted under the new CLI tree. --- smoketest/scripts/cli/test_protocols_isis.py | 47 ++++---------------------- smoketest/scripts/cli/test_protocols_ospf.py | 32 ++++-------------- smoketest/scripts/cli/test_protocols_static.py | 25 -------------- 3 files changed, 13 insertions(+), 91 deletions(-) diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 61e29c449..f1a030e77 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -119,39 +119,6 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_delete(['vrf', 'name', vrf]) self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) - def test_isis_03_zebra_route_map(self): - # Implemented because of T3328 - route_map = 'foo-isis-in' - - self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) - - self.isis_base_config() - self.cli_set(base_path + ['redistribute', 'ipv4', 'connected', 'level-2', 'route-map', route_map]) - self.cli_set(base_path + ['route-map', route_map]) - self.cli_set(base_path + ['level', 'level-2']) - - # commit changes - self.cli_commit() - - # Verify FRR configuration - zebra_route_map = f'ip protocol isis route-map {route_map}' - frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') - self.assertIn(zebra_route_map, frrconfig) - - tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') - self.assertIn(' is-type level-2-only', tmp) - - # Remove the route-map again - self.cli_delete(base_path + ['route-map']) - # commit changes - self.cli_commit() - - # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') - self.assertNotIn(zebra_route_map, frrconfig) - - self.cli_delete(['policy', 'route-map', route_map]) - def test_isis_04_default_information(self): metric = '50' route_map = 'default-foo-' @@ -293,7 +260,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['segment-routing', 'prefix', prefix_three, 'absolute', 'explicit-null']) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_four, 'absolute', 'value', prefix_four_value]) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_four, 'absolute', 'no-php-flag']) - + # Commit all changes self.cli_commit() @@ -315,16 +282,16 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['net', net]) self.cli_set(base_path + ['interface', interface]) self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) - + # Commit main ISIS changes self.cli_commit() - + # Verify main ISIS changes tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' mpls ldp-sync', tmp) self.assertIn(f' mpls ldp-sync holddown {holddown}', tmp) - + for interface in self._interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) @@ -337,13 +304,13 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' ip router isis {domain}', tmp) self.assertIn(f' ipv6 router isis {domain}', tmp) self.assertIn(f' isis mpls ldp-sync holddown {holddown}', tmp) - + for interface in self._interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) - + # Commit interface changes for disable self.cli_commit() - + # Verify interface changes for disable tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') self.assertIn(f'interface {interface}', tmp) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index d4c85f2b2..6fe6dd979 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -300,26 +300,6 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' no ip ospf passive', config) self.assertIn(f' bandwidth {bandwidth}', config) - def test_ospf_10_zebra_route_map(self): - # Implemented because of T3328 - self.cli_set(base_path + ['route-map', route_map]) - # commit changes - self.cli_commit() - - # Verify FRR configuration - zebra_route_map = f'ip protocol ospf route-map {route_map}' - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertIn(zebra_route_map, frrconfig) - - # Remove the route-map again - self.cli_delete(base_path + ['route-map']) - # commit changes - self.cli_commit() - - # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertNotIn(zebra_route_map, frrconfig) - def test_ospf_11_interface_area(self): area = '0' interfaces = Section.interfaces('ethernet') @@ -441,16 +421,16 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['interface', interface]) self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) - + # Commit main OSPF changes self.cli_commit() - + # Verify main OSPF changes frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) self.assertIn(f' mpls ldp-sync holddown {holddown}', frrconfig) - + for interface in interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) @@ -463,13 +443,13 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' ip ospf dead-interval 40', config) self.assertIn(f' ip ospf mpls ldp-sync', config) self.assertIn(f' ip ospf mpls ldp-sync holddown {holddown}', config) - + for interface in interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) - + # Commit interface changes for disable self.cli_commit() - + # Verify interface changes for disable config = self.getFRRconfig(f'interface {interface}') self.assertIn(f'interface {interface}', config) diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py index 19efe7786..bc023f3f2 100755 --- a/smoketest/scripts/cli/test_protocols_static.py +++ b/smoketest/scripts/cli/test_protocols_static.py @@ -433,30 +433,5 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, frrconfig) - def test_04_static_zebra_route_map(self): - # Implemented because of T3328 - route_map = 'foo-static-in' - self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) - - self.cli_set(base_path + ['route-map', route_map]) - # commit changes - self.cli_commit() - - # Verify FRR configuration - zebra_route_map = f'ip protocol static route-map {route_map}' - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertIn(zebra_route_map, frrconfig) - - # Remove the route-map again - self.cli_delete(base_path + ['route-map']) - # commit changes - self.cli_commit() - - # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map) - self.assertNotIn(zebra_route_map, frrconfig) - - self.cli_delete(['policy', 'route-map', route_map]) - if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From 0531ea22050d66e6da3adc87cad57ea527cea71b Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Mon, 17 Apr 2023 18:00:05 +0000 Subject: T5137: Refactoring show tech-support report Split script to small functions for flexible output reports. Improve header for commands. Each funciton easily can be modified or extended. Remove splitting command/output via percent symbol. Remove old commands and directiories like /etc/rc.local, iptables, brctl, etc. Remove ethtool operation for subinterfaces. Extend ethtool debug output. Add correct nftables command. --- src/op_mode/show_techsupport_report.py | 703 +++++++++++++-------------------- 1 file changed, 284 insertions(+), 419 deletions(-) diff --git a/src/op_mode/show_techsupport_report.py b/src/op_mode/show_techsupport_report.py index 13ed9a3c1..782004144 100644 --- a/src/op_mode/show_techsupport_report.py +++ b/src/op_mode/show_techsupport_report.py @@ -14,425 +14,290 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from vyos.util import call import os +from typing import List +from vyos.util import rc_cmd +from vyos.ifconfig import Section +from vyos.ifconfig import Interface -def header(cmd): - print(16 * '-' + '\n' + cmd + '\n' + 16 * '-') - return - - -# get intefaces info -interfaces_list = os.popen('ls /sys/class/net/ | grep eth').read().split() -bridges_list = os.popen('ls /sys/class/net/ | grep br').read().split() - -###################### THE PART OF CONFIGURATION ###################### - -cmd_list_conf = [ - "VyOS Version and Package Changes%/opt/vyatta/bin/vyatta-op-cmd-wrapper show version all", - "Configuration File%cat /opt/vyatta/etc/config/config.boot", - "Running configuration%/opt/vyatta/bin/vyatta-op-cmd-wrapper show configuration", - "Package Repository Configuration File%cat /etc/apt/sources.list", - "User Startup Scripts%cat /etc/rc.local", - "Quagga Configuration%vtysh -c 'show run'" -] - - -def CONFIGURATION(cmd): - for command_line in cmd: - line = command_line.split('%') - head = line[0] - command = line[1] - header(head) - call(command) - return - - -###################### THE PART OF INTERFACES ###################### - -cmd_list_int = [ - "Interfaces%/opt/vyatta/bin/vyatta-op-cmd-wrapper show interfaces", - "Ethernet", - "Interface statistics%ip -s link show", - "Physical Interface statistics for%ethtool -S", - "Physical Interface Details for %/opt/vyatta/bin/vyatta-op-cmd-wrapper show interfaces ethernet%ethtool -k $eth", - "ARP Table (Total entries)%/opt/vyatta/bin/vyatta-op-cmd-wrapper show arp", - "Number of incomplete entries in ARP table%show arp | grep incomplete | wc -l", - "Bridges" -] - - -def INTERFACES(cmd): - for command_line in cmd: - line = command_line.split('%') - head = line[0] - if command_line.startswith("Ethernet"): - header(command_line) - elif command_line.startswith("Physical Interface statistics"): - for command_interface in interfaces_list: - header(f'{head} {command_interface}') - call(f'{line[1]} {command_interface}') - elif command_line.startswith("Physical Interface Details"): - for command_interface in interfaces_list: - header(f'{head} {command_interface}') - call(f'{line[1]} {command_interface} physical') - call(f'{line[2]} {command_interface}') - elif command_line.startswith("Bridges"): - header(command_line) - for command_interface in bridges_list: - header(f'Information for {command_interface}') - call(f'/sbin/brctl showstp {command_interface}') - call(f'/sbin/brctl showmacs {command_interface}') - else: - command = line[1] - header(head) - call(command) - return - - -###################### THE PART OF ROUTING ###################### - -cmd_list_route = [ - "show ip route bgp", - "show ip route cache", - "show ip route connected", - "show ip route forward", - "show ip route isis", - "show ip route kernel", - "show ip route ospf", - "show ip route rip", - "show ip route static", - "show ip route summary", - "show ip route supernets-only", - "show ip route table", - "show ip route tag", - "show ip route vrf", - "show ipv6 route bgp", - "show ipv6 route cache", - "show ipv6 route connected", - "show ipv6 route forward", - "show ipv6 route isis", - "show ipv6 route kernel", - "show ipv6 route ospf", - "show ipv6 route rip", - "show ipv6 route static", - "show ipv6 route summary", - "show ipv6 route supernets-only", - "show ipv6 route table", - "show ipv6 route tag", - "show ipv6 route vrf", -] - - -def ROUTING(cmd): - for command_line in cmd: - head = command_line - command = command_line - header(head) - call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command}') - return - - -###################### THE PART OF IPTABLES ###################### - -cmd_list_iptables = [ - "Filter Chain Details%sudo /sbin/iptables -L -vn", - "Nat Chain Details%sudo /sbin/iptables -t nat -L -vn", - "Mangle Chain Details%sudo /sbin/iptables -t mangle -L -vn", - "Raw Chain Details%sudo /sbin/iptables -t raw -L -vn", - "Save Iptables Rule-Set%sudo iptables-save -c" -] - - -def IPTABLES(cmd): - for command_line in cmd: - line = command_line.split('%') - head = line[0] - command = line[1] - header(head) - call(command) - return - - -###################### THE PART OF SYSTEM ###################### - -cmd_list_system = [ - "Show System Image Version%show system image version", - "Show System Image Storage%show system image storage", - "Current Time%date", - "Installed Packages%dpkg -l", - "Loaded Modules%cat /proc/modules", - "CPU", - "Installed CPU/s%lscpu", - "Cumulative CPU Time Used by Running Processes%top -n1 -b -S", - "Hardware Interrupt Counters%cat /proc/interrupts", - "Load Average%cat /proc/loadavg" -] - - -def SYSTEM(cmd): - for command_line in cmd: - line = command_line.split('%') - head = line[0] - if command_line.startswith("CPU"): - header(command_line) - elif line[1].startswith("show"): - header(head) - command = line[1] - call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command}') - else: - header(head) - command = line[1] - call(command) - return - - -###################### THE PART OF PROCESSES ###################### - -cmd_list_processes = [ - "Running Processes%ps -ef", - "Memory", - "Installed Memory%cat /proc/meminfo", - " Memory Usage%free", - "Storage", - "Devices%cat /proc/devices", - "Partitions%cat /proc/partitions", - "Partitioning for disks%fdisk -l /dev/" -] - - -def PROCESSES(cmd): - for command_line in cmd: - line = command_line.split('%') - head = line[0] - if command_line.startswith("Memory"): - header(command_line) - elif command_line.startswith("Storage"): - header(command_line) - elif command_line.startswith("Partitioning for disks"): - header(head) - disks = set() - with open('/proc/partitions') as partitions_file: - for line in partitions_file: - fields = line.strip().split() - if len(fields) == 4 and fields[3].isalpha() and fields[3] != 'name': - disks.add(fields[3]) - for disk in disks: - call(f'fdisk -l /dev/{disk}') - else: - header(head) - command = line[1] - call(command) - return - - -###################### THE PART OF CORE SECTION ###################### - -cmd_list_core = [ - "Mounts%cat /proc/mounts", - "Diskstats%cat /proc/diskstats", - "Hard Drive Usage%df -h -x squashfs", - # "General System", - "Boot Messages%cat /var/log/dmesg", - "Recent Kernel messages (dmesg)%dmesg", - "PCI Info%sudo lspci -vvx", - "PCI Vendor and Device Codes%sudo lspci -nn", - # "System Info%${vyatta_bindir}/vyatta-show-dmi", - "GRUB Command line%cat /proc/cmdline", - "Open Ports%sudo lsof -P -n -i", - "System Startup Files%ls -l /etc/rc?.d", - "Login History%last -ix", - "Recent Log Messages%tail -n 250 /var/log/messages", - "NTP%/opt/vyatta/bin/vyatta-op-cmd-wrapper show ntp", -] - - -def CORE(cmd): - for command_line in cmd: - line = command_line.split('%') - command = line[1] - header(line[0]) - call(command) - return - - -###################### THE PART OF VyOS INFORMATION ###################### - -cmd_list_vyos = [ - "BGP", - "header BGP Summary", - "show ip bgp summary", - "header BGP Neighbors", - "show ip bgp neighbors", - "header BGP Debugging Information", - "show monitoring protocols bgp", - "CLUSTERING", - "Cluster Status", - "show cluster status", - "DHCP Server", - "DHCP Leases", - "show dhcp server leases", - "DHCP Statistics", - "show dhcp server statistics", - "DHCP Client", - "DHCP Client Leases", - "show dhcp client leases", - "DHCPV6 Server", - "DHCPV6 Server Status", - "show dhcpv6 server status", - "DHCPV6 Server Leases", - "show dhcpv6 server leases", - "DHCPV6 Relay", - "DHCPV6 Relay Status", - "show dhcpv6 relay-agent status", - "DHCPV6 Client", - "DHCPV6 Client Leases", - "show dhcpv6 client leases", - "DNS", - "DNS Dynamic Status", - "show dns dynamic status", - "DNS Forwarding Statistics", - "show dns forwarding statistics", - "DNS Forwarding Nameservers", - "show dns forwarding nameservers", - "FIREWALL", - "Firewall Group", - "show firewall group", - "Firewall Summary", - "show firewall summary", - "Firewall Statistics", - "show firewall statistics", - "IPSec", - "IPSec Status", - "show vpn ipsec status", - "IPSec sa", - "show vpn ipsec sa", - "IPSec sa Detail", - "show vpn ipsec sa detail", - "IPSec sa Statistics", - "show vpn ipsec sa statistics", - "/etc/ipsec.conf", - "cat /etc/ipsec.conf", - "/etc/ipsec.secrets", - "cat /etc/ipsec.secrets", - "NAT", - "NAT Rules", - "show nat rules", - "NAT Statistics", - "show nat statistics", - "NAT Translations Detail", - "show nat translations detail", - "FlowAccounting", - "show flow-accounting", - "OPENVPN", - "OpenVPN Interfaces", - "show interfaces openvpn detail", - "OpenVPN Server Status", - "show openvpn status server", - "OSPF", - "OSPF Neighbor", - "show ip ospf neighbor", - "OSPF Route", - "show ip ospf route", - "OSPF Debugging Information", - "show monitoring protocols ospf", - "OSPFV3", - "OSPFV3 Debugging Information", - "show monitoring protocols ospfv3", - "Policy", - "IP Route Maps", - "show ip protocol", - "Route-Map", - "show route-map", - # header IP Access Lists - # show ip access-lists - "IP Community List", - "show ip community-list", - "Traffic Policy", - "Current Traffic Policies", - "show queueing", - "RIP", - "IP RIP", - "show ip rip", - "RIP Status", - "show ip rip status", - "RIP Debugging Information", - "show monitoring protocols rip", - "RIPNG", - "RIPNG Debugging Information", - "show monitoring protocols ripng", - "VPN-L2TP", - "VPN ike secrets", - "show vpn ike secrets", - "VPN rsa-keys", - "show vpn ike rsa-keys", - "VPN ike sa", - "show vpn ike sa", - "VPN ike Status", - "show vpn ike status", - "VPN Remote-Access", - "show vpn remote-access", - "VPN Debug Detail", - "show vpn debug detail", - "VPN-PPTP", - "VPN Remote-Access", - "show vpn remote-access", - "VRRP", - # XXX: not checking if configured, we'd have to walk all VIFs - "show vrrp detail", - "WAN LOAD BALANCING", - "Wan Load Balance", - "show wan-load-balance", - "Wan Load Balance Status", - "show wan-load-balance status", - "Wan Load Balance Connection", - "show wan-load-balance connection", - "WEBPROXY/URL-FILTERING", - "WebProxy Blacklist Categories", - "show webproxy blacklist categories", - "WebProxy Blacklist Domains", - "show webproxy blacklist domains", - "WebProxy Blacklist URLs", - "show webproxy blacklist urls", - "WebProxy Blacklist Log", - "show webproxy blacklist log summary", -] - - -def VyOS(cmd): - for command_line in cmd: - if command_line.startswith("show"): - call(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {command_line}') - elif command_line.startswith("cat"): - call(command_line) - else: - header(command_line) - return - - -###################### execute all the commands ###################### - -header('CONFIGURATION') -CONFIGURATION(cmd_list_conf) - -header('INTERFACES') -INTERFACES(cmd_list_int) - -header('ROUTING') -ROUTING(cmd_list_route) - -header('IPTABLES') -IPTABLES(cmd_list_iptables) - -header('SYSTEM') -SYSTEM(cmd_list_system) - -header('PROCESSES') -PROCESSES(cmd_list_processes) - -header('CORE') -CORE(cmd_list_core) - -header('VyOS Information') -VyOS(cmd_list_vyos) + +def print_header(command: str) -> None: + """Prints a command with headers '-'. + + Example: + + % print_header('Example command') + + --------------- + Example command + --------------- + """ + header_length = len(command) * '-' + print(f"\n{header_length}\n{command}\n{header_length}") + + +def execute_command(command: str, header_text: str) -> None: + """Executes a command and prints the output with a header. + + Example: + % execute_command('uptime', "Uptime of the system") + + -------------------- + Uptime of the system + -------------------- + 20:21:57 up 9:04, 5 users, load average: 0.00, 0.00, 0.0 + + """ + print_header(header_text) + try: + rc, output = rc_cmd(command) + print(output) + except Exception as e: + print(f"Error executing command: {command}") + print(f"Error message: {e}") + + +def op(cmd: str) -> str: + """Returns a command with the VyOS operational mode wrapper.""" + return f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {cmd}' + + +def get_ethernet_interfaces() -> List[Interface]: + """Returns a list of Ethernet interfaces.""" + return Section.interfaces('ethernet') + + +def show_version() -> None: + """Prints the VyOS version and package changes.""" + execute_command(op('show version'), 'VyOS Version and Package Changes') + + +def show_config_file() -> None: + """Prints the contents of a configuration file with a header.""" + execute_command('cat /opt/vyatta/etc/config/config.boot', 'Configuration file') + + +def show_running_config() -> None: + """Prints the running configuration.""" + execute_command(op('show configuration'), 'Running configuration') + + +def show_package_repository_config() -> None: + """Prints the package repository configuration file.""" + execute_command('cat /etc/apt/sources.list', 'Package Repository Configuration File') + execute_command('ls -l /etc/apt/sources.list.d/', 'Repositories') + + +def show_user_startup_scripts() -> None: + """Prints the user startup scripts.""" + execute_command('cat /config/scripts/vyos-postconfig-bootup.script', 'User Startup Scripts') + + +def show_frr_config() -> None: + """Prints the FRR configuration.""" + execute_command('vtysh -c "show run"', 'FRR configuration') + + +def show_interfaces() -> None: + """Prints the interfaces.""" + execute_command(op('show interfaces'), 'Interfaces') + + +def show_interface_statistics() -> None: + """Prints the interface statistics.""" + execute_command('ip -s link show', 'Interface statistics') + + +def show_physical_interface_statistics() -> None: + """Prints the physical interface statistics.""" + execute_command('/usr/bin/true', 'Physical Interface statistics') + for iface in get_ethernet_interfaces(): + # Exclude vlans + if '.' in iface: + continue + execute_command(f'ethtool --driver {iface}', f'ethtool --driver {iface}') + execute_command(f'ethtool --statistics {iface}', f'ethtool --statistics {iface}') + execute_command(f'ethtool --show-ring {iface}', f'ethtool --show-ring {iface}') + execute_command(f'ethtool --show-coalesce {iface}', f'ethtool --show-coalesce {iface}') + execute_command(f'ethtool --pause {iface}', f'ethtool --pause {iface}') + execute_command(f'ethtool --show-features {iface}', f'ethtool --show-features {iface}') + execute_command(f'ethtool --phy-statistics {iface}', f'ethtool --phy-statistics {iface}') + execute_command('netstat --interfaces', 'netstat --interfaces') + execute_command('netstat --listening', 'netstat --listening') + execute_command('cat /proc/net/dev', 'cat /proc/net/dev') + + +def show_bridge() -> None: + """Show bridge interfaces.""" + execute_command(op('show bridge'), 'Show bridge') + + +def show_arp() -> None: + """Prints ARP entries.""" + execute_command(op('show arp'), 'ARP Table (Total entries)') + execute_command(op('show ipv6 neighbors'), 'show ipv6 neighbors') + + +def show_route() -> None: + """Prints routing information.""" + + cmd_list_route = [ + "show ip route bgp | head -108", + "show ip route cache", + "show ip route connected", + "show ip route forward", + "show ip route isis | head -108", + "show ip route kernel", + "show ip route ospf | head -108", + "show ip route rip", + "show ip route static", + "show ip route summary", + "show ip route supernets-only", + "show ip route table all", + "show ip route vrf all", + "show ipv6 route bgp | head 108", + "show ipv6 route cache", + "show ipv6 route connected", + "show ipv6 route forward", + "show ipv6 route isis", + "show ipv6 route kernel", + "show ipv6 route ospf", + "show ipv6 route rip", + "show ipv6 route static", + "show ipv6 route summary", + "show ipv6 route table all", + "show ipv6 route vrf all", + ] + for command in cmd_list_route: + execute_command(op(command), command) + + +def show_firewall() -> None: + """Prints firweall information.""" + execute_command('sudo nft list ruleset', 'nft list ruleset') + + +def show_system() -> None: + """Prints system parameters.""" + execute_command(op('show system image version'), 'Show System Image Version') + execute_command(op('show system image storage'), 'Show System Image Storage') + + +def show_date() -> None: + """Print the current date.""" + execute_command('date', 'Current Time') + + +def show_installed_packages() -> None: + """Prints installed packages.""" + execute_command('dpkg --list', 'Installed Packages') + + +def show_loaded_modules() -> None: + """Prints loaded modules /proc/modules""" + execute_command('cat /proc/modules', 'Loaded Modules') + + +def show_cpu_statistics() -> None: + """Prints CPU statistics.""" + execute_command('/usr/bin/true', 'CPU') + execute_command('lscpu', 'Installed CPU\'s') + execute_command('top --iterations 1 --batch-mode --accum-time-toggle', 'Cumulative CPU Time Used by Running Processes') + execute_command('cat /proc/loadavg', 'Load Average') + + +def show_system_interrupts() -> None: + """Prints system interrupts.""" + execute_command('cat /proc/interrupts', 'Hardware Interrupt Counters') + + +def show_soft_irqs() -> None: + """Prints soft IRQ's.""" + execute_command('cat /proc/softirqs', 'Soft IRQ\'s') + + +def show_softnet_statistics() -> None: + """Prints softnet statistics.""" + execute_command('cat /proc/net/softnet_stat', 'cat /proc/net/softnet_stat') + + +def show_running_processes() -> None: + """Prints current running processes""" + execute_command('ps -ef', 'Running Processes') + + +def show_memory_usage() -> None: + """Prints memory usage""" + execute_command('/usr/bin/true', 'Memory') + execute_command('cat /proc/meminfo', 'Installed Memory') + execute_command('free', 'Memory Usage') + + +def list_disks(): + disks = set() + with open('/proc/partitions') as partitions_file: + for line in partitions_file: + fields = line.strip().split() + if len(fields) == 4 and fields[3].isalpha() and fields[3] != 'name': + disks.add(fields[3]) + return disks + + +def show_storage() -> None: + """Prints storage information.""" + execute_command('cat /proc/devices', 'Devices') + execute_command('cat /proc/partitions', 'Partitions') + + for disk in list_disks(): + execute_command(f'fdisk --list /dev/{disk}', f'Partitioning for disk {disk}') + + +def main(): + # Configuration data + show_version() + show_config_file() + show_running_config() + show_package_repository_config() + show_user_startup_scripts() + show_frr_config() + + # Interfaces + show_interfaces() + show_interface_statistics() + show_physical_interface_statistics() + show_bridge() + show_arp() + + # Routing + show_route() + + # Firewall + show_firewall() + + # System + show_system() + show_date() + show_installed_packages() + show_loaded_modules() + + # CPU + show_cpu_statistics() + show_system_interrupts() + show_soft_irqs() + show_softnet_statistics() + + # Memory + show_memory_usage() + + # Storage + show_storage() + + # Processes + show_running_processes() + + # TODO: Get information from clouds + + +if __name__ == "__main__": + main() -- cgit v1.2.3 From bfe57cf80f4c71236f0885408d704a69575f0b30 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 17 Apr 2023 20:59:38 +0200 Subject: bgp: T3734: only support "l2vpn-evpn advertise-all-vni" in default VRF --- .../include/bgp/protocol-common-config.xml.i | 6 ------ interface-definitions/protocols-bgp.xml.in | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index 527eaf991..bcc131f83 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -810,12 +810,6 @@ - - - Advertise All local VNIs - - - #include diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index e1a822999..78b461f9d 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -9,6 +9,20 @@ #include + + + + + + + Advertise all local VNIs + + + + + + + -- cgit v1.2.3 From a6499ea9d95d2b66d7977cea1d43f96d0116d4c3 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 17 Apr 2023 22:36:04 +0200 Subject: op-mode: bgp: T1315: add VNI related commands This extends commit 3fa1092930c (op-mode: bgp: support VRF related "show bgp vrf" commands). vyos@vyos:~$ show bgp vni Possible completions: 1-16777215 VXLAN network identifier (VNI) number all vyos@vyos:~$ show bgp vni 1 type Possible completions: 1 EAD (Type-1) route 2 MAC-IP (Type-2) route 3 Multicast (Type-3) route ead EAD (Type-1) route macip MAC-IP (Type-2) route multicast Multicast (Type-3) route vyos@vyos:~$ show bgp vni 1 vtep Possible completions: Remote VTEP IP address --- op-mode-definitions/include/bgp/evpn-type-1.xml.i | 8 +++ op-mode-definitions/include/bgp/evpn-type-2.xml.i | 8 +++ op-mode-definitions/include/bgp/evpn-type-3.xml.i | 8 +++ op-mode-definitions/include/bgp/evpn-type-4.xml.i | 8 +++ op-mode-definitions/include/bgp/evpn-type-5.xml.i | 8 +++ .../include/bgp/evpn-type-ead.xml.i | 8 +++ op-mode-definitions/include/bgp/evpn-type-es.xml.i | 8 +++ .../include/bgp/evpn-type-macip.xml.i | 8 +++ .../include/bgp/evpn-type-multicast.xml.i | 8 +++ .../include/bgp/evpn-type-prefix.xml.i | 8 +++ .../include/bgp/show-bgp-common.xml.i | 70 ++++------------------ op-mode-definitions/show-bgp.xml.in | 27 +++++++++ 12 files changed, 117 insertions(+), 60 deletions(-) create mode 100644 op-mode-definitions/include/bgp/evpn-type-1.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-2.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-3.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-4.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-5.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-ead.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-es.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-macip.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-multicast.xml.i create mode 100644 op-mode-definitions/include/bgp/evpn-type-prefix.xml.i diff --git a/op-mode-definitions/include/bgp/evpn-type-1.xml.i b/op-mode-definitions/include/bgp/evpn-type-1.xml.i new file mode 100644 index 000000000..b5097c8b1 --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-1.xml.i @@ -0,0 +1,8 @@ + + + + EAD (Type-1) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-2.xml.i b/op-mode-definitions/include/bgp/evpn-type-2.xml.i new file mode 100644 index 000000000..827298d62 --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-2.xml.i @@ -0,0 +1,8 @@ + + + + MAC-IP (Type-2) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-3.xml.i b/op-mode-definitions/include/bgp/evpn-type-3.xml.i new file mode 100644 index 000000000..ae90b2e5c --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-3.xml.i @@ -0,0 +1,8 @@ + + + + Multicast (Type-3) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-4.xml.i b/op-mode-definitions/include/bgp/evpn-type-4.xml.i new file mode 100644 index 000000000..7248b4753 --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-4.xml.i @@ -0,0 +1,8 @@ + + + + Ethernet Segment (Type-4) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-5.xml.i b/op-mode-definitions/include/bgp/evpn-type-5.xml.i new file mode 100644 index 000000000..e3a72168a --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-5.xml.i @@ -0,0 +1,8 @@ + + + + Prefix (Type-5) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-ead.xml.i b/op-mode-definitions/include/bgp/evpn-type-ead.xml.i new file mode 100644 index 000000000..452de2f9a --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-ead.xml.i @@ -0,0 +1,8 @@ + + + + EAD (Type-1) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-es.xml.i b/op-mode-definitions/include/bgp/evpn-type-es.xml.i new file mode 100644 index 000000000..50c40151a --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-es.xml.i @@ -0,0 +1,8 @@ + + + + Ethernet Segment (Type-4) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-macip.xml.i b/op-mode-definitions/include/bgp/evpn-type-macip.xml.i new file mode 100644 index 000000000..6f601eb3f --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-macip.xml.i @@ -0,0 +1,8 @@ + + + + MAC-IP (Type-2) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-multicast.xml.i b/op-mode-definitions/include/bgp/evpn-type-multicast.xml.i new file mode 100644 index 000000000..5194dbb56 --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-multicast.xml.i @@ -0,0 +1,8 @@ + + + + Multicast (Type-3) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/evpn-type-prefix.xml.i b/op-mode-definitions/include/bgp/evpn-type-prefix.xml.i new file mode 100644 index 000000000..d5054d86b --- /dev/null +++ b/op-mode-definitions/include/bgp/evpn-type-prefix.xml.i @@ -0,0 +1,8 @@ + + + + Prefix (Type-5) route + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/show-bgp-common.xml.i b/op-mode-definitions/include/bgp/show-bgp-common.xml.i index c9a112fca..de794a879 100644 --- a/op-mode-definitions/include/bgp/show-bgp-common.xml.i +++ b/op-mode-definitions/include/bgp/show-bgp-common.xml.i @@ -171,66 +171,16 @@ Specify Route type - - - EAD (Type-1) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - MAC-IP (Type-2) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Multicast (Type-3) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Ethernet Segment (Type-4) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Prefix (Type-5) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - EAD (Type-1) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Ethernet Segment (Type-4) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - MAC-IP (Type-2) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Multicast (Type-3) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - - - - Prefix (Type-5) route - - ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ - + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include #include diff --git a/op-mode-definitions/show-bgp.xml.in b/op-mode-definitions/show-bgp.xml.in index 974147621..3c212614c 100644 --- a/op-mode-definitions/show-bgp.xml.in +++ b/op-mode-definitions/show-bgp.xml.in @@ -51,6 +51,33 @@ ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + #include + + + + + Remote VTEP IP address + + <x.x.x.x> + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display number of prefixes for all afi/safi + + + #include + #include + #include + #include + #include + #include + + + + Show BGP VRF information -- cgit v1.2.3 From 77858da1e5640aef1a542e6d6aa07715858ef750 Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:40:42 +0200 Subject: pki: T3642: Fix show command if no CA certs are present --- src/op_mode/pki.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py index 1e78c3a03..b054690b0 100755 --- a/src/op_mode/pki.py +++ b/src/op_mode/pki.py @@ -87,6 +87,9 @@ def get_config_certificate(name=None): def get_certificate_ca(cert, ca_certs): # Find CA certificate for given certificate + if not ca_certs: + return None + for ca_name, ca_dict in ca_certs.items(): if 'certificate' not in ca_dict: continue -- cgit v1.2.3 From e9fe5a877aa4d34cfde6e577e34146c9c025ccfa Mon Sep 17 00:00:00 2001 From: srividya0208 Date: Fri, 14 Apr 2023 07:11:11 -0400 Subject: op-mode: T5159: dhcpv6 incorrect warning message The operational command "show dhcpv6 server leases" shows a warning message e ven if dhcpv6 setting are configured and ipv6 address got assigned to clients. --- src/op_mode/dhcp.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py index 41da14065..fe7f252ba 100755 --- a/src/op_mode/dhcp.py +++ b/src/op_mode/dhcp.py @@ -264,8 +264,10 @@ def show_pool_statistics(raw: bool, family: ArgFamily, pool: typing.Optional[str def show_server_leases(raw: bool, family: ArgFamily, pool: typing.Optional[str], sorted: typing.Optional[str], state: typing.Optional[ArgState]): # if dhcp server is down, inactive leases may still be shown as active, so warn the user. - if not is_systemd_service_running('isc-dhcp-server.service'): - Warning('DHCP server is configured but not started. Data may be stale.') + v = '6' if family == 'inet6' else '' + service_name = 'DHCPv6' if family == 'inet6' else 'DHCP' + if not is_systemd_service_running(f'isc-dhcp-server{v}.service'): + Warning(f'{service_name} server is configured but not started. Data may be stale.') v = 'v6' if family == 'inet6' else '' if pool and pool not in _get_dhcp_pools(family=family): -- cgit v1.2.3