From c48116a95ba66c398033be4ccdc52793ed920675 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 27 Jul 2021 21:40:02 +0200 Subject: Revert "ifconfig: drop unused classes for pppoe and vti" This reverts commit e4d697b1d3aad0cb8e81f4c36bcaa4c089195f43. We need those classes for the operational level "show interfaces" command. --- python/vyos/ifconfig/__init__.py | 2 ++ python/vyos/ifconfig/pppoe.py | 39 +++++++++++++++++++++++++++++++++++++++ python/vyos/ifconfig/vti.py | 27 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 python/vyos/ifconfig/pppoe.py create mode 100644 python/vyos/ifconfig/vti.py diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index cbde93c97..d4d8c02a9 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -30,6 +30,8 @@ from vyos.ifconfig.vxlan import VXLANIf from vyos.ifconfig.wireguard import WireGuardIf from vyos.ifconfig.vtun import VTunIf from vyos.ifconfig.tunnel import TunnelIf +from vyos.ifconfig.vti import VTIIf +from vyos.ifconfig.pppoe import PPPoEIf from vyos.ifconfig.wireless import WiFiIf from vyos.ifconfig.l2tpv3 import L2TPv3If from vyos.ifconfig.macsec import MACsecIf diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py new file mode 100644 index 000000000..6f14c0fd4 --- /dev/null +++ b/python/vyos/ifconfig/pppoe.py @@ -0,0 +1,39 @@ +# Copyright 2020 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 . + + +from vyos.ifconfig.interface import Interface + + +@Interface.register +class PPPoEIf(Interface): + iftype = 'pppoe' + definition = { + **Interface.definition, + **{ + 'section': 'pppoe', + 'prefixes': ['pppoe', ], + }, + } + + # stub this interface is created in the configure script + + def _create(self): + # we can not create this interface as it is managed outside + pass + + def _delete(self): + # we can not create this interface as it is managed outside + pass diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py new file mode 100644 index 000000000..f575323af --- /dev/null +++ b/python/vyos/ifconfig/vti.py @@ -0,0 +1,27 @@ +# Copyright 2020 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 . + +from vyos.ifconfig.interface import Interface + +@Interface.register +class VTIIf(Interface): + iftype = 'vti' + definition = { + **Interface.definition, + **{ + 'section': 'vti', + 'prefixes': ['vti', ], + }, + } -- cgit v1.2.3 From 225be098db7095e779f3fa2f6cf53ca08c8faf9b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 30 Jul 2021 22:01:54 +0200 Subject: router-advert: T2745: use template common coding style in for loops (cherry picked from commit f89a0cfc7d0d908cbe1715b760b07926ffa3f7b9) --- data/templates/router-advert/radvd.conf.tmpl | 80 ++++++++++++---------- .../scripts/cli/test_service_router-advert.py | 26 ++++++- 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/data/templates/router-advert/radvd.conf.tmpl b/data/templates/router-advert/radvd.conf.tmpl index 9cc237512..88d066491 100644 --- a/data/templates/router-advert/radvd.conf.tmpl +++ b/data/templates/router-advert/radvd.conf.tmpl @@ -1,58 +1,64 @@ ### Autogenerated by service_router-advert.py ### {% if interface is defined and interface is not none %} -{% for iface in interface %} +{% for iface, iface_config in interface.items() %} interface {{ iface }} { IgnoreIfMissing on; -{% if interface[iface].default_preference is defined and interface[iface].default_preference is not none %} - AdvDefaultPreference {{ interface[iface].default_preference }}; +{% if iface_config.default_preference is defined and iface_config.default_preference is not none %} + AdvDefaultPreference {{ iface_config.default_preference }}; {% endif %} -{% if interface[iface].managed_flag is defined and interface[iface].managed_flag is not none %} - AdvManagedFlag {{ 'on' if interface[iface].managed_flag is defined else 'off' }}; +{% if iface_config.managed_flag is defined and iface_config.managed_flag is not none %} + AdvManagedFlag {{ 'on' if iface_config.managed_flag is defined else 'off' }}; {% endif %} -{% if interface[iface].interval.max is defined and interface[iface].interval.max is not none %} - MaxRtrAdvInterval {{ interface[iface].interval.max }}; +{% if iface_config.interval.max is defined and iface_config.interval.max is not none %} + MaxRtrAdvInterval {{ iface_config.interval.max }}; {% endif %} -{% if interface[iface].interval.min is defined and interface[iface].interval.min is not none %} - MinRtrAdvInterval {{ interface[iface].interval.min }}; +{% if iface_config.interval.min is defined and iface_config.interval.min is not none %} + MinRtrAdvInterval {{ iface_config.interval.min }}; {% endif %} -{% if interface[iface].reachable_time is defined and interface[iface].reachable_time is not none %} - AdvReachableTime {{ interface[iface].reachable_time }}; +{% if iface_config.reachable_time is defined and iface_config.reachable_time is not none %} + AdvReachableTime {{ iface_config.reachable_time }}; {% endif %} - AdvIntervalOpt {{ 'off' if interface[iface].no_send_advert is defined else 'on' }}; - AdvSendAdvert {{ 'off' if interface[iface].no_send_advert is defined else 'on' }}; -{% if interface[iface].default_lifetime is defined %} - AdvDefaultLifetime {{ interface[iface].default_lifetime }}; -{% endif %} -{% if interface[iface].link_mtu is defined %} - AdvLinkMTU {{ interface[iface].link_mtu }}; -{% endif %} - AdvOtherConfigFlag {{ 'on' if interface[iface].other_config_flag is defined else 'off' }}; - AdvRetransTimer {{ interface[iface].retrans_timer }}; - AdvCurHopLimit {{ interface[iface].hop_limit }}; -{% if interface[iface].route is defined %} -{% for route in interface[iface].route %} + AdvIntervalOpt {{ 'off' if iface_config.no_send_advert is defined else 'on' }}; + AdvSendAdvert {{ 'off' if iface_config.no_send_advert is defined else 'on' }}; +{% if iface_config.default_lifetime is defined %} + AdvDefaultLifetime {{ iface_config.default_lifetime }}; +{% endif %} +{% if iface_config.link_mtu is defined %} + AdvLinkMTU {{ iface_config.link_mtu }}; +{% endif %} + AdvOtherConfigFlag {{ 'on' if iface_config.other_config_flag is defined else 'off' }}; + AdvRetransTimer {{ iface_config.retrans_timer }}; + AdvCurHopLimit {{ iface_config.hop_limit }}; +{% if iface_config.route is defined %} +{% for route, route_options in iface_config.route.items() %} route {{ route }} { -{% if interface[iface].route[route].valid_lifetime is defined %} - AdvRouteLifetime {{ interface[iface].route[route].valid_lifetime }}; +{% if route_options.valid_lifetime is defined %} + AdvRouteLifetime {{ route_options.valid_lifetime }}; {% endif %} -{% if interface[iface].route[route].route_preference is defined %} - AdvRoutePreference {{ interface[iface].route[route].route_preference }}; +{% if route_options.route_preference is defined %} + AdvRoutePreference {{ route_options.route_preference }}; {% endif %} - RemoveRoute {{ 'off' if interface[iface].route[route].no_remove_route is defined else 'on' }}; + RemoveRoute {{ 'off' if route_options.no_remove_route is defined else 'on' }}; }; {% endfor %} {% endif %} -{% for prefix in interface[iface].prefix %} +{% if iface_config.prefix is defined and iface_config.prefix is not none %} +{% for prefix, prefix_options in iface_config.prefix.items() %} prefix {{ prefix }} { - AdvAutonomous {{ 'off' if interface[iface].prefix[prefix].no_autonomous_flag is defined else 'on' }}; - AdvValidLifetime {{ interface[iface].prefix[prefix].valid_lifetime }}; - AdvOnLink {{ 'off' if interface[iface].prefix[prefix].no_on_link_flag is defined else 'on' }}; - AdvPreferredLifetime {{ interface[iface].prefix[prefix].preferred_lifetime }}; + AdvAutonomous {{ 'off' if prefix_options.no_autonomous_flag is defined else 'on' }}; + AdvValidLifetime {{ prefix_options.valid_lifetime }}; + AdvOnLink {{ 'off' if prefix_options.no_on_link_flag is defined else 'on' }}; + AdvPreferredLifetime {{ prefix_options.preferred_lifetime }}; + }; +{% endfor %} +{% endif %} +{% if iface_config.name_server is defined %} + RDNSS {{ iface_config.name_server | join(" ") }} { }; -{% endfor %} -{% if interface[iface].name_server is defined %} - RDNSS {{ interface[iface].name_server | join(" ") }} { +{% endif %} +{% if iface_config.dnssl is defined %} + DNSSL {{ iface_config.dnssl | join(" ") }} { }; {% endif %} }; diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py index b19c49c6e..26b4626c2 100755 --- a/smoketest/scripts/cli/test_service_router-advert.py +++ b/smoketest/scripts/cli/test_service_router-advert.py @@ -43,11 +43,10 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path) self.cli_commit() - def test_single(self): + def test_common(self): self.cli_set(base_path + ['prefix', '::/64', 'no-on-link-flag']) self.cli_set(base_path + ['prefix', '::/64', 'no-autonomous-flag']) self.cli_set(base_path + ['prefix', '::/64', 'valid-lifetime', 'infinity']) - self.cli_set(base_path + ['dnssl', '2001:db8::1234']) self.cli_set(base_path + ['other-config-flag']) # commit changes @@ -92,5 +91,28 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertTrue(process_named_running('radvd')) + def test_dns(self): + nameserver = ['2001:db8::1', '2001:db8::2'] + dnssl = ['vyos.net', 'vyos.io'] + + self.cli_set(base_path + ['prefix', '::/64', 'valid-lifetime', 'infinity']) + self.cli_set(base_path + ['other-config-flag']) + + for ns in nameserver: + self.cli_set(base_path + ['name-server', ns]) + for sl in dnssl: + self.cli_set(base_path + ['dnssl', sl]) + + # commit changes + self.cli_commit() + + config = read_file(RADVD_CONF) + + tmp = 'RDNSS ' + ' '.join(nameserver) + ' {' + self.assertIn(tmp, config) + + tmp = 'DNSSL ' + ' '.join(dnssl) + ' {' + self.assertIn(tmp, config) + if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From d3a0b9bcb30e36633bad0edf39c1f92039bebcb7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 1 Aug 2021 10:41:02 +0200 Subject: ping: T3707: add UnicodeError exception when invalid IP address is passed (cherry picked from commit 0d1ad777daf25ef415bf45032d41b587baf20781) --- src/op_mode/ping.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py index 924a889db..610f6a05d 100755 --- a/src/op_mode/ping.py +++ b/src/op_mode/ping.py @@ -220,6 +220,8 @@ if __name__ == '__main__': try: ip = socket.gethostbyname(host) + except UnicodeError: + sys.exit(f'ping: Unknown host: {host}') except socket.gaierror: ip = host -- cgit v1.2.3 From f83a5125735bb2f63e4d98e1b264eb689a2ef00f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 1 Aug 2021 13:20:35 +0200 Subject: op-mode: bgp: T1513: backport "show bgp" commands from current branch --- op-mode-definitions/include/bgp/afi-common.xml.i | 55 +++++ .../include/bgp/afi-ipv4-ipv6-common.xml.i | 243 +++++++++++++++++++++ .../include/bgp/prefix-bestpath-multipath.xml.i | 20 ++ .../include/bgp/show-bgp-common.xml.i | 46 ++++ .../include/vtysh-generic-detail.xml.i | 8 + .../include/vtysh-generic-wide.xml.i | 8 + op-mode-definitions/show-bgp.xml.in | 91 ++++++++ 7 files changed, 471 insertions(+) create mode 100644 op-mode-definitions/include/bgp/afi-common.xml.i create mode 100644 op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i create mode 100644 op-mode-definitions/include/bgp/prefix-bestpath-multipath.xml.i create mode 100644 op-mode-definitions/include/bgp/show-bgp-common.xml.i create mode 100644 op-mode-definitions/include/vtysh-generic-detail.xml.i create mode 100644 op-mode-definitions/include/vtysh-generic-wide.xml.i create mode 100644 op-mode-definitions/show-bgp.xml.in diff --git a/op-mode-definitions/include/bgp/afi-common.xml.i b/op-mode-definitions/include/bgp/afi-common.xml.i new file mode 100644 index 000000000..7fc59f3b0 --- /dev/null +++ b/op-mode-definitions/include/bgp/afi-common.xml.i @@ -0,0 +1,55 @@ + + + + Community number where AA and NN are (0-65535) + + AA:NN + + + + + + Exact match of the communities + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + List of large-community numbers + + AA:BB:CC + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + RIB advertisement statistics + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Summary of BGP neighbor status + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show only sessions in Established state + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show only sessions not in Established state + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + +#include + 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 new file mode 100644 index 000000000..f1b699347 --- /dev/null +++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i @@ -0,0 +1,243 @@ + + + + Display routes matching the community + + + + + Should accept local VPN route if exported and imported into different VRF (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Should accept VPN route with local nexthop (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Inform EBGP peers to blackhole traffic to prefix (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Exact match of the communities + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Graceful shutdown (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Staled Long-lived Graceful Restart VPN route (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Do not send outside local AS (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Do not advertise to any peer (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Do not export to next AS (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Do not export to any peer (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + RT translated VPNv4 route filtering (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + RT translated VPNv6 route filtering (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + RT VPNv4 route filtering (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + RT VPNv6 route filtering (well-known community) + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display routes matching the community-list + + 1-500 name + + + + + + Show BGP routes exactly matching specified community list + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display detailed information about dampening + + + + + Display paths suppressed due to dampening + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display flap statistics of routes + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display detail of configured dampening parameters + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + + Display routes conforming to the filter-list + + + + + + + + Show BGP routes matching the specified large-communities + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Detailed information on TCP and BGP neighbor connections + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show detailed BGP IPv4 unicast neighbor information + + + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show routes advertised to a BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show dampened routes received from BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show flap statistics of the routes learned from BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show detailed prefix count information for BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show information received from BGP neighbor + + + + + Show prefixlist filter + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + + Show received routes from BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show routes learned from BGP neighbor + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + + Display routes conforming to the prefix-list + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display routes matching the AS path regular expression + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show BGP routes matching the specified route map + + policy route-map + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/bgp/prefix-bestpath-multipath.xml.i b/op-mode-definitions/include/bgp/prefix-bestpath-multipath.xml.i new file mode 100644 index 000000000..2d91a8253 --- /dev/null +++ b/op-mode-definitions/include/bgp/prefix-bestpath-multipath.xml.i @@ -0,0 +1,20 @@ + + + + Display only the bestpath + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display only multipaths + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display route and more specific routes + + ${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 new file mode 100644 index 000000000..785b85963 --- /dev/null +++ b/op-mode-definitions/include/bgp/show-bgp-common.xml.i @@ -0,0 +1,46 @@ + +#include +#include + + + Network in the BGP routing table to display + + <x.x.x.x> <x.x.x.x/x> <h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x> + + + + #include + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + IPv4 Address Family + + + #include + #include + + + + + Network in the BGP routing table to display + + <x.x.x.x> <x.x.x.x/x> <h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x> + + + + #include + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + IPv6 Address Family + + + #include + #include + + + diff --git a/op-mode-definitions/include/vtysh-generic-detail.xml.i b/op-mode-definitions/include/vtysh-generic-detail.xml.i new file mode 100644 index 000000000..d469f70c7 --- /dev/null +++ b/op-mode-definitions/include/vtysh-generic-detail.xml.i @@ -0,0 +1,8 @@ + + + + Detailed information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/include/vtysh-generic-wide.xml.i b/op-mode-definitions/include/vtysh-generic-wide.xml.i new file mode 100644 index 000000000..acc68b4c0 --- /dev/null +++ b/op-mode-definitions/include/vtysh-generic-wide.xml.i @@ -0,0 +1,8 @@ + + + + Increase table width for longer prefixes + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + diff --git a/op-mode-definitions/show-bgp.xml.in b/op-mode-definitions/show-bgp.xml.in new file mode 100644 index 000000000..07369ddcb --- /dev/null +++ b/op-mode-definitions/show-bgp.xml.in @@ -0,0 +1,91 @@ + + + + + + + BGP information + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display only routes with non-natural netmasks + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + #include + + + #include + + + MAC address + + + + + MAC address database + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + + martian next-hops + + + + + martian next-hop database + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + + + Global BGP memory statistics + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Show BGP nexthop table + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + #include + + + + + IPv4/IPv6 nexthop address + + <x.x.x.x> <h:h:h:h:h:h:h:h> + + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + #include + + + + + BGP RIB advertisement statistics + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + + + Display number of prefixes for all afi/safi + + ${vyos_op_scripts_dir}/vtysh_wrapper.sh $@ + + #include + + + + + -- cgit v1.2.3