summaryrefslogtreecommitdiff
path: root/python/vyos/ifconfig
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r--python/vyos/ifconfig/dhcp.py129
-rw-r--r--python/vyos/ifconfig/ethernet.py5
-rw-r--r--python/vyos/ifconfig/geneve.py2
-rw-r--r--python/vyos/ifconfig/interface.py166
-rw-r--r--python/vyos/ifconfig/macvlan.py47
-rw-r--r--python/vyos/ifconfig/tunnel.py36
-rw-r--r--python/vyos/ifconfig/vlan.py40
-rw-r--r--python/vyos/ifconfig/vrrp.py2
-rw-r--r--python/vyos/ifconfig/vxlan.py3
-rw-r--r--python/vyos/ifconfig/wireguard.py5
-rw-r--r--python/vyos/ifconfig/wireless.py3
11 files changed, 206 insertions, 232 deletions
diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py
index d4ff9c2cd..bf6566c07 100644
--- a/python/vyos/ifconfig/dhcp.py
+++ b/python/vyos/ifconfig/dhcp.py
@@ -19,28 +19,20 @@ from vyos.dicts import FixedDict
from vyos.ifconfig.control import Control
from vyos.template import render
+config_base = r'/var/lib/dhcp/dhclient_'
-class _DHCP (Control):
- client_base = r'/var/lib/dhcp/dhclient_'
-
- def __init__(self, ifname, version, **kargs):
- super().__init__(**kargs)
- self.version = version
- self.file = {
- 'ifname': ifname,
- 'conf': self.client_base + ifname + '.' + version + 'conf',
- 'pid': self.client_base + ifname + '.' + version + 'pid',
- 'lease': self.client_base + ifname + '.' + version + 'leases',
- }
-
-class _DHCPv4 (_DHCP):
+class _DHCPv4 (Control):
def __init__(self, ifname):
- super().__init__(ifname, '')
+ super().__init__()
self.options = FixedDict(**{
'ifname': ifname,
'hostname': '',
'client_id': '',
- 'vendor_class_id': ''
+ 'vendor_class_id': '',
+ 'conf_file': config_base + f'{ifname}.conf',
+ 'options_file': config_base + f'{ifname}.options',
+ 'pid_file': config_base + f'{ifname}.pid',
+ 'lease_file': config_base + f'{ifname}.leases',
})
# replace dhcpv4/v6 with systemd.networkd?
@@ -55,25 +47,16 @@ class _DHCPv4 (_DHCP):
>>> j = Interface('eth0')
>>> j.dhcp.v4.set()
"""
-
if not self.options['hostname']:
# read configured system hostname.
# maybe change to vyos hostd client ???
with open('/etc/hostname', 'r') as f:
self.options['hostname'] = f.read().rstrip('\n')
- render(self.file['conf'], 'dhcp-client/ipv4.tmpl' ,self.options)
+ render(self.options['options_file'], 'dhcp-client/daemon-options.tmpl', self.options)
+ render(self.options['conf_file'], 'dhcp-client/ipv4.tmpl', self.options)
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- cmd += ' --exec /sbin/dhclient'
- cmd += ' --'
- # now pass arguments to dhclient binary
- cmd += ' -4 -nw -cf {conf} -pf {pid} -lf {lease} {ifname}'
- return self._cmd(cmd.format(**self.file))
+ return self._cmd('systemctl restart dhclient@{ifname}.service'.format(**self.options))
def delete(self):
"""
@@ -86,44 +69,29 @@ class _DHCPv4 (_DHCP):
>>> j = Interface('eth0')
>>> j.dhcp.v4.delete()
"""
- if not os.path.isfile(self.file['pid']):
+ if not os.path.isfile(self.options['pid_file']):
self._debug_msg('No DHCP client PID found')
return None
- # with open(self.file['pid'], 'r') as f:
- # pid = int(f.read())
-
- # stop dhclient, we need to call dhclient and tell it should release the
- # aquired IP address. tcpdump tells me:
- # 172.16.35.103.68 > 172.16.35.254.67: [bad udp cksum 0xa0cb -> 0xb943!] BOOTP/DHCP, Request from 00:50:56:9d:11:df, length 300, xid 0x620e6946, Flags [none] (0x0000)
- # Client-IP 172.16.35.103
- # Client-Ethernet-Address 00:50:56:9d:11:df
- # Vendor-rfc1048 Extensions
- # Magic Cookie 0x63825363
- # DHCP-Message Option 53, length 1: Release
- # Server-ID Option 54, length 4: 172.16.35.254
- # Hostname Option 12, length 10: "vyos"
- #
- cmd = '/sbin/dhclient -cf {conf} -pf {pid} -lf {lease} -r {ifname}'
- self._cmd(cmd.format(**self.file))
+ self._cmd('systemctl stop dhclient@{ifname}.service'.format(**self.options))
# cleanup old config files
- for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self.file[name]):
- os.remove(self.file[name])
+ for name in ('conf_file', 'options_file', 'pid_file', 'lease_file'):
+ if os.path.isfile(self.options[name]):
+ os.remove(self.options[name])
-
-class _DHCPv6 (_DHCP):
+class _DHCPv6 (Control):
def __init__(self, ifname):
- super().__init__(ifname, 'v6')
+ super().__init__()
self.options = FixedDict(**{
'ifname': ifname,
+ 'conf_file': config_base + f'v6_{ifname}.conf',
+ 'options_file': config_base + f'v6_{ifname}.options',
+ 'pid_file': config_base + f'v6_{ifname}.pid',
+ 'lease_file': config_base + f'v6_{ifname}.leases',
'dhcpv6_prm_only': False,
'dhcpv6_temporary': False,
})
- self.file.update({
- 'accept_ra': f'/proc/sys/net/ipv6/conf/{ifname}/accept_ra',
- })
def set(self):
"""
@@ -134,7 +102,7 @@ class _DHCPv6 (_DHCP):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.set_dhcpv6()
+ >>> j.dhcp.v6.set()
"""
# better save then sorry .. should be checked in interface script
@@ -143,29 +111,13 @@ class _DHCPv6 (_DHCP):
raise Exception(
'DHCPv6 temporary and parameters-only options are mutually exclusive!')
- render(self.file['conf'], 'dhcp-client/ipv6.tmpl', self.options)
+ render(self.options['options_file'], 'dhcp-client/daemon-options.tmpl', self.options)
+ render(self.options['conf_file'], 'dhcp-client/ipv6.tmpl', self.options)
# no longer accept router announcements on this interface
- self._write_sysfs(self.file['accept_ra'], 0)
-
- # assemble command-line to start DHCPv6 client (dhclient)
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- cmd += ' --exec /sbin/dhclient'
- cmd += ' --'
- # now pass arguments to dhclient binary
- cmd += ' -6 -nw -cf {conf} -pf {pid} -lf {lease}'
- # add optional arguments
- if self.options['dhcpv6_prm_only']:
- cmd += ' -S'
- if self.options['dhcpv6_temporary']:
- cmd += ' -T'
- cmd += ' {ifname}'
-
- return self._cmd(cmd.format(**self.file))
+ self._write_sysfs('/proc/sys/net/ipv6/conf/{ifname}/accept_ra'.format(**self.options), 0)
+
+ return self._cmd('systemctl restart dhclient6@{ifname}.service'.format(**self.options))
def delete(self):
"""
@@ -176,33 +128,24 @@ class _DHCPv6 (_DHCP):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.del_dhcpv6()
+ >>> j.dhcp.v6.delete()
"""
- if not os.path.isfile(self.file['pid']):
+ if not os.path.isfile(self.options['pid_file']):
self._debug_msg('No DHCPv6 client PID found')
return None
- # with open(self.file['pid'], 'r') as f:
- # pid = int(f.read())
-
- # stop dhclient
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- self._cmd(cmd.format(**self.file))
+ self._cmd('systemctl stop dhclient6@{ifname}.service'.format(**self.options))
# accept router announcements on this interface
- self._write_sysfs(self.options['accept_ra'], 1)
+ self._write_sysfs('/proc/sys/net/ipv6/conf/{ifname}/accept_ra'.format(**self.options), 1)
# cleanup old config files
- for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self.file[name]):
- os.remove(self.file[name])
+ for name in ('conf_file', 'options_file', 'pid_file', 'lease_file'):
+ if os.path.isfile(self.options[name]):
+ os.remove(self.options[name])
-class DHCP (object):
+class DHCP(object):
def __init__(self, ifname):
self.v4 = _DHCPv4(ifname)
self.v6 = _DHCPv6(ifname)
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 542de4f59..5b18926c9 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -40,6 +40,7 @@ class EthernetIf(Interface):
'bondable': True,
'broadcast': True,
'bridgeable': True,
+ 'eternal': '(lan|eth|eno|ens|enp|enx)[0-9]+$',
}
}
@@ -76,10 +77,6 @@ class EthernetIf(Interface):
},
}}
- def _delete(self):
- # Ethernet interfaces can not be removed
- pass
-
def get_driver_name(self):
"""
Return the driver name used by NIC. Some NICs don't support all
diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py
index 0c1cdade9..145dc268c 100644
--- a/python/vyos/ifconfig/geneve.py
+++ b/python/vyos/ifconfig/geneve.py
@@ -35,6 +35,8 @@ class GeneveIf(Interface):
'vni': 0,
'remote': '',
}
+ options = Interface.options + \
+ ['vni', 'remote']
definition = {
**Interface.definition,
**{
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 32ce1a80c..de5ca369f 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -14,6 +14,7 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
+import re
import json
from copy import deepcopy
@@ -49,7 +50,7 @@ class Interface(Control):
# WireGuard to modify their display behaviour
OperationalClass = Operational
- options = []
+ options = ['debug', 'create',]
required = []
default = {
'type': '',
@@ -63,6 +64,7 @@ class Interface(Control):
'bondable': False,
'broadcast': False,
'bridgeable': False,
+ 'eternal': '',
}
_command_get = {
@@ -217,7 +219,7 @@ class Interface(Control):
else:
raise Exception('interface "{}" not found'.format(self.config['ifname']))
- # list of assigned IP addresses
+ # temporary list of assigned IP addresses
self._addr = []
self.operational = self.OperationalClass(ifname)
@@ -238,39 +240,21 @@ class Interface(Control):
>>> i = Interface('eth0')
>>> i.remove()
"""
- # stop DHCP(v6) if running
- self.dhcp.v4.delete()
- self.dhcp.v6.delete()
# remove all assigned IP addresses from interface - this is a bit redundant
# as the kernel will remove all addresses on interface deletion, but we
# can not delete ALL interfaces, see below
- for addr in self.get_addr():
- self.del_addr(addr)
+ self.flush_addrs()
# ---------------------------------------------------------------------
- # A code refactoring is required as this type check is present as
- # Interface implement behaviour for one of it's sub-class.
-
- # It is required as the current pattern for vlan is:
- # Interface('name').remove() to delete an interface
- # The code should be modified to have a class method called connect and
- # have Interface.connect('name').remove()
+ # Any class can define an eternal regex in its definition
+ # interface matching the regex will not be deleted
- # each subclass should register within Interface the pattern for that
- # interface ie: (ethX, etc.) and use this to create an instance of
- # the right class (EthernetIf, ...)
-
- # Ethernet interfaces can not be removed
-
- # Commented out as nowhere in the code do we call Interface()
- # This would also cause an import loop
- # if self.__class__ == EthernetIf:
- # return
-
- # ---------------------------------------------------------------------
-
- self._delete()
+ eternal = self.definition['eternal']
+ if not eternal:
+ self._delete()
+ elif not re.match(eternal, self.ifname):
+ self._delete()
def _delete(self):
# NOTE (Improvement):
@@ -431,39 +415,28 @@ class Interface(Control):
"""
return self.set_interface('ipv6_autoconf', autoconf)
- def set_ipv6_eui64_address(self, prefix):
+ def add_ipv6_eui64_address(self, prefix):
"""
Extended Unique Identifier (EUI), as per RFC2373, allows a host to
- assign iteslf a unique IPv6 address based on a given IPv6 prefix.
+ assign itself a unique IPv6 address based on a given IPv6 prefix.
- If prefix is passed address is assigned, if prefix is '' address is
- removed from interface.
+ Calculate the EUI64 from the interface's MAC, then assign it
+ with the given prefix to the interface.
"""
- # if prefix is an empty string convert it to None so mac2eui64 works
- # as expected
- if not prefix:
- prefix = None
eui64 = mac2eui64(self.get_mac(), prefix)
+ prefixlen = prefix.split('/')[1]
+ self.add_addr(f'{eui64}/{prefixlen}')
- if not prefix:
- # if prefix is empty - thus removed - we need to walk through all
- # interface IPv6 addresses and find the one with the calculated
- # EUI-64 identifier. The address is then removed
- for addr in self.get_addr():
- addr_wo_prefix = addr.split('/')[0]
- if is_ipv6(addr_wo_prefix):
- if eui64 in IPv6Address(addr_wo_prefix).exploded:
- self.del_addr(addr)
-
- return None
+ def del_ipv6_eui64_address(self, prefix):
+ """
+ Delete the address based on the interface's MAC-based EUI64
+ combined with the prefix address.
+ """
+ eui64 = mac2eui64(self.get_mac(), prefix)
+ prefixlen = prefix.split('/')[1]
+ self.del_addr(f'{eui64}/{prefixlen}')
- # calculate and add EUI-64 IPv6 address
- if IPv6Network(prefix):
- # we also need to take the subnet length into account
- prefix = prefix.split('/')[1]
- eui64 = f'{eui64}/{prefix}'
- self.add_addr(eui64 )
def set_ipv6_forwarding(self, forwarding):
"""
@@ -644,7 +617,8 @@ class Interface(Control):
def add_addr(self, addr):
"""
Add IP(v6) address to interface. Address is only added if it is not
- already assigned to that interface.
+ already assigned to that interface. Address format must be validated
+ and compressed/normalized before calling this function.
addr: can be an IPv4 address, IPv6 address, dhcp or dhcpv6!
IPv4: add IPv4 address to interface
@@ -652,6 +626,7 @@ class Interface(Control):
dhcp: start dhclient (IPv4) on interface
dhcpv6: start dhclient (IPv6) on interface
+ Returns False if address is already assigned and wasn't re-added.
Example:
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
@@ -660,32 +635,44 @@ class Interface(Control):
>>> j.get_addr()
['192.0.2.1/24', '2001:db8::ffff/64']
"""
+ # XXX: normalize/compress with ipaddress if calling functions don't?
+ # is subnet mask always passed, and in the same way?
- # cache new IP address which is assigned to interface
- self._addr.append(addr)
+ # we can't have both DHCP and static IPv4 addresses assigned
+ for a in self._addr:
+ if ( ( addr == 'dhcp' and a != 'dhcpv6' and is_ipv4(a) ) or
+ ( a == 'dhcp' and addr != 'dhcpv6' and is_ipv4(addr) ) ):
+ raise ConfigError((
+ "Can't configure both static IPv4 and DHCP address "
+ "on the same interface"))
- # we can not have both DHCP and static IPv4 addresses assigned to an interface
- if 'dhcp' in self._addr:
- for addr in self._addr:
- # do not change below 'if' ordering esle you will get an exception as:
- # ValueError: 'dhcp' does not appear to be an IPv4 or IPv6 address
- if addr != 'dhcp' and is_ipv4(addr):
- raise ConfigError(
- "Can't configure both static IPv4 and DHCP address on the same interface")
+ # do not add same address twice
+ if addr in self._addr:
+ return False
+ # add to interface
if addr == 'dhcp':
+ self._addr.append(addr)
self.dhcp.v4.set()
- elif addr == 'dhcpv6':
+ return True
+
+ if addr == 'dhcpv6':
+ self._addr.append(addr)
self.dhcp.v6.set()
- else:
- if not is_intf_addr_assigned(self.config['ifname'], addr):
- cmd = 'ip addr add "{}" dev "{}"'.format(addr, self.config['ifname'])
- return self._cmd(cmd)
+ return True
+
+ if not is_intf_addr_assigned(self.ifname, addr):
+ self._addr.append(addr)
+ self._cmd(f'ip addr add "{addr}" dev "{self.ifname}"')
+ return True
+
+ return False
def del_addr(self, addr):
"""
- Delete IP(v6) address to interface. Address is only added if it is
- assigned to that interface.
+ Delete IP(v6) address from interface. Address is only deleted if it is
+ assigned to that interface. Address format must be exactly the same as
+ was used when adding the address.
addr: can be an IPv4 address, IPv6 address, dhcp or dhcpv6!
IPv4: delete IPv4 address from interface
@@ -693,6 +680,7 @@ class Interface(Control):
dhcp: stop dhclient (IPv4) on interface
dhcpv6: stop dhclient (IPv6) on interface
+ Returns False if address isn't already assigned and wasn't deleted.
Example:
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
@@ -704,11 +692,35 @@ class Interface(Control):
>>> j.get_addr()
['2001:db8::ffff/64']
"""
+
+ # remove from cache (dhcp, and dhcpv6 can not be in it)
+ if addr in self._addr:
+ self._addr.remove(addr)
+
+ # remove from interface
if addr == 'dhcp':
self.dhcp.v4.delete()
- elif addr == 'dhcpv6':
+ return True
+
+ if addr == 'dhcpv6':
self.dhcp.v6.delete()
- else:
- if is_intf_addr_assigned(self.config['ifname'], addr):
- cmd = 'ip addr del "{}" dev "{}"'.format(addr, self.config['ifname'])
- return self._cmd(cmd)
+ return True
+
+ if is_intf_addr_assigned(self.ifname, addr):
+ self._cmd(f'ip addr del "{addr}" dev "{self.ifname}"')
+ return True
+
+ return False
+
+ def flush_addrs(self):
+ """
+ Flush all addresses from an interface, including DHCP.
+
+ Will raise an exception on error.
+ """
+ # stop DHCP(v6) if running
+ self.dhcp.v4.delete()
+ self.dhcp.v6.delete()
+
+ # flush all addresses
+ self._cmd(f'ip addr flush dev "{self.ifname}"')
diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py
index 55b1a3e91..b5481f4a7 100644
--- a/python/vyos/ifconfig/macvlan.py
+++ b/python/vyos/ifconfig/macvlan.py
@@ -13,6 +13,7 @@
# 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 copy import deepcopy
from vyos.ifconfig.interface import Interface
from vyos.ifconfig.vlan import VLAN
@@ -27,6 +28,9 @@ class MACVLANIf(Interface):
default = {
'type': 'macvlan',
+ 'address': '',
+ 'source_interface': '',
+ 'mode': '',
}
definition = {
**Interface.definition,
@@ -35,33 +39,32 @@ class MACVLANIf(Interface):
'prefixes': ['peth', ],
},
}
- options = Interface.options + ['source_interface', 'mode']
+ options = Interface.options + \
+ ['source_interface', 'mode']
def _create(self):
- cmd = 'ip link add {ifname} link {source_interface} type macvlan mode {mode}'.format(
- **self.config)
- self._cmd(cmd)
+ # 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}'
+ self._cmd(cmd.format(**self.config))
- @staticmethod
- def get_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)
+
+ @classmethod
+ def get_config(cls):
"""
- VXLAN interfaces require a configuration when they are added using
- iproute2. This static method will provide the configuration dictionary
- used by this class.
+ MACVLAN interfaces require a configuration when they are added using
+ iproute2. This method will provide the configuration dictionary used
+ by this class.
Example:
>> dict = MACVLANIf().get_config()
"""
- config = {
- 'address': '',
- 'source_interface': '',
- 'mode': ''
- }
- return 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)
+ return deepcopy(cls.default)
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 009a53a82..85c22b5b4 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -43,7 +43,7 @@ class _Tunnel(Interface):
**{
'section': 'tunnel',
'prefixes': ['tun',],
- 'bridgeable': True,
+ 'bridgeable': False,
},
}
@@ -135,14 +135,21 @@ class GREIf(_Tunnel):
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre.c
"""
+ definition = {
+ **_Tunnel.definition,
+ **{
+ 'bridgeable': True,
+ },
+ }
+
ip = [IP4, IP6]
tunnel = IP4
default = {'type': 'gre'}
required = ['local', ] # mGRE is a GRE without remote endpoint
- options = ['local', 'remote', 'ttl', 'tos', 'key']
- updates = ['local', 'remote', 'ttl', 'tos',
+ options = ['local', 'remote', 'dev', 'ttl', 'tos', 'key']
+ updates = ['local', 'remote', 'dev', 'ttl', 'tos',
'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
@@ -160,6 +167,13 @@ class GRETapIf(_Tunnel):
# no multicast, ttl or tos for gretap
+ definition = {
+ **_Tunnel.definition,
+ **{
+ 'bridgeable': True,
+ },
+ }
+
ip = [IP4, ]
tunnel = IP4
@@ -189,9 +203,9 @@ class IP6GREIf(_Tunnel):
default = {'type': 'ip6gre'}
required = ['local', 'remote']
- options = ['local', 'remote', 'encaplimit',
+ options = ['local', 'remote', 'dev', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel']
- updates = ['local', 'remote', 'encaplimit',
+ updates = ['local', 'remote', 'dev', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel',
'mtu', 'multicast', 'allmulticast']
@@ -225,8 +239,8 @@ class IPIPIf(_Tunnel):
default = {'type': 'ipip'}
required = ['local', 'remote']
- options = ['local', 'remote', 'ttl', 'tos', 'key']
- updates = ['local', 'remote', 'ttl', 'tos',
+ options = ['local', 'remote', 'dev', 'ttl', 'tos', 'key']
+ updates = ['local', 'remote', 'dev', 'ttl', 'tos',
'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
@@ -248,9 +262,9 @@ class IPIP6If(_Tunnel):
default = {'type': 'ipip6'}
required = ['local', 'remote']
- options = ['local', 'remote', 'encaplimit',
+ options = ['local', 'remote', 'dev', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel']
- updates = ['local', 'remote', 'encaplimit',
+ updates = ['local', 'remote', 'dev', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel',
'mtu', 'multicast', 'allmulticast']
@@ -286,8 +300,8 @@ class SitIf(_Tunnel):
default = {'type': 'sit'}
required = ['local', 'remote']
- options = ['local', 'remote', 'ttl', 'tos', 'key']
- updates = ['local', 'remote', 'ttl', 'tos',
+ options = ['local', 'remote', 'dev', 'ttl', 'tos', 'key']
+ updates = ['local', 'remote', 'dev', 'ttl', 'tos',
'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
diff --git a/python/vyos/ifconfig/vlan.py b/python/vyos/ifconfig/vlan.py
index 7b1e00d87..d68e8f6cd 100644
--- a/python/vyos/ifconfig/vlan.py
+++ b/python/vyos/ifconfig/vlan.py
@@ -101,26 +101,26 @@ class VLAN:
>>> i.add_vlan(10)
"""
vlan_ifname = self.config['ifname'] + '.' + str(vlan_id)
- if not os.path.exists(f'/sys/class/net/{vlan_ifname}'):
- self._vlan_id = int(vlan_id)
-
- if ethertype:
- self._ethertype = ethertype
- ethertype = 'proto {}'.format(ethertype)
-
- # Optional ingress QOS mapping
- opt_i = ''
- if ingress_qos:
- opt_i = 'ingress-qos-map ' + ingress_qos
- # Optional egress QOS mapping
- opt_e = ''
- if egress_qos:
- opt_e = 'egress-qos-map ' + egress_qos
-
- # create interface in the system
- cmd = 'ip link add link {ifname} name {ifname}.{vlan} type vlan {proto} id {vlan} {opt_e} {opt_i}' \
- .format(ifname=self.config['ifname'], vlan=self._vlan_id, proto=ethertype, opt_e=opt_e, opt_i=opt_i)
- self._cmd(cmd)
+ if os.path.exists(f'/sys/class/net/{vlan_ifname}'):
+ return self.__class__(vlan_ifname)
+
+ if ethertype:
+ self._ethertype = ethertype
+ ethertype = 'proto {}'.format(ethertype)
+
+ # Optional ingress QOS mapping
+ opt_i = ''
+ if ingress_qos:
+ opt_i = 'ingress-qos-map ' + ingress_qos
+ # Optional egress QOS mapping
+ opt_e = ''
+ if egress_qos:
+ opt_e = 'egress-qos-map ' + egress_qos
+
+ # create interface in the system
+ cmd = 'ip link add link {ifname} name {ifname}.{vlan} type vlan {proto} id {vlan} {opt_e} {opt_i}' \
+ .format(ifname=self.ifname, vlan=vlan_id, proto=ethertype, opt_e=opt_e, opt_i=opt_i)
+ self._cmd(cmd)
# return new object mapping to the newly created interface
# we can now work on this object for e.g. IP address setting
diff --git a/python/vyos/ifconfig/vrrp.py b/python/vyos/ifconfig/vrrp.py
index 29b10dd9e..a872725b2 100644
--- a/python/vyos/ifconfig/vrrp.py
+++ b/python/vyos/ifconfig/vrrp.py
@@ -109,7 +109,7 @@ class VRRP(object):
return []
disabled = []
- config = json.loads(util.readfile(cls.location['vyos']))
+ config = json.loads(util.read_file(cls.location['vyos']))
# add disabled groups to the list
for group in config['vrrp_groups']:
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index f47ae17cc..f9f2e38e9 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -59,7 +59,8 @@ class VXLANIf(Interface):
'bridgeable': True,
}
}
- options = ['group', 'remote', 'src_interface', 'port', 'vni', 'src_address']
+ options = Interface.options + \
+ ['group', 'remote', 'src_interface', 'port', 'vni', 'src_address']
mapping = {
'ifname': 'add',
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index ff945c9d0..fdf5d9347 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -165,8 +165,9 @@ class WireGuardIf(Interface):
'bridgeable': True,
}
}
- options = ['port', 'private-key', 'pubkey', 'psk',
- 'allowed-ips', 'fwmark', 'endpoint', 'keepalive']
+ options = Interface.options + \
+ ['port', 'private-key', 'pubkey', 'psk',
+ 'allowed-ips', 'fwmark', 'endpoint', 'keepalive']
"""
Wireguard interface class, contains a comnfig dictionary since
diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py
index 946ae1642..3122ac0a3 100644
--- a/python/vyos/ifconfig/wireless.py
+++ b/python/vyos/ifconfig/wireless.py
@@ -38,7 +38,8 @@ class WiFiIf(Interface):
'bridgeable': True,
}
}
- options = ['phy', 'op_mode']
+ options = Interface.options + \
+ ['phy', 'op_mode']
def _create(self):
# all interfaces will be added in monitor mode