summaryrefslogtreecommitdiff
path: root/python/vyos/ifconfig
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r--python/vyos/ifconfig/__init__.py1
-rw-r--r--python/vyos/ifconfig/bond.py3
-rw-r--r--python/vyos/ifconfig/bridge.py3
-rw-r--r--python/vyos/ifconfig/control.py13
-rw-r--r--python/vyos/ifconfig/dhcp.py194
-rw-r--r--python/vyos/ifconfig/ethernet.py2
-rw-r--r--python/vyos/ifconfig/input.py31
-rw-r--r--python/vyos/ifconfig/interface.py46
-rw-r--r--python/vyos/ifconfig/macvlan.py11
-rw-r--r--python/vyos/ifconfig/section.py (renamed from python/vyos/ifconfig/register.py)72
-rw-r--r--python/vyos/ifconfig/stp.py2
-rw-r--r--python/vyos/ifconfig/tunnel.py16
-rw-r--r--python/vyos/ifconfig/vti.py31
-rw-r--r--python/vyos/ifconfig/vxlan.py25
14 files changed, 255 insertions, 195 deletions
diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py
index 1f9956af0..cd1696ca1 100644
--- a/python/vyos/ifconfig/__init__.py
+++ b/python/vyos/ifconfig/__init__.py
@@ -14,6 +14,7 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+from vyos.ifconfig.section import Section
from vyos.ifconfig.interface import Interface
from vyos.ifconfig.bond import BondIf
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py
index e2ff71490..47dd4ff34 100644
--- a/python/vyos/ifconfig/bond.py
+++ b/python/vyos/ifconfig/bond.py
@@ -18,7 +18,8 @@ import os
from vyos.ifconfig.interface import Interface
from vyos.ifconfig.vlan import VLAN
-from vyos.validate import *
+from vyos.validate import assert_list
+from vyos.validate import assert_positive
@Interface.register
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py
index 94b0075d8..44b92c1db 100644
--- a/python/vyos/ifconfig/bridge.py
+++ b/python/vyos/ifconfig/bridge.py
@@ -16,7 +16,8 @@
from vyos.ifconfig.interface import Interface
-from vyos.validate import *
+from vyos.validate import assert_boolean
+from vyos.validate import assert_positive
@Interface.register
diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py
index c7a2fa2d6..7bb63beed 100644
--- a/python/vyos/ifconfig/control.py
+++ b/python/vyos/ifconfig/control.py
@@ -16,12 +16,13 @@
import os
-from vyos.util import debug, debug_msg
-from vyos.util import popen, cmd
-from vyos.ifconfig.register import Register
+from vyos import debug
+from vyos.util import popen
+from vyos.util import cmd
+from vyos.ifconfig.section import Section
-class Control(Register):
+class Control(Section):
_command_get = {}
_command_set = {}
@@ -35,10 +36,10 @@ class Control(Register):
# if debug is not explicitely disabled the the config, enable it
self.debug = ''
if kargs.get('debug', True):
- self.debug = debug('ifconfig')
+ self.debug = debug.enabled('ifconfig')
def _debug_msg (self, message):
- return debug_msg(message, self.debug)
+ return debug.message(message, self.debug)
def _popen(self, command):
return popen(command, self.debug)
diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py
index 8ec8263b5..d4ff9c2cd 100644
--- a/python/vyos/ifconfig/dhcp.py
+++ b/python/vyos/ifconfig/dhcp.py
@@ -14,105 +14,37 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
-import jinja2
+from vyos.dicts import FixedDict
from vyos.ifconfig.control import Control
+from vyos.template import render
-template_v4 = """
-# generated by ifconfig.py
-option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
-timeout 60;
-retry 300;
-
-interface "{{ intf }}" {
- send host-name "{{ hostname }}";
- {% if client_id -%}
- send dhcp-client-identifier "{{ client_id }}";
- {% endif -%}
- {% if vendor_class_id -%}
- send vendor-class-identifier "{{ vendor_class_id }}";
- {% endif -%}
- request subnet-mask, broadcast-address, routers, domain-name-servers,
- rfc3442-classless-static-routes, domain-name, interface-mtu;
- require subnet-mask;
-}
-
-"""
-
-template_v6 = """
-# generated by ifconfig.py
-interface "{{ intf }}" {
- request routers, domain-name-servers, domain-name;
-}
-
-"""
-
-class DHCP (Control):
+
+class _DHCP (Control):
client_base = r'/var/lib/dhcp/dhclient_'
- def __init__ (self, ifname, **kargs):
+ def __init__(self, ifname, version, **kargs):
super().__init__(**kargs)
-
- # per interface DHCP config files
- self._dhcp = {
- 4: {
- 'ifname': ifname,
- 'conf': self.client_base + ifname + '.conf',
- 'pid': self.client_base + ifname + '.pid',
- 'lease': self.client_base + ifname + '.leases',
- 'options': {
- 'intf': ifname,
- 'hostname': '',
- 'client_id': '',
- 'vendor_class_id': ''
- },
- },
- 6: {
- 'ifname': ifname,
- 'conf': self.client_base + ifname + '.v6conf',
- 'pid': self.client_base + ifname + '.v6pid',
- 'lease': self.client_base + ifname + '.v6leases',
- 'accept_ra': f'/proc/sys/net/ipv6/conf/{ifname}/accept_ra',
- 'options': {
- 'intf': ifname,
- 'dhcpv6_prm_only': False,
- 'dhcpv6_temporary': False
- },
- },
+ 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',
}
- def get_dhcp_options(self):
- """
- Return dictionary with supported DHCP options.
-
- Dictionary should be altered and send back via set_dhcp_options()
- so those options are applied when DHCP is run.
- """
- return self._dhcp[4]['options']
-
- def set_dhcp_options(self, options):
- """
- Store new DHCP options used by next run of DHCP client.
- """
- self._dhcp[4]['options'] = options
-
- def get_dhcpv6_options(self):
- """
- Return dictionary with supported DHCPv6 options.
-
- Dictionary should be altered and send back via set_dhcp_options()
- so those options are applied when DHCP is run.
- """
- return self._dhcp[6]['options']
-
- def set_dhcpv6_options(self, options):
- """
- Store new DHCP options used by next run of DHCP client.
- """
- self._dhcp[6]['options'] = options
+class _DHCPv4 (_DHCP):
+ def __init__(self, ifname):
+ super().__init__(ifname, '')
+ self.options = FixedDict(**{
+ 'ifname': ifname,
+ 'hostname': '',
+ 'client_id': '',
+ 'vendor_class_id': ''
+ })
# replace dhcpv4/v6 with systemd.networkd?
- def _set_dhcp(self):
+ def set(self):
"""
Configure interface as DHCP client. The dhclient binary is automatically
started in background!
@@ -121,21 +53,16 @@ class DHCP (Control):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.set_dhcp()
+ >>> j.dhcp.v4.set()
"""
- dhcp = self.get_dhcp_options()
- if not dhcp['hostname']:
+ if not self.options['hostname']:
# read configured system hostname.
# maybe change to vyos hostd client ???
with open('/etc/hostname', 'r') as f:
- dhcp['hostname'] = f.read().rstrip('\n')
+ self.options['hostname'] = f.read().rstrip('\n')
- # render DHCP configuration
- tmpl = jinja2.Template(template_v4)
- dhcp_text = tmpl.render(dhcp)
- with open(self._dhcp[4]['conf'], 'w') as f:
- f.write(dhcp_text)
+ render(self.file['conf'], 'dhcp-client/ipv4.tmpl' ,self.options)
cmd = 'start-stop-daemon'
cmd += ' --start'
@@ -146,9 +73,9 @@ class DHCP (Control):
cmd += ' --'
# now pass arguments to dhclient binary
cmd += ' -4 -nw -cf {conf} -pf {pid} -lf {lease} {ifname}'
- return self._cmd(cmd.format(**self._dhcp[4]))
+ return self._cmd(cmd.format(**self.file))
- def _del_dhcp(self):
+ def delete(self):
"""
De-configure interface as DHCP clinet. All auto generated files like
pid, config and lease will be removed.
@@ -157,14 +84,14 @@ class DHCP (Control):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.del_dhcp()
+ >>> j.dhcp.v4.delete()
"""
- if not os.path.isfile(self._dhcp[4]['pid']):
+ if not os.path.isfile(self.file['pid']):
self._debug_msg('No DHCP client PID found')
return None
- # with open(self._dhcp[4]['pid'], 'r') as f:
- # pid = int(f.read())
+ # 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:
@@ -178,14 +105,27 @@ class DHCP (Control):
# Hostname Option 12, length 10: "vyos"
#
cmd = '/sbin/dhclient -cf {conf} -pf {pid} -lf {lease} -r {ifname}'
- self._cmd(cmd.format(**self._dhcp[4]))
+ self._cmd(cmd.format(**self.file))
# cleanup old config files
for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self._dhcp[4][name]):
- os.remove(self._dhcp[4][name])
+ if os.path.isfile(self.file[name]):
+ os.remove(self.file[name])
+
- def _set_dhcpv6(self):
+class _DHCPv6 (_DHCP):
+ def __init__(self, ifname):
+ super().__init__(ifname, 'v6')
+ self.options = FixedDict(**{
+ 'ifname': ifname,
+ 'dhcpv6_prm_only': False,
+ 'dhcpv6_temporary': False,
+ })
+ self.file.update({
+ 'accept_ra': f'/proc/sys/net/ipv6/conf/{ifname}/accept_ra',
+ })
+
+ def set(self):
"""
Configure interface as DHCPv6 client. The dhclient binary is automatically
started in background!
@@ -196,22 +136,17 @@ class DHCP (Control):
>>> j = Interface('eth0')
>>> j.set_dhcpv6()
"""
- dhcpv6 = self.get_dhcpv6_options()
# better save then sorry .. should be checked in interface script
# but if you missed it we are safe!
- if dhcpv6['dhcpv6_prm_only'] and dhcpv6['dhcpv6_temporary']:
+ if self.options['dhcpv6_prm_only'] and self.options['dhcpv6_temporary']:
raise Exception(
'DHCPv6 temporary and parameters-only options are mutually exclusive!')
- # render DHCP configuration
- tmpl = jinja2.Template(template_v6)
- dhcpv6_text = tmpl.render(dhcpv6)
- with open(self._dhcp[6]['conf'], 'w') as f:
- f.write(dhcpv6_text)
+ render(self.file['conf'], 'dhcp-client/ipv6.tmpl', self.options)
# no longer accept router announcements on this interface
- self._write_sysfs(self._dhcp[6]['accept_ra'], 0)
+ self._write_sysfs(self.file['accept_ra'], 0)
# assemble command-line to start DHCPv6 client (dhclient)
cmd = 'start-stop-daemon'
@@ -224,15 +159,15 @@ class DHCP (Control):
# now pass arguments to dhclient binary
cmd += ' -6 -nw -cf {conf} -pf {pid} -lf {lease}'
# add optional arguments
- if dhcpv6['dhcpv6_prm_only']:
+ if self.options['dhcpv6_prm_only']:
cmd += ' -S'
- if dhcpv6['dhcpv6_temporary']:
+ if self.options['dhcpv6_temporary']:
cmd += ' -T'
cmd += ' {ifname}'
- return self._cmd(cmd.format(**self._dhcp[6]))
+ return self._cmd(cmd.format(**self.file))
- def _del_dhcpv6(self):
+ def delete(self):
"""
De-configure interface as DHCPv6 clinet. All auto generated files like
pid, config and lease will be removed.
@@ -243,12 +178,12 @@ class DHCP (Control):
>>> j = Interface('eth0')
>>> j.del_dhcpv6()
"""
- if not os.path.isfile(self._dhcp[6]['pid']):
+ if not os.path.isfile(self.file['pid']):
self._debug_msg('No DHCPv6 client PID found')
return None
- # with open(self._dhcp[6]['pid'], 'r') as f:
- # pid = int(f.read())
+ # with open(self.file['pid'], 'r') as f:
+ # pid = int(f.read())
# stop dhclient
cmd = 'start-stop-daemon'
@@ -256,13 +191,18 @@ class DHCP (Control):
cmd += ' --oknodo'
cmd += ' --quiet'
cmd += ' --pidfile {pid}'
- self._cmd(cmd.format(**self._dhcp[6]))
+ self._cmd(cmd.format(**self.file))
# accept router announcements on this interface
- self._write_sysfs(self._dhcp[6]['accept_ra'], 1)
+ self._write_sysfs(self.options['accept_ra'], 1)
# cleanup old config files
for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self._dhcp[6][name]):
- os.remove(self._dhcp[6][name])
+ if os.path.isfile(self.file[name]):
+ os.remove(self.file[name])
+
+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 291b326bf..542de4f59 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -18,8 +18,8 @@ import re
from vyos.ifconfig.interface import Interface
from vyos.ifconfig.vlan import VLAN
+from vyos.validate import assert_list
from vyos.util import run
-from vyos.validate import *
@Interface.register
diff --git a/python/vyos/ifconfig/input.py b/python/vyos/ifconfig/input.py
new file mode 100644
index 000000000..bfab36335
--- /dev/null
+++ b/python/vyos/ifconfig/input.py
@@ -0,0 +1,31 @@
+# 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 InputIf(Interface):
+ default = {
+ 'type': '',
+ }
+ definition = {
+ **Interface.definition,
+ **{
+ 'section': 'input',
+ 'prefixes': ['ifb', ],
+ },
+ }
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 96057a943..43f823eca 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -18,23 +18,33 @@ import re
import json
import glob
import time
+from time import sleep
+from os.path import isfile
from copy import deepcopy
+from datetime import timedelta
-from vyos.validate import * # should not * include
-from vyos.util import mac2eui64
-from vyos import ConfigError
-
+from hurry.filesize import size, alternative
from ipaddress import IPv4Network, IPv6Address, IPv6Network
from netifaces import ifaddresses, AF_INET, AF_INET6
-from time import sleep
-from os.path import isfile
from tabulate import tabulate
-from hurry.filesize import size,alternative
-from datetime import timedelta
+from vyos.util import mac2eui64
+from vyos import ConfigError
from vyos.ifconfig.dhcp import DHCP
+from vyos.validate import is_ipv4
+from vyos.validate import is_ipv6
+from vyos.validate import is_intf_addr_assigned
+from vyos.validate import assert_boolean
+from vyos.validate import assert_list
+from vyos.validate import assert_mac
+from vyos.validate import assert_mtu
+from vyos.validate import assert_positive
+from vyos.validate import assert_range
+
+from vyos.ifconfig.control import Control
+
-class Interface(DHCP):
+class Interface(Control):
options = []
required = []
default = {
@@ -173,7 +183,8 @@ class Interface(DHCP):
self.config['ifname'] = ifname
# we must have updated config before initialising the Interface
- super().__init__(ifname, **kargs)
+ super().__init__(**kargs)
+ self.dhcp = DHCP(ifname)
if not os.path.exists('/sys/class/net/{}'.format(self.config['ifname'])):
# Any instance of Interface, such as Interface('eth0')
@@ -216,8 +227,8 @@ class Interface(DHCP):
>>> i.remove()
"""
# stop DHCP(v6) if running
- self._del_dhcp()
- self._del_dhcpv6()
+ 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
@@ -660,12 +671,13 @@ class Interface(DHCP):
# 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")
+ raise ConfigError(
+ "Can't configure both static IPv4 and DHCP address on the same interface")
if addr == 'dhcp':
- self._set_dhcp()
+ self.dhcp.v4.set()
elif addr == 'dhcpv6':
- self._set_dhcpv6()
+ 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'])
@@ -694,9 +706,9 @@ class Interface(DHCP):
['2001:db8::ffff/64']
"""
if addr == 'dhcp':
- self._del_dhcp()
+ self.dhcp.v4.delete()
elif addr == 'dhcpv6':
- self._del_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'])
diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py
index 4e4b563a1..55b1a3e91 100644
--- a/python/vyos/ifconfig/macvlan.py
+++ b/python/vyos/ifconfig/macvlan.py
@@ -35,10 +35,10 @@ class MACVLANIf(Interface):
'prefixes': ['peth', ],
},
}
- options = Interface.options + ['link', 'mode']
+ options = Interface.options + ['source_interface', 'mode']
def _create(self):
- cmd = 'ip link add {ifname} link {link} type macvlan mode {mode}'.format(
+ cmd = 'ip link add {ifname} link {source_interface} type macvlan mode {mode}'.format(
**self.config)
self._cmd(cmd)
@@ -54,7 +54,7 @@ class MACVLANIf(Interface):
"""
config = {
'address': '',
- 'link': 0,
+ 'source_interface': '',
'mode': ''
}
return config
@@ -62,7 +62,6 @@ class MACVLANIf(Interface):
def set_mode(self, mode):
"""
"""
-
- cmd = 'ip link set dev {} type macvlan mode {}'.format(
- self.config['ifname'], mode)
+ ifname = self.config['ifname']
+ cmd = f'ip link set dev {ifname} type macvlan mode {mode}'
return self._cmd(cmd)
diff --git a/python/vyos/ifconfig/register.py b/python/vyos/ifconfig/section.py
index c90782b70..ab340d247 100644
--- a/python/vyos/ifconfig/register.py
+++ b/python/vyos/ifconfig/section.py
@@ -16,9 +16,10 @@
import netifaces
-class Register:
+class Section:
# the known interface prefixes
_prefixes = {}
+ _classes = []
# class need to define: definition['prefixes']
# the interface prefixes declared by a class used to name interface with
@@ -26,9 +27,16 @@ class Register:
@classmethod
def register(cls, klass):
+ """
+ A function to use as decorator the interfaces classes
+ It register the prefix for the interface (eth, dum, vxlan, ...)
+ with the class which can handle it (EthernetIf, DummyIf,VXLANIf, ...)
+ """
if not klass.definition.get('prefixes',[]):
raise RuntimeError(f'valid interface prefixes not defined for {klass.__name__}')
+ cls._classes.append(klass)
+
for ifprefix in klass.definition['prefixes']:
if ifprefix in cls._prefixes:
raise RuntimeError(f'only one class can be registered for prefix "{ifprefix}" type')
@@ -38,7 +46,11 @@ class Register:
@classmethod
def _basename (cls, name, vlan):
- # remove number from interface name
+ """
+ remove the number at the end of interface name
+ name: name of the interface
+ vlan: if vlan is True, do not stop at the vlan number
+ """
name = name.rstrip('0123456789')
name = name.rstrip('.')
if vlan:
@@ -47,15 +59,13 @@ class Register:
@classmethod
def section(cls, name, vlan=True):
- # return the name of a section an interface should be under
+ """
+ return the name of a section an interface should be under
+ name: name of the interface (eth0, dum1, ...)
+ vlan: should we try try to remove the VLAN from the number
+ """
name = cls._basename(name, vlan)
- # XXX: To leave as long as vti and input are not moved to vyos
- if name == 'vti':
- return 'vti'
- if name == 'ifb':
- return 'input'
-
if name in cls._prefixes:
return cls._prefixes[name].definition['section']
return ''
@@ -68,15 +78,13 @@ class Register:
raise ValueError(f'No type found for interface name: {name}')
@classmethod
- def _listing (cls,section=''):
+ def _intf_under_section (cls,section=''):
+ """
+ return a generator with the name of the interface which are under a section
+ """
interfaces = netifaces.interfaces()
for ifname in interfaces:
- # XXX: Temporary hack as vti and input are not yet moved from vyatta to vyos
- if ifname.startswith('vti') or ifname.startswith('input'):
- yield ifname
- continue
-
ifsection = cls.section(ifname)
if not ifsection:
continue
@@ -87,9 +95,37 @@ class Register:
yield ifname
@classmethod
- def listing(cls, section=''):
- return list(cls._listing(section))
+ def interfaces(cls, section=''):
+ """
+ return a list of the name of the interface which are under a section
+ if no section is provided, then it returns all configured interfaces
+ """
+ return list(cls._intf_under_section(section))
+ @classmethod
+ def _intf_with_feature(cls, feature=''):
+ """
+ return a generator with the name of the interface which have
+ a particular feature set in their definition such as:
+ bondable, broadcast, bridgeable, ...
+ """
+ for klass in cls._classes:
+ if klass.definition[feature]:
+ yield klass.definition['section']
-# XXX: TODO - limit name for VRF interfaces
+ @classmethod
+ def feature(cls, feature=''):
+ """
+ return list with the name of the interface which have
+ a particular feature set in their definition such as:
+ bondable, broadcast, bridgeable, ...
+ """
+ return list(cls._intf_with_feature(feature))
+ @classmethod
+ def reserved(cls):
+ """
+ return list with the interface name prefixes
+ eth, lo, vxlan, dum, ...
+ """
+ return list(cls._prefixes.keys())
diff --git a/python/vyos/ifconfig/stp.py b/python/vyos/ifconfig/stp.py
index 97a3c1ff3..5e83206c2 100644
--- a/python/vyos/ifconfig/stp.py
+++ b/python/vyos/ifconfig/stp.py
@@ -16,7 +16,7 @@
from vyos.ifconfig.interface import Interface
-from vyos.validate import *
+from vyos.validate import assert_positive
class STP:
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 1bbb9eb6a..009a53a82 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -31,7 +31,7 @@ def enable_to_on(value):
raise ValueError(f'expect enable or disable but got "{value}"')
-
+@Interface.register
class _Tunnel(Interface):
"""
_Tunnel: private base class for tunnels
@@ -143,7 +143,7 @@ class GREIf(_Tunnel):
options = ['local', 'remote', 'ttl', 'tos', 'key']
updates = ['local', 'remote', 'ttl', 'tos',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname}'
@@ -167,7 +167,7 @@ class GRETapIf(_Tunnel):
required = ['local', ]
options = ['local', 'remote', ]
- updates = []
+ updates = ['mtu', ]
create = 'ip link add {ifname} type {type}'
change = ''
@@ -193,7 +193,7 @@ class IP6GREIf(_Tunnel):
'hoplimit', 'tclass', 'flowlabel']
updates = ['local', 'remote', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname} mode {type}'
@@ -227,7 +227,7 @@ class IPIPIf(_Tunnel):
options = ['local', 'remote', 'ttl', 'tos', 'key']
updates = ['local', 'remote', 'ttl', 'tos',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname}'
@@ -252,7 +252,7 @@ class IPIP6If(_Tunnel):
'hoplimit', 'tclass', 'flowlabel']
updates = ['local', 'remote', 'encaplimit',
'hoplimit', 'tclass', 'flowlabel',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
create = 'ip -6 tunnel add {ifname} mode {type}'
change = 'ip -6 tunnel cha {ifname}'
@@ -288,7 +288,7 @@ class SitIf(_Tunnel):
options = ['local', 'remote', 'ttl', 'tos', 'key']
updates = ['local', 'remote', 'ttl', 'tos',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
create = 'ip tunnel add {ifname} mode {type}'
change = 'ip tunnel cha {ifname}'
@@ -309,7 +309,7 @@ class Sit6RDIf(SitIf):
# TODO: check if key can really be used with 6RD
options = ['remote', 'ttl', 'tos', 'key', '6rd-prefix', '6rd-relay-prefix']
updates = ['remote', 'ttl', 'tos',
- 'multicast', 'allmulticast']
+ 'mtu', 'multicast', 'allmulticast']
def _create(self):
# do not call _Tunnel.create, building fully here
diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py
new file mode 100644
index 000000000..56ebe01d1
--- /dev/null
+++ b/python/vyos/ifconfig/vti.py
@@ -0,0 +1,31 @@
+# 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 VTIIf(Interface):
+ default = {
+ 'type': 'vti',
+ }
+ definition = {
+ **Interface.definition,
+ **{
+ 'section': 'vti',
+ 'prefixes': ['vti', ],
+ },
+ }
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index 5678ad62e..f47ae17cc 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -43,12 +43,13 @@ class VXLANIf(Interface):
default = {
'type': 'vxlan',
- 'vni': 0,
- 'dev': '',
'group': '',
- 'remote': '',
'port': 8472, # The Linux implementation of VXLAN pre-dates
# the IANA's selection of a standard destination port
+ 'remote': '',
+ 'src_address': '',
+ 'src_interface': '',
+ 'vni': 0
}
definition = {
**Interface.definition,
@@ -58,24 +59,30 @@ class VXLANIf(Interface):
'bridgeable': True,
}
}
- options = ['group', 'remote', 'dev', 'port', 'vni']
+ options = ['group', 'remote', 'src_interface', 'port', 'vni', 'src_address']
mapping = {
'ifname': 'add',
'vni': 'id',
'port': 'dstport',
+ 'src_address': 'nolearning local',
}
def _create(self):
cmdline = set()
if self.config['remote']:
- cmdline = ('ifname', 'type', 'remote', 'dev', 'vni', 'port')
- elif self.config['group'] and self.config['dev']:
- cmdline = ('ifname', 'type', 'group', 'dev', 'vni', 'port')
+ cmdline = ('ifname', 'type', 'remote', 'src_interface', 'vni', 'port')
+
+ elif self.config['src_address']:
+ cmdline = ('ifname', 'type', 'src_address', 'vni', 'port')
+
+ elif self.config['group'] and self.config['src_interface']:
+ cmdline = ('ifname', 'type', 'group', 'src_interface', 'vni', 'port')
+
else:
- intf = self.config['intf']
+ ifname = self.config['ifname']
raise ConfigError(
- f'VXLAN "{intf}" is missing mandatory underlay interface for a multicast network.')
+ f'VXLAN "{ifname}" is missing mandatory underlay interface for a multicast network.')
cmd = 'ip link'
for key in cmdline: