summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/configd-include.json1
-rw-r--r--interface-definitions/interfaces-erspan.xml.in114
-rw-r--r--interface-definitions/interfaces-tunnel.xml.in89
-rw-r--r--python/vyos/ifconfig/__init__.py2
-rwxr-xr-xpython/vyos/ifconfig/erspan.py170
-rw-r--r--python/vyos/ifconfig/tunnel.py12
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_tunnel.py86
-rwxr-xr-xsrc/conf_mode/interfaces-erspan.py108
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py30
9 files changed, 205 insertions, 407 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
index eed858363..4959e5020 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -21,7 +21,6 @@
"interfaces-pppoe.py",
"interfaces-pseudo-ethernet.py",
"interfaces-tunnel.py",
-"interfaces-erspan.py",
"interfaces-vxlan.py",
"interfaces-wireguard.py",
"interfaces-wireless.py",
diff --git a/interface-definitions/interfaces-erspan.xml.in b/interface-definitions/interfaces-erspan.xml.in
deleted file mode 100644
index 769899415..000000000
--- a/interface-definitions/interfaces-erspan.xml.in
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0"?>
-<interfaceDefinition>
- <node name="interfaces">
- <children>
- <tagNode name="erspan" owner="${vyos_conf_scripts_dir}/interfaces-erspan.py">
- <properties>
- <help>Encapsulated Remote SPAN over GRE and IPv4/IPv6 Tunnel Interface</help>
- <priority>310</priority>
- <constraint>
- <regex>^ersp[0-9]+$</regex>
- </constraint>
- <constraintErrorMessage>ERSPAN tunnel interface must be named erspN</constraintErrorMessage>
- <valueHelp>
- <format>erspN</format>
- <description>ERSPAN Tunnel interface name</description>
- </valueHelp>
- </properties>
- <children>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-mtu-64-8024.xml.i>
- #include <include/source-address-ipv4-ipv6.xml.i>
- #include <include/interface/tunnel-remote.xml.i>
- <leafNode name="encapsulation">
- <properties>
- <help>Encapsulation of this tunnel interface</help>
- <completionHelp>
- <list>erspan ip6erspan</list>
- </completionHelp>
- <valueHelp>
- <format>erspan</format>
- <description>Generic Routing Encapsulation</description>
- </valueHelp>
- <valueHelp>
- <format>ip6erspan</format>
- <description>Generic Routing Encapsulation bridge interface</description>
- </valueHelp>
- <constraint>
- <regex>^(erspan|ip6erspan)$</regex>
- </constraint>
- <constraintErrorMessage>Invalid encapsulation, must be one of: erspan, ip6erspan</constraintErrorMessage>
- </properties>
- </leafNode>
- <node name="parameters">
- <properties>
- <help>ERSPAN Tunnel parameters</help>
- </properties>
- <children>
- <node name="ip">
- <properties>
- <help>IPv4 specific tunnel parameters</help>
- </properties>
- <children>
- #include <include/interface/interface-parameters-key.xml.i>
- #include <include/interface/interface-parameters-tos.xml.i>
- #include <include/interface/interface-parameters-ttl.xml.i>
- </children>
- </node>
- <leafNode name="version">
- <properties>
- <help>ERSPAN version number setting(default:1)</help>
- <constraint>
- <validator name="numeric" argument="--range 1-2"/>
- </constraint>
- <constraintErrorMessage>The version number of ERSPAN must be 1 or 2</constraintErrorMessage>
- </properties>
- <defaultValue>1</defaultValue>
- </leafNode>
- <leafNode name="direction">
- <properties>
- <help>Specifies mirrored traffic direction</help>
- <completionHelp>
- <list>ingress egress</list>
- </completionHelp>
- <valueHelp>
- <format>ingress</format>
- <description>Mirror ingress direction</description>
- </valueHelp>
- <valueHelp>
- <format>egress</format>
- <description>Mirror egress direction</description>
- </valueHelp>
- <constraint>
- <regex>^(ingress|egress)$</regex>
- </constraint>
- <constraintErrorMessage>The mirror direction of ERSPAN must be ingress or egress</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="hwid">
- <properties>
- <help>an unique identifier of an ERSPAN v2 engine within a system</help>
- <constraint>
- <validator name="numeric" argument="--range 1-1048575"/>
- </constraint>
- <constraintErrorMessage>ERSPAN hwid must be a number(range:0-1048575)</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="idx">
- <properties>
- <help>specifies the ERSPAN v1 index field</help>
- <constraint>
- <validator name="numeric" argument="--range 0-63"/>
- </constraint>
- <constraintErrorMessage>ERSPAN idx must be a number(range:0-63)</constraintErrorMessage>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </tagNode>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in
index e3aad2719..e4bdcb3d7 100644
--- a/interface-definitions/interfaces-tunnel.xml.in
+++ b/interface-definitions/interfaces-tunnel.xml.in
@@ -80,9 +80,13 @@
<properties>
<help>Encapsulation of this tunnel interface</help>
<completionHelp>
- <list>gre gretap ip6gre ip6gretap ip6ip6 ipip ipip6 sit</list>
+ <list>erspan gre gretap ip6erspan ip6gre ip6gretap ip6ip6 ipip ipip6 sit</list>
</completionHelp>
<valueHelp>
+ <format>erspan</format>
+ <description>Encapsulated Remote Switched Port Analyzer</description>
+ </valueHelp>
+ <valueHelp>
<format>gre</format>
<description>Generic Routing Encapsulation</description>
</valueHelp>
@@ -91,6 +95,10 @@
<description>Generic Routing Encapsulation (virtual L2 tunnel)</description>
</valueHelp>
<valueHelp>
+ <format>ip6erspan</format>
+ <description>Encapsulated Remote Switched Port Analyzer over IPv6 network</description>
+ </valueHelp>
+ <valueHelp>
<format>ip6gre</format>
<description>GRE over IPv6 network</description>
</valueHelp>
@@ -115,9 +123,9 @@
<description>Simple Internet Transition encapsulation</description>
</valueHelp>
<constraint>
- <regex>^(gre|gretap|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)$</regex>
+ <regex>^(erspan|gre|gretap|ip6erspan|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)$</regex>
</constraint>
- <constraintErrorMessage>Invalid encapsulation, must be one of: gre, gretap, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6</constraintErrorMessage>
+ <constraintErrorMessage>Invalid encapsulation, must be one of: erspan, gre, gretap, ip6erspan, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="multicast">
@@ -145,6 +153,81 @@
<help>Tunnel parameters</help>
</properties>
<children>
+ <node name="erspan">
+ <properties>
+ <help>ERSPAN Tunnel parameters</help>
+ </properties>
+ <children>
+
+<!---
+Temporary disabled b/c of https://github.com/shemminger/iproute2/issues/41
+ <leafNode name="direction">
+ <properties>
+ <help>Specifies mirrored traffic direction</help>
+ <completionHelp>
+ <list>ingress egress</list>
+ </completionHelp>
+ <valueHelp>
+ <format>ingress</format>
+ <description>Mirror ingress direction</description>
+ </valueHelp>
+ <valueHelp>
+ <format>egress</format>
+ <description>Mirror egress direction</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(ingress|egress)$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="hw-id">
+ <properties>
+ <help>Unique identifier of ERSPAN engine within a system</help>
+ <valueHelp>
+ <format>0-1048575</format>
+ <description>Unique identifier of ERSPAN engine</description>
+ </valueHelp>
+ <constraint>
+fix double hyphen below ...
+ <validator name="numeric" argument="- -range 0-1048575"/>
+ </constraint>
+ </properties>
+ </leafNode>
+-->
+ <leafNode name="index">
+ <properties>
+ <help>Specifify ERSPAN version 1 index field</help>
+ <valueHelp>
+ <format>0-63</format>
+ <description>Platform-depedent field for specifying port number and direction</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-63"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="version">
+ <properties>
+ <help>Protocol version</help>
+ <valueHelp>
+ <format>1</format>
+ <description>ERSPAN Type II</description>
+ </valueHelp>
+<!--
+Temporary disabled b/c of https://github.com/shemminger/iproute2/issues/41
+ <valueHelp>
+ <format>2</format>
+ <description>ERSPAN Type III</description>
+ </valueHelp>
+-->
+ <constraint>
+ <validator name="numeric" argument="--range 1-1"/>
+ </constraint>
+ </properties>
+ <defaultValue>1</defaultValue>
+ </leafNode>
+ </children>
+ </node>
<node name="ip">
<properties>
<help>IPv4 specific tunnel parameters</help>
diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py
index f5dfa8e05..e9da1e9f5 100644
--- a/python/vyos/ifconfig/__init__.py
+++ b/python/vyos/ifconfig/__init__.py
@@ -32,8 +32,6 @@ from vyos.ifconfig.vtun import VTunIf
from vyos.ifconfig.vti import VTIIf
from vyos.ifconfig.pppoe import PPPoEIf
from vyos.ifconfig.tunnel import TunnelIf
-from vyos.ifconfig.erspan import ERSpanIf
-from vyos.ifconfig.erspan import ER6SpanIf
from vyos.ifconfig.wireless import WiFiIf
from vyos.ifconfig.l2tpv3 import L2TPv3If
from vyos.ifconfig.macsec import MACsecIf
diff --git a/python/vyos/ifconfig/erspan.py b/python/vyos/ifconfig/erspan.py
deleted file mode 100755
index 03b2acdbf..000000000
--- a/python/vyos/ifconfig/erspan.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library. If not, see <http://www.gnu.org/licenses/>.
-
-# https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/#erspan
-# http://vger.kernel.org/lpc_net2018_talks/erspan-linux-presentation.pdf
-
-from copy import deepcopy
-
-from netaddr import EUI
-from netaddr import mac_unix_expanded
-from random import getrandbits
-
-from vyos.util import dict_search
-from vyos.ifconfig.interface import Interface
-from vyos.validate import assert_list
-
-@Interface.register
-class _ERSpan(Interface):
- """
- _ERSpan: private base class for ERSPAN tunnels
- """
- iftype = 'erspan'
- definition = {
- **Interface.definition,
- **{
- 'section': 'erspan',
- 'prefixes': ['ersp',],
- },
- }
-
- def __init__(self,ifname,**config):
- self.config = deepcopy(config) if config else {}
- super().__init__(ifname, **self.config)
-
- def change_options(self):
- pass
-
- def _create(self):
- pass
-
-class ERSpanIf(_ERSpan):
- """
- ERSpanIf: private base class for ERSPAN Over GRE and IPv4 tunnels
- """
-
- def _create(self):
- ifname = self.config['ifname']
- source_address = self.config['source_address']
- remote = self.config['remote']
- key = self.config['parameters']['ip']['key']
- version = self.config['parameters']['version']
- command = f'ip link add dev {ifname} type erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
-
- if int(version) == 1:
- idx=dict_search('parameters.erspan.idx',self.config)
- if idx:
- command += f' erspan {idx}'
- elif int(version) == 2:
- direction=dict_search('parameters.erspan.direction',self.config)
- if direction:
- command += f' erspan_dir {direction}'
- hwid=dict_search('parameters.erspan.hwid',self.config)
- if hwid:
- command += f' erspan_hwid {hwid}'
-
- ttl = dict_search('parameters.ip.ttl',self.config)
- if ttl:
- command += f' ttl {ttl}'
- tos = dict_search('parameters.ip.tos',self.config)
- if tos:
- command += f' tos {tos}'
-
- self._cmd(command)
-
- def change_options(self):
- ifname = self.config['ifname']
- source_address = self.config['source_address']
- remote = self.config['remote']
- key = self.config['parameters']['ip']['key']
- version = self.config['parameters']['version']
- command = f'ip link set dev {ifname} type erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
-
- if int(version) == 1:
- idx=dict_search('parameters.erspan.idx',self.config)
- if idx:
- command += f' erspan {idx}'
- elif int(version) == 2:
- direction=dict_search('parameters.erspan.direction',self.config)
- if direction:
- command += f' erspan_dir {direction}'
- hwid=dict_search('parameters.erspan.hwid',self.config)
- if hwid:
- command += f' erspan_hwid {hwid}'
-
- ttl = dict_search('parameters.ip.ttl',self.config)
- if ttl:
- command += f' ttl {ttl}'
- tos = dict_search('parameters.ip.tos',self.config)
- if tos:
- command += f' tos {tos}'
-
- self._cmd(command)
-
-class ER6SpanIf(_ERSpan):
- """
- ER6SpanIf: private base class for ERSPAN Over GRE and IPv6 tunnels
- """
-
- def _create(self):
- ifname = self.config['ifname']
- source_address = self.config['source_address']
- remote = self.config['remote']
- key = self.config['parameters']['ip']['key']
- version = self.config['parameters']['version']
- command = f'ip link add dev {ifname} type ip6erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
-
- if int(version) == 1:
- idx=dict_search('parameters.erspan.idx',self.config)
- if idx:
- command += f' erspan {idx}'
- elif int(version) == 2:
- direction=dict_search('parameters.erspan.direction',self.config)
- if direction:
- command += f' erspan_dir {direction}'
- hwid=dict_search('parameters.erspan.hwid',self.config)
- if hwid:
- command += f' erspan_hwid {hwid}'
-
- ttl = dict_search('parameters.ip.ttl',self.config)
- if ttl:
- command += f' ttl {ttl}'
- tos = dict_search('parameters.ip.tos',self.config)
- if tos:
- command += f' tos {tos}'
-
- self._cmd(command)
-
- def change_options(self):
- ifname = self.config['ifname']
- source_address = self.config['source_address']
- remote = self.config['remote']
- key = self.config['parameters']['ip']['key']
- version = self.config['parameters']['version']
- command = f'ip link set dev {ifname} type ip6erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
-
- if int(version) == 1:
- idx=dict_search('parameters.erspan.idx',self.config)
- if idx:
- command += f' erspan {idx}'
- elif int(version) == 2:
- direction=dict_search('parameters.erspan.direction',self.config)
- if direction:
- command += f' erspan_dir {direction}'
- hwid=dict_search('parameters.erspan.hwid',self.config)
- if hwid:
- command += f' erspan_hwid {hwid}'
-
- self._cmd(command)
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index e5e1300b2..08854a3b0 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -63,6 +63,10 @@ class TunnelIf(Interface):
'parameters.ip.no_pmtu_discovery' : 'nopmtudisc',
'parameters.ip.tos' : 'tos',
'parameters.ip.ttl' : 'ttl',
+ 'parameters.erspan.direction' : 'erspan_dir',
+ 'parameters.erspan.hw_id' : 'erspan_hwid',
+ 'parameters.erspan.index' : 'erspan',
+ 'parameters.erspan.version' : 'erspan_ver',
}
mapping_ipv6 = {
'parameters.ipv6.encaplimit' : 'encaplimit',
@@ -113,8 +117,12 @@ class TunnelIf(Interface):
mapping = { **self.mapping, **self.mapping_ipv4 }
cmd = 'ip tunnel add {ifname} mode {encapsulation}'
- if self.iftype in ['gretap', 'ip6gretap']:
+ if self.iftype in ['gretap', 'ip6gretap', 'erspan', 'ip6erspan']:
cmd = 'ip link add name {ifname} type {encapsulation}'
+ # ERSPAN requires the serialisation of packets
+ if self.iftype in ['erspan', 'ip6erspan']:
+ cmd += ' seq'
+
for vyos_key, iproute2_key in mapping.items():
# dict_search will return an empty dict "{}" for valueless nodes like
# "parameters.nolearning" - thus we need to test the nodes existence
@@ -131,7 +139,7 @@ class TunnelIf(Interface):
def _change_options(self):
# gretap interfaces do not support changing any parameter
- if self.iftype in ['gretap', 'ip6gretap']:
+ if self.iftype in ['gretap', 'ip6gretap', 'erspan', 'ip6erspan']:
return
if self.config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py
index 6af31ddff..0e021b385 100755
--- a/smoketest/scripts/cli/test_interfaces_tunnel.py
+++ b/smoketest/scripts/cli/test_interfaces_tunnel.py
@@ -232,5 +232,91 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase):
conf = get_interface_config(interface)
self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote'])
+ def test_erspan(self):
+ interface = f'tun1070'
+ encapsulation = 'erspan'
+ ip_key = '77'
+ idx = '20'
+
+ self.cli_set(self._base_path + [interface, 'encapsulation', encapsulation])
+ self.cli_set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.cli_set(self._base_path + [interface, 'remote', remote_ip4])
+
+ self.cli_set(self._base_path + [interface, 'parameters', 'erspan', 'index', idx])
+
+ # ERSPAN requires ip key parameter
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_set(self._base_path + [interface, 'parameters', 'ip', 'key', ip_key])
+
+ # Check if commit is ok
+ self.cli_commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(mtu, conf['mtu'])
+ self.assertEqual(interface, conf['ifname'])
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
+ self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(0, conf['linkinfo']['info_data']['ttl'])
+ self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['ikey'])
+ self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['okey'])
+ self.assertEqual(int(idx), conf['linkinfo']['info_data']['erspan_index'])
+ self.assertEqual(1, conf['linkinfo']['info_data']['erspan_ver'])
+ self.assertTrue( conf['linkinfo']['info_data']['iseq'])
+ self.assertTrue( conf['linkinfo']['info_data']['oseq'])
+
+ # Change remote ip address (inc host by 2
+ new_remote = inc_ip(remote_ip4, 2)
+ self.cli_set(self._base_path + [interface, 'remote', new_remote])
+ # Check if commit is ok
+ self.cli_commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote'])
+
+ def test_ip6erspan(self):
+ interface = f'tun1070'
+ encapsulation = 'ip6erspan'
+ ip_key = '77'
+ erspan_ver = '2'
+ direction = 'ingres'
+
+ self.cli_set(self._base_path + [interface, 'encapsulation', encapsulation])
+ self.cli_set(self._base_path + [interface, 'source-address', self.local_v6])
+ self.cli_set(self._base_path + [interface, 'remote', remote_ip6])
+
+ self.cli_set(self._base_path + [interface, 'parameters', 'erspan', 'index', '10'])
+
+ # ERSPAN requires ip key parameter
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_set(self._base_path + [interface, 'parameters', 'ip', 'key', ip_key])
+
+ # Check if commit is ok
+ self.cli_commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(mtu, conf['mtu'])
+ self.assertEqual(interface, conf['ifname'])
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
+ self.assertEqual(self.local_v6, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(remote_ip6, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(0, conf['linkinfo']['info_data']['ttl'])
+ self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['ikey'])
+ self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['okey'])
+ self.assertEqual(1, conf['linkinfo']['info_data']['erspan_ver'])
+ self.assertTrue( conf['linkinfo']['info_data']['iseq'])
+ self.assertTrue( conf['linkinfo']['info_data']['oseq'])
+
+ # Change remote ip address (inc host by 2
+ new_remote = inc_ip(remote_ip6, 2)
+ self.cli_set(self._base_path + [interface, 'remote', new_remote])
+ # Check if commit is ok
+ self.cli_commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote'])
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/interfaces-erspan.py b/src/conf_mode/interfaces-erspan.py
deleted file mode 100755
index 97ae3cf55..000000000
--- a/src/conf_mode/interfaces-erspan.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018-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/>.
-
-import os
-
-from sys import exit
-from copy import deepcopy
-from netifaces import interfaces
-
-from vyos.config import Config
-from vyos.configdict import dict_merge
-from vyos.configdict import get_interface_dict
-from vyos.configdict import node_changed
-from vyos.configdict import leaf_node_changed
-from vyos.configverify import verify_mtu_ipv6
-from vyos.configverify import verify_tunnel
-from vyos.ifconfig import Interface
-from vyos.ifconfig import ERSpanIf
-from vyos.ifconfig import ER6SpanIf
-from vyos.template import is_ipv4
-from vyos.template import is_ipv6
-from vyos.util import dict_search
-from vyos import ConfigError
-from vyos import airbag
-airbag.enable()
-
-def get_config(config=None):
- """
- Retrive CLI config as dictionary. Dictionary can never be empty, as at least
- the interface name will be added or a deleted flag
- """
- if config:
- conf = config
- else:
- conf = Config()
- base = ['interfaces', 'erspan']
- erspan = get_interface_dict(conf, base)
-
- tmp = leaf_node_changed(conf, ['encapsulation'])
- if tmp:
- erspan.update({'encapsulation_changed': {}})
-
- return erspan
-
-def verify(erspan):
- if 'deleted' in erspan:
- return None
-
- if 'encapsulation' not in erspan:
- raise ConfigError('Unable to detect the following ERSPAN tunnel encapsulation'\
- '{ifname}!'.format(**erspan))
-
- verify_mtu_ipv6(erspan)
- verify_tunnel(erspan)
-
- key = dict_search('parameters.ip.key',erspan)
- if key == None:
- raise ConfigError('parameters.ip.key is mandatory for ERSPAN tunnel')
-
-
-def generate(erspan):
- return None
-
-def apply(erspan):
- if 'deleted' in erspan or 'encapsulation_changed' in erspan:
- if erspan['ifname'] in interfaces():
- tmp = Interface(erspan['ifname'])
- tmp.remove()
- if 'deleted' in erspan:
- return None
-
- dispatch = {
- 'erspan': ERSpanIf,
- 'ip6erspan': ER6SpanIf
- }
-
- # We need to re-map the tunnel encapsulation proto to a valid interface class
- encap = erspan['encapsulation']
- klass = dispatch[encap]
-
- erspan_tunnel = klass(**erspan)
- erspan_tunnel.change_options()
- erspan_tunnel.update(erspan)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- generate(c)
- verify(c)
- apply(c)
- except ConfigError as e:
- print(e)
- exit(1)
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index cab94a5b0..4e6c8a9ab 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -61,6 +61,9 @@ def get_config(config=None):
nhrp = conf.get_config_dict([], key_mangling=('-', '_'), get_first_key=True)
if nhrp: tunnel.update({'nhrp' : list(nhrp.keys())})
+ if 'encapsulation' in tunnel and tunnel['encapsulation'] not in ['erspan', 'ip6erspan']:
+ del tunnel['parameters']['erspan']
+
return tunnel
def verify(tunnel):
@@ -72,14 +75,28 @@ def verify(tunnel):
return None
- if 'encapsulation' not in tunnel:
- error = 'Must configure encapsulation for "{ifname}"!'
- raise ConfigError(error.format(**tunnel))
+ verify_tunnel(tunnel)
+
+ if tunnel['encapsulation'] in ['erspan', 'ip6erspan']:
+ if dict_search('parameters.ip.key', tunnel) == None:
+ raise ConfigError('ERSPAN requires ip key parameter!')
+
+ # this is a default field
+ ver = int(tunnel['parameters']['erspan']['version'])
+ if ver == 1:
+ if 'hw_id' in tunnel['parameters']['erspan']:
+ raise ConfigError('ERSPAN version 1 does not support hw-id!')
+ if 'direction' in tunnel['parameters']['erspan']:
+ raise ConfigError('ERSPAN version 1 does not support direction!')
+ elif ver == 2:
+ if 'idx' in tunnel['parameters']['erspan']:
+ raise ConfigError('ERSPAN version 2 does not index parameter!')
+ if 'direction' not in tunnel['parameters']['erspan']:
+ raise ConfigError('ERSPAN version 2 requires direction to be set!')
verify_mtu_ipv6(tunnel)
verify_address(tunnel)
verify_vrf(tunnel)
- verify_tunnel(tunnel)
if 'source_interface' in tunnel:
verify_interface_exists(tunnel['source_interface'])
@@ -92,7 +109,6 @@ def verify(tunnel):
if tunnel['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
raise ConfigError('Can not disable PMTU discovery for given encapsulation')
-
def generate(tunnel):
return None
@@ -108,8 +124,8 @@ def apply(tunnel):
encap = dict_search('linkinfo.info_kind', tmp)
remote = dict_search('linkinfo.info_data.remote', tmp)
- if ('deleted' in tunnel or 'encapsulation_changed' in tunnel or
- encap in ['gretap', 'ip6gretap'] or remote in ['any']):
+ if ('deleted' in tunnel or 'encapsulation_changed' in tunnel or encap in
+ ['gretap', 'ip6gretap', 'erspan', 'ip6erspan'] or remote in ['any']):
if interface in interfaces():
tmp = Interface(interface)
tmp.remove()