From 4ecfd5d87c33aea770878a012f3b4956deafd762 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Tue, 8 Feb 2022 10:58:20 +0000 Subject: openvpn: T4230: Delete checks if local-host address assigned OpenVPN can't start if it depends on VRRP virtual-address as virtual-address is not yet assigned by HA (openvpn and ha in one commit) as we have checks "if address assigned" It depends on commit priorities: 460 interfaces/openvpn 800 high-availability Replace check if local-host address assigned from raise ConfigError to print (just notification) Allow to bind OpenVPN service to nonlocal address --- src/conf_mode/interfaces-openvpn.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 3b8fae710..0f6114b4a 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -47,6 +47,7 @@ from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.util import call from vyos.util import chown +from vyos.util import cmd from vyos.util import dict_search from vyos.util import dict_search_args from vyos.util import makedir @@ -423,8 +424,8 @@ def verify(openvpn): # verify specified IP address is present on any interface on this system if 'local_host' in openvpn: if not is_addr_assigned(openvpn['local_host']): - raise ConfigError('local-host IP address "{local_host}" not assigned' \ - ' to any interface'.format(**openvpn)) + print('local-host IP address "{local_host}" not assigned' \ + ' to any interface'.format(**openvpn)) # TCP active if openvpn['protocol'] == 'tcp-active': @@ -647,6 +648,13 @@ def apply(openvpn): return None + # verify specified IP address is present on any interface on this system + # Allow to bind service to nonlocal address, if it virtaual-vrrp address + # or if address will be assign later + if 'local_host' in openvpn: + if not is_addr_assigned(openvpn['local_host']): + cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1') + # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process call(f'systemctl reload-or-restart openvpn@{interface}.service') -- cgit v1.2.3 From 230ac0a202acd7ae9ad9bccb9e777ee5a0e0b7b7 Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Wed, 9 Feb 2022 16:07:55 +0000 Subject: openvpn: T3686: Fix for check local-address in script and tmpl Local-address should be checked/executed only if it exists in the openvpn configuration, dictionary, jinja2 template --- data/templates/openvpn/server.conf.tmpl | 10 ++++++---- src/conf_mode/interfaces-openvpn.py | 13 +++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl index 7a0470d0e..fb7ad9e16 100644 --- a/data/templates/openvpn/server.conf.tmpl +++ b/data/templates/openvpn/server.conf.tmpl @@ -141,11 +141,13 @@ ping {{ keep_alive.interval }} ping-restart {{ keep_alive.failure_count }} {% if device_type == 'tap' %} -{% for laddr, laddr_conf in local_address.items() if laddr | is_ipv4 %} -{% if laddr_conf is defined and laddr_conf.subnet_mask is defined and laddr_conf.subnet_mask is not none %} +{% if local_address is defined and local_address is not none %} +{% for laddr, laddr_conf in local_address.items() if laddr | is_ipv4 %} +{% if laddr_conf is defined and laddr_conf.subnet_mask is defined and laddr_conf.subnet_mask is not none %} ifconfig {{ laddr }} {{ laddr_conf.subnet_mask }} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} +{% endif %} {% else %} {% for laddr in local_address if laddr | is_ipv4 %} {% for raddr in remote_address if raddr | is_ipv4 %} diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 3b8fae710..242fae9fb 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-2021 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -225,11 +225,12 @@ def verify(openvpn): if 'local_address' not in openvpn and 'is_bridge_member' not in openvpn: raise ConfigError('Must specify "local-address" or add interface to bridge') - if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1: - raise ConfigError('Only one IPv4 local-address can be specified') + if 'local_address' in openvpn: + if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1: + raise ConfigError('Only one IPv4 local-address can be specified') - if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1: - raise ConfigError('Only one IPv6 local-address can be specified') + if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1: + raise ConfigError('Only one IPv6 local-address can be specified') if openvpn['device_type'] == 'tun': if 'remote_address' not in openvpn: @@ -268,7 +269,7 @@ def verify(openvpn): if dict_search('remote_host', openvpn) in dict_search('remote_address', openvpn): raise ConfigError('"remote-address" and "remote-host" can not be the same') - if openvpn['device_type'] == 'tap': + if openvpn['device_type'] == 'tap' and 'local_address' in openvpn: # we can only have one local_address, this is ensured above v4addr = None for laddr in openvpn['local_address']: -- cgit v1.2.3 From 1cbcbf40b7721849f9696c05fac65db010a66b7c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 17 Feb 2022 20:58:02 +0100 Subject: openvpn: T4230: globally enable ip_nonlocal_bind --- src/conf_mode/interfaces-openvpn.py | 7 ------- src/etc/sysctl.d/33-vyos-nonlocal-bind.conf | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 src/etc/sysctl.d/33-vyos-nonlocal-bind.conf (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 329399274..29a25eedc 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -649,13 +649,6 @@ def apply(openvpn): return None - # verify specified IP address is present on any interface on this system - # Allow to bind service to nonlocal address, if it virtaual-vrrp address - # or if address will be assign later - if 'local_host' in openvpn: - if not is_addr_assigned(openvpn['local_host']): - cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1') - # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process call(f'systemctl reload-or-restart openvpn@{interface}.service') diff --git a/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf b/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf new file mode 100644 index 000000000..aa81b5336 --- /dev/null +++ b/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf @@ -0,0 +1,8 @@ +### Added by vyos-1x ### +# +# ip_nonlocal_bind - BOOLEAN +# If set, allows processes to bind() to non-local IP addresses, +# which can be quite useful - but may break some applications. +# Default: 0 +net.ipv4.ip_nonlocal_bind = 1 +net.ipv6.ip_nonlocal_bind = 1 -- cgit v1.2.3 From 999b1e50dfdea8694174e82d22b2438cb1bf5e28 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 24 Mar 2022 17:42:59 +0100 Subject: openvpn: T4294: force service restart on openvpn-option node change --- src/conf_mode/interfaces-openvpn.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 29a25eedc..c30c0bdd0 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -32,6 +32,7 @@ from shutil import rmtree from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import leaf_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_bridge_delete from vyos.ifconfig import VTunIf @@ -88,6 +89,9 @@ def get_config(config=None): if 'deleted' not in openvpn: openvpn['pki'] = tmp_pki + tmp = leaf_node_changed(conf, ['openvpn-option']) + if tmp: openvpn['restart_required'] = '' + # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True) @@ -651,7 +655,10 @@ def apply(openvpn): # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process - call(f'systemctl reload-or-restart openvpn@{interface}.service') + action = 'reload-or-restart' + if 'restart_required' in openvpn: + action = 'restart' + call(f'systemctl {action} openvpn@{interface}.service') o = VTunIf(**openvpn) o.update(openvpn) -- cgit v1.2.3 From 60f093464692f08c1c32c9e31513a6ae98636617 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Mon, 28 Mar 2022 10:46:30 +0300 Subject: Revert "openvpn: T4230: globally enable ip_nonlocal_bind" This reverts commit 1cbcbf40b7721849f9696c05fac65db010a66b7c. --- src/conf_mode/interfaces-openvpn.py | 7 +++++++ src/etc/sysctl.d/33-vyos-nonlocal-bind.conf | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 src/etc/sysctl.d/33-vyos-nonlocal-bind.conf (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index c30c0bdd0..8f9c0b3f1 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -653,6 +653,13 @@ def apply(openvpn): return None + # verify specified IP address is present on any interface on this system + # Allow to bind service to nonlocal address, if it virtaual-vrrp address + # or if address will be assign later + if 'local_host' in openvpn: + if not is_addr_assigned(openvpn['local_host']): + cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1') + # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process action = 'reload-or-restart' diff --git a/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf b/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf deleted file mode 100644 index aa81b5336..000000000 --- a/src/etc/sysctl.d/33-vyos-nonlocal-bind.conf +++ /dev/null @@ -1,8 +0,0 @@ -### Added by vyos-1x ### -# -# ip_nonlocal_bind - BOOLEAN -# If set, allows processes to bind() to non-local IP addresses, -# which can be quite useful - but may break some applications. -# Default: 0 -net.ipv4.ip_nonlocal_bind = 1 -net.ipv6.ip_nonlocal_bind = 1 -- cgit v1.2.3 From 37c6d9fae5172b0342f94212e6483b3aa8fcd673 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 23 Mar 2022 10:07:41 +0100 Subject: qos: T4284: support mirror and redirect on all interface types --- interface-definitions/interfaces-dummy.xml.in | 1 + interface-definitions/interfaces-geneve.xml.in | 1 + interface-definitions/interfaces-l2tpv3.xml.in | 1 + interface-definitions/interfaces-loopback.xml.in | 1 + interface-definitions/interfaces-macsec.xml.in | 1 + interface-definitions/interfaces-openvpn.xml.in | 1 + interface-definitions/interfaces-pppoe.xml.in | 1 + .../interfaces-pseudo-ethernet.xml.in | 1 + interface-definitions/interfaces-tunnel.xml.in | 1 + interface-definitions/interfaces-vti.xml.in | 1 + interface-definitions/interfaces-vxlan.xml.in | 1 + interface-definitions/interfaces-wireguard.xml.in | 1 + interface-definitions/interfaces-wireless.xml.in | 1 + interface-definitions/interfaces-wwan.xml.in | 1 + python/vyos/configverify.py | 27 +++---- python/vyos/ifconfig/interface.py | 84 ++++++++++++---------- src/conf_mode/interfaces-bonding.py | 6 +- src/conf_mode/interfaces-bridge.py | 6 +- src/conf_mode/interfaces-dummy.py | 4 +- src/conf_mode/interfaces-ethernet.py | 6 +- src/conf_mode/interfaces-geneve.py | 4 +- src/conf_mode/interfaces-l2tpv3.py | 4 +- src/conf_mode/interfaces-loopback.py | 4 +- src/conf_mode/interfaces-macsec.py | 4 +- src/conf_mode/interfaces-openvpn.py | 2 + src/conf_mode/interfaces-pppoe.py | 4 +- src/conf_mode/interfaces-pseudo-ethernet.py | 4 +- src/conf_mode/interfaces-tunnel.py | 4 +- src/conf_mode/interfaces-vti.py | 4 +- src/conf_mode/interfaces-vxlan.py | 4 +- src/conf_mode/interfaces-wireguard.py | 4 +- src/conf_mode/interfaces-wireless.py | 4 +- src/conf_mode/interfaces-wwan.py | 4 +- 33 files changed, 107 insertions(+), 90 deletions(-) (limited to 'src/conf_mode/interfaces-openvpn.py') diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in index 109ed1b50..988d87502 100644 --- a/interface-definitions/interfaces-dummy.xml.in +++ b/interface-definitions/interfaces-dummy.xml.in @@ -29,6 +29,7 @@ #include + #include #include #include #include diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index aa5809e60..5f2c6bc05 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -50,6 +50,7 @@ + #include #include #include #include diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in index 680170b0f..0dcabf7a0 100644 --- a/interface-definitions/interfaces-l2tpv3.xml.in +++ b/interface-definitions/interfaces-l2tpv3.xml.in @@ -58,6 +58,7 @@ #include #include #include + #include #include 1488 diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in index ffffc0220..1e093d95b 100644 --- a/interface-definitions/interfaces-loopback.xml.in +++ b/interface-definitions/interfaces-loopback.xml.in @@ -26,6 +26,7 @@ #include + #include #include #include diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 311e95c2f..fbdd1562a 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -23,6 +23,7 @@ #include #include #include + #include Security/Encryption Settings diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index 73e30e590..761f8bcad 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -168,6 +168,7 @@ #include + #include Hashing Algorithm diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in index 1d888236e..adf5f4040 100644 --- a/interface-definitions/interfaces-pppoe.xml.in +++ b/interface-definitions/interfaces-pppoe.xml.in @@ -102,6 +102,7 @@ + #include #include 1492 diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index 7baeac537..aed2052f5 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -27,6 +27,7 @@ #include #include #include + #include #include #include diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in index bc9297c86..b31f22552 100644 --- a/interface-definitions/interfaces-tunnel.xml.in +++ b/interface-definitions/interfaces-tunnel.xml.in @@ -107,6 +107,7 @@ Invalid encapsulation, must be one of: erspan, gre, gretap, ip6erspan, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6 + #include Multicast operation over tunnel diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in index 538194c2b..d66fc952e 100644 --- a/interface-definitions/interfaces-vti.xml.in +++ b/interface-definitions/interfaces-vti.xml.in @@ -34,6 +34,7 @@ #include #include #include + #include #include #include #include diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index 18abf9f20..b1a2dfaec 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -53,6 +53,7 @@ #include #include #include + #include #include #include diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 2f130c6f2..51565cfe6 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -23,6 +23,7 @@ #include #include #include + #include 1420 diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index ef56c208a..a16a7841e 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -566,6 +566,7 @@ g + #include Wireless physical device diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in index c46bc58a7..33bc0cb3d 100644 --- a/interface-definitions/interfaces-wwan.xml.in +++ b/interface-definitions/interfaces-wwan.xml.in @@ -31,6 +31,7 @@ #include #include #include + #include #include 1430 diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 7f1258575..df2c5775a 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -178,31 +178,26 @@ def verify_eapol(config): if 'certificate' not in ca_cert: raise ConfigError('Invalid CA certificate specified for EAPoL') -def verify_mirror(config): +def verify_mirror_redirect(config): """ Common helper function used by interface implementations to perform - recurring validation of mirror interface configuration. + recurring validation of mirror and redirect interface configuration via tc(8) It makes no sense to mirror traffic back at yourself! """ + if {'mirror', 'redirect'} <= set(config): + raise ConfigError('Mirror and redirect can not be enabled at the same time!') + if 'mirror' in config: for direction, mirror_interface in config['mirror'].items(): if mirror_interface == config['ifname']: raise ConfigError(f'Can not mirror "{direction}" traffic back ' \ 'the originating interface!') -def verify_redirect(config): - """ - Common helper function used by interface implementations to perform - recurring validation of the redirect interface configuration. - - It makes no sense to mirror and redirect traffic at the same time! - """ - if {'mirror', 'redirect'} <= set(config): - raise ConfigError('Can not do both redirect and mirror') - if dict_search('traffic_policy.in', config) != None: - raise ConfigError('Can not use ingress policy and redirect') + # XXX: support combination of limiting and redirect/mirror - this is an + # artificial limitation + raise ConfigError('Can not use ingress policy tigether with mirror or redirect!') def verify_authentication(config): """ @@ -328,7 +323,7 @@ def verify_vlan_config(config): verify_dhcpv6(vlan) verify_address(vlan) verify_vrf(vlan) - verify_redirect(vlan) + verify_mirror_redirect(vlan) verify_mtu_parent(vlan, config) # 802.1ad (Q-in-Q) VLANs @@ -337,7 +332,7 @@ def verify_vlan_config(config): verify_dhcpv6(s_vlan) verify_address(s_vlan) verify_vrf(s_vlan) - verify_redirect(s_vlan) + verify_mirror_redirect(s_vlan) verify_mtu_parent(s_vlan, config) for c_vlan in s_vlan.get('vif_c', {}): @@ -345,7 +340,7 @@ def verify_vlan_config(config): verify_dhcpv6(c_vlan) verify_address(c_vlan) verify_vrf(c_vlan) - verify_redirect(c_vlan) + verify_mirror_redirect(c_vlan) verify_mtu_parent(c_vlan, config) verify_mtu_parent(c_vlan, s_vlan) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 585a605e4..76164ca32 100755 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1294,48 +1294,60 @@ class Interface(Control): if os.path.isfile(config_file): os.remove(config_file) - def set_mirror(self): + def set_mirror_redirect(self): # Please refer to the document for details # - https://man7.org/linux/man-pages/man8/tc.8.html # - https://man7.org/linux/man-pages/man8/tc-mirred.8.html # Depening if we are the source or the target interface of the port # mirror we need to setup some variables. source_if = self._config['ifname'] - config = self._config.get('mirror', None) + mirror_config = None + if 'mirror' in self._config: + mirror_config = self._config['mirror'] if 'is_mirror_intf' in self._config: source_if = next(iter(self._config['is_mirror_intf'])) - config = self._config['is_mirror_intf'][source_if].get('mirror', None) - - # Check configuration stored by old perl code before delete T3782/T4056 - if not 'redirect' in self._config and not 'traffic_policy' in self._config: - # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 - # Remove existing mirroring rules - delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' - delete_tc_cmd += f'tc qdisc del dev {source_if} handle 1: root prio 2> /dev/null;' - delete_tc_cmd += 'set $?=0' - self._popen(delete_tc_cmd) - - # Bail out early if nothing needs to be configured - if not config: - return - - for direction, mirror_if in config.items(): - if mirror_if not in interfaces(): - continue - - if direction == 'ingress': - handle = 'ffff: ingress' - parent = 'ffff:' - elif direction == 'egress': - handle = '1: root prio' - parent = '1:' - - # Mirror egress traffic - mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' - # Export the mirrored traffic to the interface - mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {mirror_if}' - self._popen(mirror_cmd) + mirror_config = self._config['is_mirror_intf'][source_if].get('mirror', None) + + redirect_config = None + + # clear existing ingess - ignore errors (e.g. "Error: Cannot find specified + # qdisc on specified device") - we simply cleanup all stuff here + self._popen(f'tc qdisc del dev {source_if} parent ffff: 2>/dev/null'); + self._popen(f'tc qdisc del dev {source_if} parent 1: 2>/dev/null'); + + # Apply interface mirror policy + if mirror_config: + for direction, target_if in mirror_config.items(): + if target_if not in interfaces(): + continue + + if direction == 'ingress': + handle = 'ffff: ingress' + parent = 'ffff:' + elif direction == 'egress': + handle = '1: root prio' + parent = '1:' + + # Mirror egress traffic + mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' + # Export the mirrored traffic to the interface + mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress mirror dev {target_if}' + _, err = self._popen(mirror_cmd) + if err: print('tc qdisc(filter for mirror port failed') + + # Apply interface traffic redirection policy + elif 'redirect' in self._config: + _, err = self._popen(f'tc qdisc add dev {source_if} handle ffff: ingress') + if err: print(f'tc qdisc add for redirect failed!') + + target_if = self._config['redirect'] + _, err = self._popen(f'tc filter add dev {source_if} parent ffff: protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress redirect dev {target_if}') + if err: print('tc filter add for redirect failed') def set_xdp(self, state): """ @@ -1562,8 +1574,8 @@ class Interface(Control): # eXpress Data Path - highly experimental self.set_xdp('xdp' in config) - # configure port mirror - self.set_mirror() + # configure interface mirror or redirection target + self.set_mirror_redirect() # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() @@ -1723,5 +1735,5 @@ class VLANIf(Interface): return super().set_admin_state(state) - def set_mirror(self): + def set_mirror_redirect(self): return diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 661dc2298..ad5a0f499 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -27,9 +27,8 @@ from vyos.configdict import is_source_interface from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_mirror +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf @@ -151,8 +150,7 @@ def verify(bond): verify_address(bond) verify_dhcpv6(bond) verify_vrf(bond) - verify_mirror(bond) - verify_redirect(bond) + verify_mirror_redirect(bond) # use common function to verify VLAN configuration verify_vlan_config(bond) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index e16c0e9f4..b1f7e6d7c 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -27,8 +27,7 @@ from vyos.configdict import is_source_interface from vyos.configdict import has_vlan_subinterface_configured from vyos.configdict import dict_merge from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_mirror -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf from vyos.validate import has_address_configured @@ -107,8 +106,7 @@ def verify(bridge): verify_dhcpv6(bridge) verify_vrf(bridge) - verify_mirror(bridge) - verify_redirect(bridge) + verify_mirror_redirect(bridge) ifname = bridge['ifname'] diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py index 4072c4452..4a1eb7b93 100755 --- a/src/conf_mode/interfaces-dummy.py +++ b/src/conf_mode/interfaces-dummy.py @@ -21,7 +21,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import DummyIf from vyos import ConfigError from vyos import airbag @@ -47,7 +47,7 @@ def verify(dummy): verify_vrf(dummy) verify_address(dummy) - verify_redirect(dummy) + verify_mirror_redirect(dummy) return None diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 3eeddf190..6aea7a80e 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -25,10 +25,9 @@ from vyos.configverify import verify_address from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_eapol from vyos.configverify import verify_interface_exists -from vyos.configverify import verify_mirror +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ethtool import Ethtool @@ -84,8 +83,7 @@ def verify(ethernet): verify_address(ethernet) verify_vrf(ethernet) verify_eapol(ethernet) - verify_mirror(ethernet) - verify_redirect(ethernet) + verify_mirror_redirect(ethernet) ethtool = Ethtool(ifname) # No need to check speed and duplex keys as both have default values. diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index a94b5e1f7..3a668226b 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.py @@ -24,7 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_address from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_bridge_delete -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import GeneveIf from vyos import ConfigError @@ -51,7 +51,7 @@ def verify(geneve): verify_mtu_ipv6(geneve) verify_address(geneve) - verify_redirect(geneve) + verify_mirror_redirect(geneve) if 'remote' not in geneve: raise ConfigError('Remote side must be configured') diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 5ea7159dc..22256bf4f 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -25,7 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import L2TPv3If from vyos.util import check_kmod from vyos.validate import is_addr_assigned @@ -77,7 +77,7 @@ def verify(l2tpv3): verify_mtu_ipv6(l2tpv3) verify_address(l2tpv3) - verify_redirect(l2tpv3) + verify_mirror_redirect(l2tpv3) return None def generate(l2tpv3): diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py index e6a851113..e4bc15bb5 100755 --- a/src/conf_mode/interfaces-loopback.py +++ b/src/conf_mode/interfaces-loopback.py @@ -20,7 +20,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import LoopbackIf from vyos import ConfigError from vyos import airbag @@ -40,7 +40,7 @@ def get_config(config=None): return loopback def verify(loopback): - verify_redirect(loopback) + verify_mirror_redirect(loopback) return None def generate(loopback): diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 6a29fdb11..96fc1c41c 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -29,7 +29,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos import ConfigError from vyos import airbag @@ -67,7 +67,7 @@ def verify(macsec): verify_vrf(macsec) verify_mtu_ipv6(macsec) verify_address(macsec) - verify_redirect(macsec) + verify_mirror_redirect(macsec) if not (('security' in macsec) and ('cipher' in macsec['security'])): diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 8f9c0b3f1..83d1c6d9b 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -35,6 +35,7 @@ from vyos.configdict import get_interface_dict from vyos.configdict import leaf_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTunIf from vyos.pki import load_dh_parameters from vyos.pki import load_private_key @@ -495,6 +496,7 @@ def verify(openvpn): raise ConfigError('Username for authentication is missing') verify_vrf(openvpn) + verify_mirror_redirect(openvpn) return None diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 9962e0a08..bfb1fadd5 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -28,7 +28,7 @@ from vyos.configverify import verify_source_interface from vyos.configverify import verify_interface_exists from vyos.configverify import verify_vrf from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import PPPoEIf from vyos.template import render from vyos.util import call @@ -86,7 +86,7 @@ def verify(pppoe): verify_authentication(pppoe) verify_vrf(pppoe) verify_mtu_ipv6(pppoe) - verify_redirect(pppoe) + verify_mirror_redirect(pppoe) if {'connect_on_demand', 'vrf'} <= set(pppoe): raise ConfigError('On-demand dialing and VRF can not be used at the same time') diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index f57e41cc4..f2c85554f 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -25,7 +25,7 @@ from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_mtu_parent -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import MACVLANIf from vyos import ConfigError @@ -61,7 +61,7 @@ def verify(peth): verify_vrf(peth) verify_address(peth) verify_mtu_parent(peth, peth['parent']) - verify_redirect(peth) + verify_mirror_redirect(peth) # use common function to verify VLAN configuration verify_vlan_config(peth) diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 005fae5eb..f4668d976 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -26,7 +26,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.configverify import verify_tunnel from vyos.ifconfig import Interface @@ -158,7 +158,7 @@ def verify(tunnel): verify_mtu_ipv6(tunnel) verify_address(tunnel) verify_vrf(tunnel) - verify_redirect(tunnel) + verify_mirror_redirect(tunnel) if 'source_interface' in tunnel: verify_interface_exists(tunnel['source_interface']) diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index 30e13536f..f06fdff1b 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -19,7 +19,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTIIf from vyos.util import dict_search from vyos import ConfigError @@ -40,7 +40,7 @@ def get_config(config=None): return vti def verify(vti): - verify_redirect(vti) + verify_mirror_redirect(vti) return None def generate(vti): diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index a29836efd..0a9b51cac 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -25,7 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos.ifconfig import Interface from vyos.ifconfig import VXLANIf @@ -141,7 +141,7 @@ def verify(vxlan): verify_mtu_ipv6(vxlan) verify_address(vxlan) - verify_redirect(vxlan) + verify_mirror_redirect(vxlan) return None def generate(vxlan): diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index dc0fe7b9c..b404375d6 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -28,7 +28,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod from vyos.util import check_port_availability @@ -71,7 +71,7 @@ def verify(wireguard): verify_mtu_ipv6(wireguard) verify_address(wireguard) verify_vrf(wireguard) - verify_redirect(wireguard) + verify_mirror_redirect(wireguard) if 'private_key' not in wireguard: raise ConfigError('Wireguard private-key not defined') diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index fdf9e3988..500952df1 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -27,7 +27,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_source_interface -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import WiFiIf @@ -190,7 +190,7 @@ def verify(wifi): verify_address(wifi) verify_vrf(wifi) - verify_redirect(wifi) + verify_mirror_redirect(wifi) # use common function to verify VLAN configuration verify_vlan_config(wifi) diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index d5e259c74..9a33039a3 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -24,7 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configdict import leaf_node_changed from vyos.configverify import verify_authentication from vyos.configverify import verify_interface_exists -from vyos.configverify import verify_redirect +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import WWANIf from vyos.util import cmd @@ -105,7 +105,7 @@ def verify(wwan): verify_interface_exists(ifname) verify_authentication(wwan) verify_vrf(wwan) - verify_redirect(wwan) + verify_mirror_redirect(wwan) return None -- cgit v1.2.3