summaryrefslogtreecommitdiff
path: root/python/vyos/ifconfig
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r--python/vyos/ifconfig/__init__.py12
-rw-r--r--python/vyos/ifconfig/bond.py20
-rw-r--r--python/vyos/ifconfig/bridge.py38
-rw-r--r--python/vyos/ifconfig/control.py2
-rw-r--r--python/vyos/ifconfig/dummy.py25
-rwxr-xr-xpython/vyos/ifconfig/erspan.py84
-rw-r--r--python/vyos/ifconfig/ethernet.py19
-rw-r--r--python/vyos/ifconfig/geneve.py56
-rw-r--r--python/vyos/ifconfig/input.py3
-rw-r--r--python/vyos/ifconfig/interface.py77
-rw-r--r--python/vyos/ifconfig/l2tpv3.py55
-rw-r--r--python/vyos/ifconfig/loopback.py20
-rw-r--r--python/vyos/ifconfig/macsec.py36
-rw-r--r--python/vyos/ifconfig/macvlan.py38
-rw-r--r--python/vyos/ifconfig/pppoe.py41
-rw-r--r--python/vyos/ifconfig/tunnel.py285
-rw-r--r--python/vyos/ifconfig/vti.py6
-rw-r--r--python/vyos/ifconfig/vtun.py27
-rw-r--r--python/vyos/ifconfig/vxlan.py98
-rw-r--r--python/vyos/ifconfig/wireguard.py29
-rw-r--r--python/vyos/ifconfig/wireless.py37
21 files changed, 257 insertions, 751 deletions
diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py
index f7b55c9dd..9d797d7f1 100644
--- a/python/vyos/ifconfig/__init__.py
+++ b/python/vyos/ifconfig/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -30,15 +30,7 @@ from vyos.ifconfig.vxlan import VXLANIf
from vyos.ifconfig.wireguard import WireGuardIf
from vyos.ifconfig.vtun import VTunIf
from vyos.ifconfig.vti import VTIIf
-from vyos.ifconfig.pppoe import PPPoEIf
-from vyos.ifconfig.tunnel import GREIf
-from vyos.ifconfig.tunnel import GRETapIf
-from vyos.ifconfig.tunnel import IP6GREIf
-from vyos.ifconfig.tunnel import IPIPIf
-from vyos.ifconfig.tunnel import IPIP6If
-from vyos.ifconfig.tunnel import IP6IP6If
-from vyos.ifconfig.tunnel import SitIf
-from vyos.ifconfig.tunnel import Sit6RDIf
+from vyos.ifconfig.tunnel import TunnelIf
from vyos.ifconfig.erspan import ERSpanIf
from vyos.ifconfig.erspan import ER6SpanIf
from vyos.ifconfig.wireless import WiFiIf
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py
index 709222b09..bfa3b0025 100644
--- a/python/vyos/ifconfig/bond.py
+++ b/python/vyos/ifconfig/bond.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -31,9 +31,7 @@ class BondIf(Interface):
monitoring may be performed.
"""
- default = {
- 'type': 'bond',
- }
+ iftype = 'bond'
definition = {
**Interface.definition,
** {
@@ -343,9 +341,6 @@ class BondIf(Interface):
if 'shutdown_required' in config:
self.set_admin_state('down')
- # call base class first
- super().update(config)
-
# ARP monitor targets need to be synchronized between sysfs and CLI.
# Unfortunately an address can't be send twice to sysfs as this will
# result in the following exception: OSError: [Errno 22] Invalid argument.
@@ -404,12 +399,5 @@ class BondIf(Interface):
value = config.get('primary')
if value: self.set_primary(value)
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py
index 1bd617a05..600bd3db8 100644
--- a/python/vyos/ifconfig/bridge.py
+++ b/python/vyos/ifconfig/bridge.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -34,10 +34,7 @@ class BridgeIf(Interface):
The Linux bridge code implements a subset of the ANSI/IEEE 802.1d standard.
"""
-
- default = {
- 'type': 'bridge',
- }
+ iftype = 'bridge'
definition = {
**Interface.definition,
**{
@@ -236,11 +233,6 @@ class BridgeIf(Interface):
interface setup code and provide a single point of entry when workin
on any interface. """
- # call base class first
- super().update(config)
-
- ifname = config['ifname']
-
# Set ageing time
value = config.get('aging')
self.set_ageing_time(value)
@@ -280,24 +272,25 @@ class BridgeIf(Interface):
vlan_filter = '1' if 'enable_vlan' in config else '0'
self.set_vlan_filter(vlan_filter)
+ ifname = config['ifname']
if int(vlan_filter):
add_vlan = []
cur_vlan_ids = get_vlan_ids(ifname)
-
+
tmp = dict_search('vif', config)
if tmp:
for vif, vif_config in tmp.items():
add_vlan.append(vif)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {ifname} vid {vlan} self'
self._cmd(cmd)
-
+
for vlan in add_vlan:
cmd = f'bridge vlan add dev {ifname} vid {vlan} self'
self._cmd(cmd)
-
+
# VLAN of bridge parent interface is always 1
# VLAN 1 is the default VLAN for all unlabeled packets
cmd = f'bridge vlan add dev {ifname} vid 1 pvid untagged self'
@@ -337,7 +330,7 @@ class BridgeIf(Interface):
native_vlan_id = None
allowed_vlan_ids= []
cur_vlan_ids = get_vlan_ids(interface)
-
+
if 'native_vlan' in interface_config:
vlan_id = interface_config['native_vlan']
add_vlan.append(vlan_id)
@@ -353,12 +346,12 @@ class BridgeIf(Interface):
else:
add_vlan.append(vlan)
allowed_vlan_ids.append(vlan)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {interface} vid {vlan} master'
self._cmd(cmd)
-
+
for vlan in allowed_vlan_ids:
cmd = f'bridge vlan add dev {interface} vid {vlan} master'
self._cmd(cmd)
@@ -367,12 +360,5 @@ class BridgeIf(Interface):
cmd = f'bridge vlan add dev {interface} vid {native_vlan_id} pvid untagged master'
self._cmd(cmd)
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py
index 43136f361..d41dfef47 100644
--- a/python/vyos/ifconfig/control.py
+++ b/python/vyos/ifconfig/control.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
diff --git a/python/vyos/ifconfig/dummy.py b/python/vyos/ifconfig/dummy.py
index 19ef9d304..d45769931 100644
--- a/python/vyos/ifconfig/dummy.py
+++ b/python/vyos/ifconfig/dummy.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -23,9 +23,7 @@ class DummyIf(Interface):
packets through without actually transmitting them.
"""
- default = {
- 'type': 'dummy',
- }
+ iftype = 'dummy'
definition = {
**Interface.definition,
**{
@@ -33,22 +31,3 @@ class DummyIf(Interface):
'prefixes': ['dum', ],
},
}
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/erspan.py b/python/vyos/ifconfig/erspan.py
index 50230e14a..03b2acdbf 100755
--- a/python/vyos/ifconfig/erspan.py
+++ b/python/vyos/ifconfig/erspan.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -31,12 +31,7 @@ class _ERSpan(Interface):
"""
_ERSpan: private base class for ERSPAN tunnels
"""
- default = {
- **Interface.default,
- **{
- 'type': 'erspan',
- }
- }
+ iftype = 'erspan'
definition = {
**Interface.definition,
**{
@@ -44,29 +39,14 @@ class _ERSpan(Interface):
'prefixes': ['ersp',],
},
}
-
- options = ['local_ip','remote_ip','encapsulation','parameters']
-
+
def __init__(self,ifname,**config):
self.config = deepcopy(config) if config else {}
super().__init__(ifname, **self.config)
-
+
def change_options(self):
pass
-
- def update(self, config):
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- super().update(config)
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
+
def _create(self):
pass
@@ -74,15 +54,15 @@ class ERSpanIf(_ERSpan):
"""
ERSpanIf: private base class for ERSPAN Over GRE and IPv4 tunnels
"""
-
+
def _create(self):
ifname = self.config['ifname']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ 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 {local_ip} remote {remote_ip} seq key {key} erspan_ver {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:
@@ -94,24 +74,24 @@ class ERSpanIf(_ERSpan):
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']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ 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 {local_ip} remote {remote_ip} seq key {key} erspan_ver {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:
@@ -123,29 +103,29 @@ class ERSpanIf(_ERSpan):
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']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ 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 {local_ip} remote {remote_ip} seq key {key} erspan_ver {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:
@@ -157,24 +137,24 @@ class ER6SpanIf(_ERSpan):
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']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ 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 {local_ip} remote {remote_ip} seq key {key} erspan_ver {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:
@@ -186,5 +166,5 @@ class ER6SpanIf(_ERSpan):
hwid=dict_search('parameters.erspan.hwid',self.config)
if hwid:
command += f' erspan_hwid {hwid}'
-
+
self._cmd(command)
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 547b54b84..b89ca5a5c 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -26,10 +26,7 @@ class EthernetIf(Interface):
"""
Abstraction of a Linux Ethernet Interface
"""
-
- default = {
- 'type': 'ethernet',
- }
+ iftype = 'ethernet'
definition = {
**Interface.definition,
**{
@@ -321,9 +318,6 @@ class EthernetIf(Interface):
interface setup code and provide a single point of entry when workin
on any interface. """
- # call base class first
- super().update(config)
-
# disable ethernet flow control (pause frames)
value = 'off' if 'disable_flow_control' in config else 'on'
self.set_flow_control(value)
@@ -357,12 +351,5 @@ class EthernetIf(Interface):
for b_type in config['ring_buffer']:
self.set_ring_buffer(b_type, config['ring_buffer'][b_type])
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py
index 5c4597be8..7cb3968df 100644
--- a/python/vyos/ifconfig/geneve.py
+++ b/python/vyos/ifconfig/geneve.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -13,7 +13,8 @@
# 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/>.
-from vyos.ifconfig.interface import Interface
+from vyos.ifconfig import Interface
+from vyos.util import dict_search
@Interface.register
class GeneveIf(Interface):
@@ -26,14 +27,7 @@ class GeneveIf(Interface):
https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/#geneve
https://lwn.net/Articles/644938/
"""
-
- default = {
- 'type': 'geneve',
- 'vni': 0,
- 'remote': '',
- }
- options = Interface.options + \
- ['vni', 'remote']
+ iftype = 'geneve'
definition = {
**Interface.definition,
**{
@@ -44,27 +38,27 @@ class GeneveIf(Interface):
}
def _create(self):
- cmd = 'ip link add name {ifname} type geneve id {vni} remote {remote}'.format(**self.config)
- self._cmd(cmd)
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ mapping = {
+ 'parameters.ip.dont_fragment': 'df set',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ }
+
+ cmd = 'ip link add name {ifname} type {type} id {vni} remote {remote}'
+ 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
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+ self._cmd(cmd.format(**self.config))
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/input.py b/python/vyos/ifconfig/input.py
index a6e566d87..db7d2b6b4 100644
--- a/python/vyos/ifconfig/input.py
+++ b/python/vyos/ifconfig/input.py
@@ -17,9 +17,6 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class InputIf(Interface):
- default = {
- 'type': '',
- }
definition = {
**Interface.definition,
**{
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 86529b265..fe6a3c95e 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -60,7 +60,6 @@ class Interface(Control):
options = ['debug', 'create']
required = []
default = {
- 'type': '',
'debug': True,
'create': True,
}
@@ -232,26 +231,21 @@ class Interface(Control):
>>> from vyos.ifconfig import Interface
>>> i = Interface('eth0')
"""
+ self.config = deepcopy(kargs)
+ self.config['ifname'] = self.ifname = ifname
- self.config = deepcopy(self.default)
- for k in self.options:
- if k in kargs:
- self.config[k] = kargs[k]
-
- # make sure the ifname is the first argument and not from the dict
- self.config['ifname'] = ifname
self._admin_state_down_cnt = 0
# we must have updated config before initialising the Interface
super().__init__(**kargs)
- self.ifname = ifname
if not self.exists(ifname):
- # Any instance of Interface, such as Interface('eth0')
- # can be used safely to access the generic function in this class
- # as 'type' is unset, the class can not be created
- if not self.config['type']:
+ # Any instance of Interface, such as Interface('eth0') can be used
+ # safely to access the generic function in this class as 'type' is
+ # unset, the class can not be created
+ if not self.iftype:
raise Exception(f'interface "{ifname}" not found')
+ self.config['type'] = self.iftype
# Should an Instance of a child class (EthernetIf, DummyIf, ..)
# be required, then create should be set to False to not accidentally create it.
@@ -923,12 +917,12 @@ class Interface(Control):
else:
add_vlan.append(vlan)
allowed_vlan_ids.append(vlan)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {ifname} vid {vlan} master'
self._cmd(cmd)
-
+
for vlan in allowed_vlan_ids:
cmd = f'bridge vlan add dev {ifname} vid {vlan} master'
self._cmd(cmd)
@@ -1075,6 +1069,10 @@ class Interface(Control):
interface setup code and provide a single point of entry when workin
on any interface. """
+ if self.debug:
+ import pprint
+ pprint.pprint(config)
+
# Cache the configuration - it will be reused inside e.g. DHCP handler
# XXX: maybe pass the option via __init__ in the future and rename this
# method to apply()?
@@ -1244,6 +1242,16 @@ class Interface(Control):
# configure port mirror
self.set_mirror()
+ # 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()
+ # function. We will only enable the interface if 'up' was called as
+ # often as 'down'. This is required by some interface implementations
+ # as certain parameters can only be changed when the interface is
+ # in admin-down state. This ensures the link does not flap during
+ # reconfiguration.
+ state = 'down' if 'disable' in config else 'up'
+ self.set_admin_state(state)
+
# remove no longer required 802.1ad (Q-in-Q VLANs)
ifname = config['ifname']
for vif_s_id in config.get('vif_s_remove', {}):
@@ -1297,17 +1305,7 @@ class Interface(Control):
class VLANIf(Interface):
""" Specific class which abstracts 802.1q and 802.1ad (Q-in-Q) VLAN interfaces """
- default = {
- 'type': 'vlan',
- 'source_interface': '',
- 'vlan_id': '',
- 'protocol': '',
- 'ingress_qos': '',
- 'egress_qos': '',
- }
-
- options = Interface.options + \
- ['source_interface', 'vlan_id', 'protocol', 'ingress_qos', 'egress_qos']
+ iftype = 'vlan'
def remove(self):
"""
@@ -1336,11 +1334,11 @@ class VLANIf(Interface):
return
cmd = 'ip link add link {source_interface} name {ifname} type vlan id {vlan_id}'
- if self.config['protocol']:
+ if 'protocol' in self.config:
cmd += ' protocol {protocol}'
- if self.config['ingress_qos']:
+ if 'ingress_qos' in self.config:
cmd += ' ingress-qos-map {ingress_qos}'
- if self.config['egress_qos']:
+ if 'egress_qos' in self.config:
cmd += ' egress-qos-map {egress_qos}'
self._cmd(cmd.format(**self.config))
@@ -1372,22 +1370,3 @@ class VLANIf(Interface):
def set_mirror(self):
return
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py
index 8ed3d5afb..7ff0fdd0e 100644
--- a/python/vyos/ifconfig/l2tpv3.py
+++ b/python/vyos/ifconfig/l2tpv3.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -24,19 +24,7 @@ class L2TPv3If(Interface):
either hot standby or load balancing services. Additionally, link integrity
monitoring may be performed.
"""
-
- default = {
- 'type': 'l2tp',
- 'peer_tunnel_id': '',
- 'local_port': 0,
- 'remote_port': 0,
- 'encapsulation': 'udp',
- 'local_address': '',
- 'remote_address': '',
- 'session_id': '',
- 'tunnel_id': '',
- 'peer_session_id': ''
- }
+ iftype = 'l2tp'
definition = {
**Interface.definition,
**{
@@ -45,20 +33,16 @@ class L2TPv3If(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port',
- 'encapsulation', 'local_address', 'remote_address', 'session_id',
- 'peer_session_id']
def _create(self):
# create tunnel interface
cmd = 'ip l2tp add tunnel tunnel_id {tunnel_id}'
cmd += ' peer_tunnel_id {peer_tunnel_id}'
- cmd += ' udp_sport {local_port}'
- cmd += ' udp_dport {remote_port}'
+ cmd += ' udp_sport {source_port}'
+ cmd += ' udp_dport {destination_port}'
cmd += ' encap {encapsulation}'
- cmd += ' local {local_address}'
- cmd += ' remote {remote_address}'
+ cmd += ' local {source_address}'
+ cmd += ' remote {remote}'
self._cmd(cmd.format(**self.config))
# setup session
@@ -82,36 +66,15 @@ class L2TPv3If(Interface):
>>> i.remove()
"""
- if self.exists(self.config['ifname']):
+ if self.exists(self.ifname):
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
- if self.config['tunnel_id'] and self.config['session_id']:
+ if {'tunnel_id', 'session_id'} <= set(self.config):
cmd = 'ip l2tp del session tunnel_id {tunnel_id}'
cmd += ' session_id {session_id}'
self._cmd(cmd.format(**self.config))
- if self.config['tunnel_id']:
+ if 'tunnel_id' in self.config:
cmd = 'ip l2tp del tunnel tunnel_id {tunnel_id}'
self._cmd(cmd.format(**self.config))
-
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py
index 0e632d826..192c12f5c 100644
--- a/python/vyos/ifconfig/loopback.py
+++ b/python/vyos/ifconfig/loopback.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -22,9 +22,8 @@ class LoopbackIf(Interface):
uses to communicate with itself.
"""
_persistent_addresses = ['127.0.0.1/8', '::1/128']
- default = {
- 'type': 'loopback',
- }
+ iftype = 'loopback'
+
definition = {
**Interface.definition,
**{
@@ -33,9 +32,6 @@ class LoopbackIf(Interface):
'bridgeable': True,
}
}
-
- name = 'loopback'
-
def remove(self):
"""
Loopback interface can not be deleted from operating system. We can
@@ -70,13 +66,3 @@ class LoopbackIf(Interface):
# call base class
super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/macsec.py b/python/vyos/ifconfig/macsec.py
index 456686ea6..1a78d18d8 100644
--- a/python/vyos/ifconfig/macsec.py
+++ b/python/vyos/ifconfig/macsec.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-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
@@ -27,12 +27,7 @@ class MACsecIf(Interface):
other security solutions such as IPsec (layer 3) or TLS (layer 4), as all
those solutions are used for their own specific use cases.
"""
-
- default = {
- 'type': 'macsec',
- 'security_cipher': '',
- 'source_interface': ''
- }
+ iftype = 'macsec'
definition = {
**Interface.definition,
**{
@@ -40,8 +35,6 @@ class MACsecIf(Interface):
'prefixes': ['macsec', ],
},
}
- options = Interface.options + \
- ['security_cipher', 'source_interface']
def _create(self):
"""
@@ -49,28 +42,9 @@ class MACsecIf(Interface):
down by default.
"""
# create tunnel interface
- cmd = 'ip link add link {source_interface} {ifname} type {type}'
- cmd += ' cipher {security_cipher}'
- self._cmd(cmd.format(**self.config))
+ cmd = 'ip link add link {source_interface} {ifname} type {type}'.format(**self.config)
+ cmd += f' cipher {self.config["security"]["cipher"]}'
+ self._cmd(cmd)
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py
index 2447fec77..776014bc3 100644
--- a/python/vyos/ifconfig/macvlan.py
+++ b/python/vyos/ifconfig/macvlan.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -20,13 +20,7 @@ class MACVLANIf(Interface):
"""
Abstraction of a Linux MACvlan interface
"""
-
- default = {
- 'type': 'macvlan',
- 'address': '',
- 'source_interface': '',
- 'mode': '',
- }
+ iftype = 'macvlan'
definition = {
**Interface.definition,
**{
@@ -34,39 +28,13 @@ class MACVLANIf(Interface):
'prefixes': ['peth', ],
},
}
- options = Interface.options + \
- ['source_interface', 'mode']
def _create(self):
# please do not change the order when assembling the command
- cmd = 'ip link add {ifname}'
- if self.config['source_interface']:
- cmd += ' link {source_interface}'
- cmd += ' type macvlan'
- if self.config['mode']:
- cmd += ' mode {mode}'
+ cmd = 'ip link add {ifname} link {source_interface} type {type} mode {mode}'
self._cmd(cmd.format(**self.config))
def set_mode(self, mode):
ifname = self.config['ifname']
cmd = f'ip link set dev {ifname} type macvlan mode {mode}'
return self._cmd(cmd)
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py
deleted file mode 100644
index 787245696..000000000
--- a/python/vyos/ifconfig/pppoe.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2020 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/>.
-
-
-from vyos.ifconfig.interface import Interface
-
-
-@Interface.register
-class PPPoEIf(Interface):
- default = {
- 'type': '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/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 4320bf8bc..439d88dbc 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -16,13 +16,12 @@
# https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/
# https://community.hetzner.com/tutorials/linux-setup-gre-tunnel
-from copy import deepcopy
-
from netaddr import EUI
from netaddr import mac_unix_expanded
from random import getrandbits
from vyos.ifconfig.interface import Interface
+from vyos.util import dict_search
from vyos.validate import assert_list
def enable_to_on(value):
@@ -32,11 +31,10 @@ def enable_to_on(value):
return 'off'
raise ValueError(f'expect enable or disable but got "{value}"')
-
@Interface.register
-class _Tunnel(Interface):
+class TunnelIf(Interface):
"""
- _Tunnel: private base class for tunnels
+ Tunnel: private base class for tunnels
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/tunnel.c
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ip6tunnel.c
"""
@@ -48,16 +46,30 @@ class _Tunnel(Interface):
},
}
- default = {
- 'local' : '',
- 'remote': '',
- 'dev' : '',
- 'ttl' : '',
- 'tos' : '',
- 'key' : '',
- 'raw' : '',
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ # - https://man7.org/linux/man-pages/man8/ip-tunnel.8.html
+ mapping = {
+ 'source_address' : 'local',
+ 'source_interface' : 'dev',
+ 'remote' : 'remote',
+ 'parameters.ip.key' : 'key',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ }
+ mapping_ipv4 = {
+ 'parameters.ip.key' : 'key',
+ 'parameters.ip.no_pmtu_discovery' : 'nopmtudisc',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ }
+ mapping_ipv6 = {
+ 'parameters.ipv6.encaplimit' : 'encaplimit',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ 'parameters.ipv6.hoplimit' : 'hoplimit',
+ 'parameters.ipv6.tclass' : 'tclass',
}
- options = Interface.options + list(default.keys())
# TODO: This is surely used for more than tunnels
# TODO: could be refactored elsewhere
@@ -76,28 +88,67 @@ class _Tunnel(Interface):
},
}
}
- _create_cmd = 'ip tunnel add {ifname} mode {type}'
+
+ def __init__(self, ifname, **kargs):
+ self.iftype = kargs['encapsulation']
+ super().__init__(ifname, **kargs)
+
+ # The gretap interface has the possibility to act as L2 bridge
+ if self.iftype in ['gretap', 'ip6gretap']:
+ # no multicast, ttl or tos for gretap
+ self.definition = {
+ **TunnelIf.definition,
+ **{
+ 'bridgeable': True,
+ },
+ }
+
def _create(self):
- # add " option-name option-name-value ..." for all options set
- options = ' '.join(['{} {}'.format(k, self.config[k])
- for k,v in self.config.items() if v and k not in
- ['ifname', 'type', 'raw']])
- if 'raw' in self.config:
- options += ' ' + ' '.join(self.config['raw'])
- self._cmd('{} {}'.format(self._create_cmd.format(**self.config), options))
- self.set_admin_state('down')
+ if self.config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
+ mapping = { **self.mapping, **self.mapping_ipv6 }
+ else:
+ mapping = { **self.mapping, **self.mapping_ipv4 }
+
+ cmd = 'ip tunnel add {ifname} mode {encapsulation}'
+ if self.iftype in ['gretap', 'ip6gretap']:
+ cmd = 'ip link add name {ifname} type {encapsulation}'
+ 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
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
- def change_options(self):
- change = 'ip tunnel change {ifname} mode {type}'
+ self.set_admin_state('down')
- # add " option-name option-name-value ..." for all options set
- options = ' '.join(['{} {}'.format(k, self.config[k])
- for k,v in self.config.items() if v and k not in
- ['ifname', 'type', 'raw']])
- if 'raw' in self.config:
- options += ' ' + ' '.join(self.config['raw'])
- self._cmd('{} {}'.format(change.format(**self.config), options))
+ def _change_options(self):
+ # gretap interfaces do not support changing any parameter
+ if self.iftype in ['gretap', 'ip6gretap']:
+ return
+
+ if self.config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
+ mapping = { **self.mapping, **self.mapping_ipv6 }
+ else:
+ mapping = { **self.mapping, **self.mapping_ipv4 }
+
+ cmd = 'ip tunnel change {ifname} mode {encapsulation}'
+ 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
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
def get_mac(self):
"""
@@ -128,172 +179,8 @@ class _Tunnel(Interface):
get_config_dict(). It's main intention is to consolidate the scattered
interface setup code and provide a single point of entry when workin
on any interface. """
+ # Adjust iproute2 tunnel parameters if necessary
+ self._change_options()
# call base class first
super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
-class GREIf(_Tunnel):
- """
- GRE: Generic Routing Encapsulation
-
- For more information please refer to:
- RFC1701, RFC1702, RFC2784
- https://tools.ietf.org/html/rfc2784
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre.c
- """
-
- default = {
- **_Tunnel.default,
- **{
- 'type': 'gre',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- },
- }
-
-# GreTap also called GRE Bridge
-class GRETapIf(_Tunnel):
- """
- GRETapIF: GreIF using TAP instead of TUN
-
- https://en.wikipedia.org/wiki/TUN/TAP
- """
- # no multicast, ttl or tos for gretap
- definition = {
- **_Tunnel.definition,
- **{
- 'bridgeable': True,
- },
- }
- default = {
- 'type': 'gretap',
- 'local': '',
- 'remote': '',
- 'dev': '',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- }
-
- _create_cmd = 'ip link add name {ifname} type {type}'
-
- def change_options(self):
- pass
-
-class IP6GREIf(_Tunnel):
- """
- IP6Gre: IPv6 Support for Generic Routing Encapsulation (GRE)
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc7676
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre6.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ip6gre',
- 'encaplimit': '',
- 'hoplimit': '',
- 'tclass': '',
- 'flowlabel': '',
- },
- }
-
-class IPIPIf(_Tunnel):
- """
- IPIP: IP Encapsulation within IP
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc2003
- """
- # IPIP does not allow to pass multicast, unlike GRE
- # but the interface itself can be set with multicast
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ipip',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- },
- }
-
-class IPIP6If(_Tunnel):
- """
- IPIP6: IPv4 over IPv6 tunnel
-
- For more information please refer to:
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_ip6tnl.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ipip6',
- 'encaplimit': '',
- 'hoplimit': '',
- 'tclass': '',
- 'flowlabel': '',
- },
- }
-
-class IP6IP6If(IPIP6If):
- """
- IP6IP6: IPv6 over IPv6 tunnel
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc2473
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ip6ip6',
- },
- }
-
-
-class SitIf(_Tunnel):
- """
- Sit: Simple Internet Transition
-
- For more information please refer to:
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_iptnl.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'sit',
- },
- }
-
-class Sit6RDIf(SitIf):
- """
- Sit6RDIf: Simple Internet Transition with 6RD
-
- https://en.wikipedia.org/wiki/IPv6_rapid_deployment
- """
- # TODO: check if key can really be used with 6RD
- default = {
- **_Tunnel.default,
- **{
- 'type': '6rd',
- '6rd_prefix' : '',
- '6rd_relay_prefix' : '',
- },
- }
-
- def _create(self):
- # do not call _Tunnel.create, building fully here
-
- create = 'ip tunnel add {ifname} mode {type} remote {remote}'
- self._cmd(create.format(**self.config))
- self.set_interface('state','down')
-
- set6rd = 'ip tunnel 6rd dev {ifname} 6rd-prefix {6rd-prefix}'
- if '6rd-relay-prefix' in self.config:
- set6rd += ' 6rd-relay-prefix {6rd-relay-prefix}'
- self._cmd(set6rd.format(**self.config))
diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py
index d0745898c..e2090c889 100644
--- a/python/vyos/ifconfig/vti.py
+++ b/python/vyos/ifconfig/vti.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 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
@@ -17,9 +17,7 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class VTIIf(Interface):
- default = {
- 'type': 'vti',
- }
+ iftype = 'vti'
definition = {
**Interface.definition,
**{
diff --git a/python/vyos/ifconfig/vtun.py b/python/vyos/ifconfig/vtun.py
index 99a592b3e..6fb414e56 100644
--- a/python/vyos/ifconfig/vtun.py
+++ b/python/vyos/ifconfig/vtun.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-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
@@ -17,10 +17,7 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class VTunIf(Interface):
- default = {
- 'type': 'vtun',
- 'device_type': 'tun',
- }
+ iftype = 'vtun'
definition = {
**Interface.definition,
**{
@@ -29,7 +26,6 @@ class VTunIf(Interface):
'bridgeable': True,
},
}
- options = Interface.options + ['device_type']
def _create(self):
""" Depending on OpenVPN operation mode the interface is created
@@ -51,22 +47,3 @@ class VTunIf(Interface):
def del_addr(self, addr):
# IP addresses are managed by OpenVPN daemon
pass
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index ad1f605ed..d73fb47b8 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -14,7 +14,8 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from vyos import ConfigError
-from vyos.ifconfig.interface import Interface
+from vyos.ifconfig import Interface
+from vyos.util import dict_search
@Interface.register
class VXLANIf(Interface):
@@ -38,16 +39,7 @@ class VXLANIf(Interface):
https://www.kernel.org/doc/Documentation/networking/vxlan.txt
"""
- default = {
- 'type': 'vxlan',
- 'group': '',
- 'port': 8472, # The Linux implementation of VXLAN pre-dates
- # the IANA's selection of a standard destination port
- 'remote': '',
- 'source_address': '',
- 'source_interface': '',
- 'vni': 0
- }
+ iftype = 'vxlan'
definition = {
**Interface.definition,
**{
@@ -56,60 +48,34 @@ class VXLANIf(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['group', 'remote', 'source_interface', 'port', 'vni', 'source_address']
-
- mapping = {
- 'ifname': 'add',
- 'vni': 'id',
- 'port': 'dstport',
- 'source_address': 'local',
- 'source_interface': 'dev',
- }
def _create(self):
- cmdline = ['ifname', 'type', 'vni', 'port']
-
- if self.config['source_address']:
- cmdline.append('source_address')
-
- if self.config['remote']:
- cmdline.append('remote')
-
- if self.config['group'] or self.config['source_interface']:
- if self.config['group'] and self.config['source_interface']:
- cmdline.append('group')
- cmdline.append('source_interface')
- else:
- ifname = self.config['ifname']
- raise ConfigError(
- f'VXLAN "{ifname}" is missing mandatory underlay multicast'
- 'group or source interface for a multicast network.')
-
- cmd = 'ip link'
- for key in cmdline:
- value = self.config.get(key, '')
- if not value:
- continue
- cmd += ' {} {}'.format(self.mapping.get(key, key), value)
-
- self._cmd(cmd)
-
- def update(self, config):
- """ General helper function which works on a dictionary retrived by
- get_config_dict(). It's main intention is to consolidate the scattered
- interface setup code and provide a single point of entry when workin
- on any interface. """
-
- # call base class first
- super().update(config)
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ mapping = {
+ 'source_address' : 'local',
+ 'source_interface' : 'dev',
+ 'remote' : 'remote',
+ 'group' : 'group',
+ 'parameters.ip.dont_fragment': 'df set',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ 'parameters.nolearning' : 'nolearning',
+ }
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ cmd = 'ip link add {ifname} type {type} id {vni} dstport {port}'
+ 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
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
+ # interface is always A/D down. It needs to be enabled explicitly
+ self.set_admin_state('down')
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index 9ee798ee8..e5b9c4408 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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
@@ -148,18 +148,7 @@ class WireGuardOperational(Operational):
@Interface.register
class WireGuardIf(Interface):
OperationalClass = WireGuardOperational
-
- default = {
- 'type': 'wireguard',
- 'port': 0,
- 'private_key': None,
- 'pubkey': None,
- 'psk': '',
- 'allowed_ips': [],
- 'fwmark': 0x00,
- 'endpoint': None,
- 'keepalive': 0
- }
+ iftype = 'wireguard'
definition = {
**Interface.definition,
**{
@@ -168,9 +157,6 @@ class WireGuardIf(Interface):
'bridgeable': False,
}
}
- options = Interface.options + \
- ['port', 'private_key', 'pubkey', 'psk',
- 'allowed_ips', 'fwmark', 'endpoint', 'keepalive']
def get_mac(self):
"""
@@ -261,14 +247,3 @@ class WireGuardIf(Interface):
# call base class
super().update(config)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py
index 37703d242..748b6e02d 100644
--- a/python/vyos/ifconfig/wireless.py
+++ b/python/vyos/ifconfig/wireless.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-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
@@ -20,11 +20,7 @@ class WiFiIf(Interface):
"""
Handle WIFI/WLAN interfaces.
"""
-
- default = {
- 'type': 'wifi',
- 'phy': 'phy0'
- }
+ iftype = 'wifi'
definition = {
**Interface.definition,
**{
@@ -33,14 +29,10 @@ class WiFiIf(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['phy', 'op_mode']
-
def _create(self):
# all interfaces will be added in monitor mode
- cmd = 'iw phy {phy} interface add {ifname} type monitor' \
- .format(**self.config)
- self._cmd(cmd)
+ cmd = 'iw phy {physical_device} interface add {ifname} type monitor'
+ self._cmd(cmd.format(**self.config))
# wireless interface is administratively down by default
self.set_admin_state('down')
@@ -71,24 +63,3 @@ class WiFiIf(Interface):
# re-add ourselves to any bridge we might have fallen out of
if bridge_member:
self.add_to_bridge(bridge_member)
-
- # 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()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
-
-@Interface.register
-class WiFiModemIf(WiFiIf):
- definition = {
- **WiFiIf.definition,
- **{
- 'section': 'wirelessmodem',
- 'prefixes': ['wlm', ],
- }
- }