summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/bgp.frr.tmpl4
-rw-r--r--data/templates/openvpn/server.conf.tmpl24
-rw-r--r--interface-definitions/include/interface-mirror.xml.i26
-rw-r--r--python/vyos/ifconfig/interface.py49
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py34
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py44
-rwxr-xr-xsrc/migration-scripts/interfaces/16-to-1752
7 files changed, 179 insertions, 54 deletions
diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl
index 86e1aa366..16355a1e5 100644
--- a/data/templates/frr/bgp.frr.tmpl
+++ b/data/templates/frr/bgp.frr.tmpl
@@ -114,9 +114,9 @@
{% endif %}
{% if config.address_family[af].prefix_list is defined and config.address_family[af].prefix_list is not none %}
{% if config.address_family[af].prefix_list.export is defined and config.address_family[af].prefix_list.export is not none %}
- neighbor {{ neighbor }} route-map {{ config.address_family[af].prefix_list.export }} out
+ neighbor {{ neighbor }} prefix-list {{ config.address_family[af].prefix_list.export }} out
{% elif config.address_family[af].prefix_list.import is defined and config.address_family[af].prefix_list.import is not none %}
- neighbor {{ neighbor }} route-map {{ config.address_family[af].prefix_list.export }} in
+ neighbor {{ neighbor }} prefix-list {{ config.address_family[af].prefix_list.import }} in
{% endif %}
{% endif %}
{% if config.address_family[af].soft_reconfiguration is defined and config.address_family[af].soft_reconfiguration.inbound is defined %}
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index a1daaa078..9fc281afc 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -227,7 +227,29 @@ cipher aes-256-cbc
{% endif %}
{% endif %}
{% if encryption.ncp_ciphers is defined and encryption.ncp_ciphers is not none %}
-ncp-ciphers {{ encryption.ncp_ciphers | join(':') }}
+{% set cipher_list = [] %}
+{% for cipher in encryption.ncp_ciphers %}
+{% if cipher == 'none' %}
+{% set cipher_list = cipher_list.append('none') %}
+{% elif cipher == 'des' %}
+{% set cipher_list = cipher_list.append('des-cbc') %}
+{% elif cipher == '3des' %}
+{% set cipher_list = cipher_list.append('des-ede3-cbc') %}
+{% elif cipher == 'aes128' %}
+{% set cipher_list = cipher_list.append('aes-128-cbc') %}
+{% elif cipher == 'aes128gcm' %}
+{% set cipher_list = cipher_list.append('aes-128-gcm') %}
+{% elif cipher == 'aes192' %}
+{% set cipher_list = cipher_list.append('aes-192-cbc') %}
+{% elif cipher == 'aes192gcm' %}
+{% set cipher_list = cipher_list.append('aes-192-gcm') %}
+{% elif cipher == 'aes256' %}
+{% set cipher_list = cipher_list.append('aes-256-cbc') %}
+{% elif cipher == 'aes256gcm' %}
+{% set cipher_list = cipher_list.append('aes-256-gcm') %}
+{% endif %}
+{% endfor %}
+ncp-ciphers {{ cipher_list | join(':') }}:{{ cipher_list | join(':') | upper }}
{% elif encryption.disable_ncp is defined %}
ncp-disable
{% endif %}
diff --git a/interface-definitions/include/interface-mirror.xml.i b/interface-definitions/include/interface-mirror.xml.i
index e3720cde7..d34132a9c 100644
--- a/interface-definitions/include/interface-mirror.xml.i
+++ b/interface-definitions/include/interface-mirror.xml.i
@@ -1,11 +1,25 @@
<!-- included start from interface-mirror.xml.i -->
-<leafNode name="mirror">
+<node name="mirror">
<properties>
<help>Incoming/outgoing packet mirroring destination</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
- </completionHelp>
- <multi/>
</properties>
-</leafNode>
+ <children>
+ <leafNode name="ingress">
+ <properties>
+ <help>Mirror the ingress traffic of the interface to the destination interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="egress">
+ <properties>
+ <help>Mirror the egress traffic of the interface to the destination interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ </children>
+</node>
<!-- included end -->
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 24f60efb8..6e6a83f36 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -977,25 +977,40 @@ class Interface(Control):
old_handle = rule['handle']
old_kind = rule['kind']
if old_dev == dev and old_handle == handle and old_kind == kind:
- delete_tc_cmd = f'tc qdisc del dev {dev} handle {handle} {kind}'
- self._cmd(delete_tc_cmd)
-
-
-
- def apply_mirror(self,config):
- ifname = config['ifname']
-
+ if 'root' in rule and rule['root']:
+ delete_tc_cmd = f'tc qdisc del dev {dev} handle {handle} root {kind}'
+ self._cmd(delete_tc_cmd)
+ else:
+ delete_tc_cmd = f'tc qdisc del dev {dev} handle {handle} {kind}'
+ self._cmd(delete_tc_cmd)
+
+ def apply_mirror(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
+ ifname = self._config['ifname']
# Remove existing mirroring rules
self.del_tc_qdisc(ifname,'ingress','ffff:')
-
+ self.del_tc_qdisc(ifname,'prio','1:')
+
# Setting up packet mirroring
- mirror = dict_search('mirror', config)
- if mirror:
- for interface in mirror:
- mirror_cmd = f'tc qdisc add dev {ifname} handle ffff: ingress'
- self._cmd(mirror_cmd)
- mirror_cmd = f'tc filter add dev {ifname} parent ffff: protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {interface}'
- self._cmd(mirror_cmd)
+ ingress_mirror = dict_search('mirror.ingress', self._config)
+ if ingress_mirror:
+ # Mirror ingress traffic
+ mirror_cmd = f'tc qdisc add dev {ifname} handle ffff: ingress'
+ self._cmd(mirror_cmd)
+ # Export the mirrored traffic to the interface
+ mirror_cmd = f'tc filter add dev {ifname} parent ffff: protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {ingress_mirror}'
+ self._cmd(mirror_cmd)
+
+ egress_mirror = dict_search('mirror.egress', self._config)
+ if egress_mirror:
+ # Mirror egress traffic
+ mirror_cmd = f'tc qdisc add dev {ifname} handle 1: root prio'
+ self._cmd(mirror_cmd)
+ # Export the mirrored traffic to the interface
+ mirror_cmd = f'tc filter add dev {ifname} parent 1: protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {egress_mirror}'
+ self._cmd(mirror_cmd)
def update(self, config):
""" General helper function which works on a dictionary retrived by
@@ -1215,7 +1230,7 @@ class Interface(Control):
vlan = VLANIf(vif_ifname, **tmp)
vlan.update(vif_config)
- self.apply_mirror(config)
+ self.apply_mirror()
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 4187fd77c..d1bb9c3fe 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -28,6 +28,22 @@ from vyos.util import dict_search
from vyos.validate import is_intf_addr_assigned
from vyos.validate import is_ipv6_link_local
+def read_mirror_rule(interfaces):
+ Success = 0
+ for interface in interfaces:
+ get_tc_cmd = 'tc -j qdisc'
+ tmp = cmd(get_tc_cmd, shell=True)
+ data = json.loads(tmp)
+ for rule in data:
+ dev = rule['dev']
+ handle = rule['handle']
+ kind = rule['kind']
+ if dev == interface and handle == "ffff:" and kind == "ingress":
+ Success+=1
+ elif dev == interface and handle == "1:" and kind == "prio":
+ Success+=1
+ return Success
+
class BasicInterfaceTest:
class BaseTest(unittest.TestCase):
_test_ip = False
@@ -73,25 +89,19 @@ class BasicInterfaceTest:
Success = 0
i = 0
if self._test_mirror:
+ # Check the two-way mirror rules of ingress and egress
for interface in self._interfaces:
- self.session.set(self._base_path + [interface, 'mirror', 'lo'])
+ self.session.set(self._base_path + [interface, 'mirror', 'ingress', 'lo'])
+ self.session.set(self._base_path + [interface, 'mirror', 'egress', 'lo'])
i+=1
self.session.commit()
# Parse configuration
- for interface in self._interfaces:
- get_tc_cmd = 'tc -j qdisc'
- tmp = cmd(get_tc_cmd, shell=True)
- data = json.loads(tmp)
- for rule in data:
- dev = rule['dev']
- handle = rule['handle']
- kind = rule['kind']
- if dev == interface and handle == "ffff:" and kind == "ingress":
- Success+=1
- if Success == i:
+ Success = read_mirror_rule(self._interfaces)
+ if Success == i*2:
self.assertTrue(True)
else:
self.assertTrue(False)
+ i=0
else:
return None
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 642738b09..a3f32fd2d 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -60,12 +60,22 @@ def verify(bgp):
if neigh not in asn_config:
continue
- for neighbor, config in asn_config[neigh].items():
- if 'remote_as' not in config and 'peer_group' not in config:
- raise ConfigError(f'BGP remote-as must be specified for "{neighbor}"!')
+ #for neighbor, config in asn_config[neigh].items():
+ '''
+ # These checks need to be modified. Because peer-group can be declared without 'remote-as'.
+ # When 'remote-as' configured for specific neighbor in peer-group. For example
+ #
- if 'remote_as' in config and 'peer_group' in config:
- raise ConfigError(f'BGP peer-group member "{neighbor}" cannot override remote-as of peer-group!')
+ set protocols nbgp 65001 neighbor 100.64.0.2 peer-group 'FOO'
+ set protocols nbgp 65001 neighbor 100.64.0.2 remote-as '65002'
+ set protocols nbgp 65001 peer-group FOO
+
+ '''
+ #if 'remote_as' not in config and 'peer_group' not in config:
+ # raise ConfigError(f'BGP remote-as must be specified for "{neighbor}"!')
+
+ #if 'remote_as' in config and 'peer_group' in config:
+ # raise ConfigError(f'BGP peer-group member "{neighbor}" cannot override remote-as of peer-group!')
return None
@@ -87,24 +97,26 @@ def generate(bgp):
def apply(bgp):
# Save original configuration prior to starting any commit actions
- frr_cfg = {}
- frr_cfg['original_config'] = frr.get_configuration(daemon='bgpd')
- frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], bgp['new_frr_config'], from_re='router bgp .*')
+ frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration(daemon='bgpd')
+ frr_cfg.modify_section(f'router bgp \S+', '')
+ frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['new_frr_config'])
+ frr_cfg.commit_configuration(daemon='bgpd')
+
+ # If FRR config is blank, rerun the blank commit x times due to frr-reload
+ # behavior/bug not properly clearing out on one commit.
+ if bgp['new_frr_config'] == '':
+ for a in range(5):
+ frr_cfg.commit_configuration(daemon='bgpd')
# Debugging
+ '''
print('')
print('--------- DEBUGGING ----------')
print(f'Existing config:\n{frr_cfg["original_config"]}\n\n')
print(f'Replacement config:\n{bgp["new_frr_config"]}\n\n')
print(f'Modified config:\n{frr_cfg["modified_config"]}\n\n')
-
- # FRR mark configuration will test for syntax errors and throws an
- # exception if any syntax errors is detected
- frr.mark_configuration(frr_cfg['modified_config'])
-
- # Commit resulting configuration to FRR, this will throw CommitError
- # on failure
- frr.reload_configuration(frr_cfg['modified_config'], daemon='bgpd')
+ '''
return None
diff --git a/src/migration-scripts/interfaces/16-to-17 b/src/migration-scripts/interfaces/16-to-17
new file mode 100755
index 000000000..a6b4c7663
--- /dev/null
+++ b/src/migration-scripts/interfaces/16-to-17
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 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 <http://www.gnu.org/licenses/>.
+
+# Command line migration of port mirroring
+# https://phabricator.vyos.net/T3089
+
+import sys
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ sys.exit(1)
+
+ file_name = sys.argv[1]
+
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ base = ['interfaces', 'ethernet']
+ if not config.exists(base):
+ # Nothing to do
+ sys.exit(0)
+
+ for interface in config.list_nodes(base):
+ mirror_old_base = base + [interface, 'mirror']
+ if config.exists(mirror_old_base):
+ intf = config.return_values(mirror_old_base)
+ if config.exists(mirror_old_base):
+ config.delete(mirror_old_base)
+ config.set(mirror_old_base + ['ingress'],intf[0])
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ sys.exit(1)