diff options
-rw-r--r-- | python/vyos/ifconfig/bond.py | 18 | ||||
-rw-r--r-- | python/vyos/ifconfig/bridge.py | 17 | ||||
-rw-r--r-- | python/vyos/ifconfig/control.py | 4 | ||||
-rw-r--r-- | python/vyos/ifconfig/dummy.py | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 20 | ||||
-rw-r--r-- | python/vyos/ifconfig/geneve.py | 9 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig/l2tpv3.py | 14 | ||||
-rw-r--r-- | python/vyos/ifconfig/loopback.py | 11 | ||||
-rw-r--r-- | python/vyos/ifconfig/macvlan.py | 11 | ||||
-rw-r--r-- | python/vyos/ifconfig/register.py | 96 | ||||
-rw-r--r-- | python/vyos/ifconfig/tunnel.py | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig/vxlan.py | 24 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireguard.py | 14 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireless.py | 26 | ||||
-rw-r--r-- | python/vyos/ifconfig_vlan.py | 2 |
16 files changed, 260 insertions, 30 deletions
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index c9dac891f..af4082f8f 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -21,6 +21,7 @@ from vyos.ifconfig.vlan import VLANIf from vyos.validate import * +@Interface.register class BondIf(VLANIf): """ The Linux bonding driver provides a method for aggregating multiple network @@ -30,6 +31,19 @@ class BondIf(VLANIf): monitoring may be performed. """ + default = { + 'type': 'bond', + } + definition = { + **Interface.definition, + ** { + 'section': 'bonding', + 'prefixes': ['bond', ], + 'broadcast': True, + 'bridgeable': True, + }, + } + _sysfs_set = {**VLANIf._sysfs_set, **{ 'bond_hash_policy': { 'validate': lambda v: assert_list(v, ['layer2', 'layer2+3', 'layer3+4', 'encap2+3', 'encap3+4']), @@ -69,10 +83,6 @@ class BondIf(VLANIf): } }} - default = { - 'type': 'bond', - } - def remove(self): """ Remove interface from operating system. Removing the interface diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index 90c44af13..94b0075d8 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -18,6 +18,8 @@ from vyos.ifconfig.interface import Interface from vyos.validate import * + +@Interface.register class BridgeIf(Interface): """ A bridge is a way to connect two Ethernet segments together in a protocol @@ -28,6 +30,18 @@ class BridgeIf(Interface): The Linux bridge code implements a subset of the ANSI/IEEE 802.1d standard. """ + default = { + 'type': 'bridge', + } + definition = { + **Interface.definition, + **{ + 'section': 'bridge', + 'prefixes': ['br', ], + 'broadcast': True, + }, + } + _sysfs_set = {**Interface._sysfs_set, **{ 'ageing_time': { 'validate': assert_positive, @@ -72,9 +86,6 @@ class BridgeIf(Interface): }, }} - default = { - 'type': 'bridge', - } def set_ageing_time(self, time): """ diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index 89deba40a..28adc80d1 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -17,8 +17,10 @@ import os from subprocess import Popen, PIPE, STDOUT +from vyos.ifconfig.register import Register -class Control: + +class Control(Register): _command_get = {} _command_set = {} diff --git a/python/vyos/ifconfig/dummy.py b/python/vyos/ifconfig/dummy.py index 58b89fe68..404c490c7 100644 --- a/python/vyos/ifconfig/dummy.py +++ b/python/vyos/ifconfig/dummy.py @@ -17,6 +17,7 @@ from vyos.ifconfig.interface import Interface +@Interface.register class DummyIf(Interface): """ A dummy interface is entirely virtual like, for example, the loopback @@ -27,3 +28,10 @@ class DummyIf(Interface): default = { 'type': 'dummy', } + definition = { + **Interface.definition, + **{ + 'section': 'dummy', + 'prefixes': ['dum', ], + }, + } diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 30e3a3bef..606161121 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -17,15 +17,31 @@ import os import re from vyos.ifconfig.vlan import VLANIf +from vyos.ifconfig.interface import Interface from vyos.validate import * +@Interface.register class EthernetIf(VLANIf): """ Abstraction of a Linux Ethernet Interface """ + default = { + 'type': 'ethernet', + } + definition = { + **Interface.definition, + **{ + 'section': 'ethernet', + 'prefixes': ['lan', 'eth', 'eno', 'ens', 'enp', 'enx'], + 'bondable': True, + 'broadcast': True, + 'bridgeable': True, + } + } + _command_set = {**VLANIf._command_set, **{ 'gro': { 'validate': lambda v: assert_list(v, ['on', 'off']), @@ -49,10 +65,6 @@ class EthernetIf(VLANIf): }, }} - default = { - 'type': 'ethernet', - } - def _delete(self): # Ethernet interfaces can not be removed pass diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py index a3b3a4c4a..f27786417 100644 --- a/python/vyos/ifconfig/geneve.py +++ b/python/vyos/ifconfig/geneve.py @@ -18,6 +18,7 @@ from copy import deepcopy from vyos.ifconfig.interface import Interface +@Interface.register class GeneveIf(Interface): """ Geneve: Generic Network Virtualization Encapsulation @@ -34,6 +35,14 @@ class GeneveIf(Interface): 'vni': 0, 'remote': '', } + definition = { + **Interface.definition, + **{ + 'section': 'geneve', + 'prefixes': ['gnv', ], + 'bridgeable': True, + } + } def _create(self): cmd = 'ip link add name {ifname} type geneve id {vni} remote {remote}'.format(**self.config) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index a1f8198c7..1759e3545 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -42,6 +42,14 @@ class Interface(DHCP): default = { 'type': '', } + definition = { + 'section': '', + 'prefixes': [], + 'vlan': False, + 'bondable': False, + 'broadcast': False, + 'bridgeable': False, + } _command_set = { 'state': { diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py index a87535277..fbfab4c6e 100644 --- a/python/vyos/ifconfig/l2tpv3.py +++ b/python/vyos/ifconfig/l2tpv3.py @@ -19,6 +19,7 @@ import os from vyos.ifconfig.interface import Interface +@Interface.register class L2TPv3If(Interface): """ The Linux bonding driver provides a method for aggregating multiple network @@ -28,12 +29,19 @@ class L2TPv3If(Interface): monitoring may be performed. """ - options = Interface.options + \ - ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port', - 'encapsulation', 'local_address', 'remote_address'] default = { 'type': 'l2tp', } + definition = { + **Interface.definition, + **{ + 'section': 'l2tpeth', + 'prefixes': ['l2tpeth', ], + 'bridgeable': True, + } + } + options = Interface.options + \ + ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port', 'encapsulation', 'local_address', 'remote_address'] def _create(self): # create tunnel interface diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 37b8e9e3b..8e4438662 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -17,6 +17,7 @@ from vyos.ifconfig.interface import Interface +@Interface.register class LoopbackIf(Interface): """ The loopback device is a special, virtual network interface that your router @@ -26,6 +27,16 @@ class LoopbackIf(Interface): default = { 'type': 'loopback', } + definition = { + **Interface.definition, + **{ + 'section': 'loopback', + 'prefixes': ['lo', ], + 'bridgeable': True, + } + } + + name = 'loopback' def remove(self): """ diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py index da3beea8b..a1dca5e41 100644 --- a/python/vyos/ifconfig/macvlan.py +++ b/python/vyos/ifconfig/macvlan.py @@ -14,18 +14,27 @@ # License along with this library. If not, see <http://www.gnu.org/licenses/>. +from vyos.ifconfig.interface import Interface from vyos.ifconfig.vlan import VLANIf +@Interface.register class MACVLANIf(VLANIf): """ Abstraction of a Linux MACvlan interface """ - options = VLANIf.options + ['link', 'mode'] default = { 'type': 'macvlan', } + definition = { + **Interface.definition, + **{ + 'section': 'pseudo-ethernet', + 'prefixes': ['peth', ], + }, + } + options = Interface.options + ['link', 'mode'] def _create(self): cmd = 'ip link add {ifname} link {link} type macvlan mode {mode}'.format( diff --git a/python/vyos/ifconfig/register.py b/python/vyos/ifconfig/register.py new file mode 100644 index 000000000..2d4b0d4c0 --- /dev/null +++ b/python/vyos/ifconfig/register.py @@ -0,0 +1,96 @@ +# 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/>. + +import netifaces + + +class Register: + # the known interface prefixes + _prefixes = {} + + # class need to define: definition['prefixes'] + # the interface prefixes declared by a class used to name interface with + # prefix[0-9]*(\.[0-9]+)?(\.[0-9]+)?, such as lo, eth0 or eth0.1.2 + + @classmethod + def register(cls, klass): + if not klass.definition.get('prefixes',[]): + raise RuntimeError(f'valid interface prefixes not defined for {klass.__name__}') + + for ifprefix in klass.definition['prefixes']: + if ifprefix in cls._prefixes: + raise RuntimeError(f'only one class can be registered for prefix "{ifprefix}" type') + cls._prefixes[ifprefix] = klass + + return klass + + @classmethod + def _basename (cls, name, vlan): + # remove number from interface name + name = name.rstrip('0123456789') + name = name.rstrip('.') + if vlan: + name = name.rstrip('0123456789') + return name + + @classmethod + def section(cls, name, vlan=True): + # return the name of a section an interface should be under + 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].defintion['section'] + return '' + + @classmethod + def klass(cls, name, vlan=True): + name = cls._basename(name, vlan) + if name in cls._prefixes: + return cls._prefixes[name] + raise ValueError(f'No type found for interface name: {name}') + + @classmethod + def _listing (cls): + interfaces = netifaces.interfaces() + + for ifname in interfaces: + if '@' in ifname: + # Tunnels: sit0@NONE, gre0@NONE, gretap0@NONE, erspan0@NONE, tunl0@NONE, ip6tnl0@NONE, ip6gre0@NONE + continue + + # 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 + + if not cls.section(ifname): + continue + yield ifname + + @classmethod + def listing(cls, section=''): + if not section: + return list(cls._listing()) + return [_ for _ in cls._listing() if cls._basename(_,False) in self.prefixes] + + +# XXX: TODO - limit name for VRF interfaces + diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py index c82727eee..a49bdd51c 100644 --- a/python/vyos/ifconfig/tunnel.py +++ b/python/vyos/ifconfig/tunnel.py @@ -38,6 +38,14 @@ class _Tunnel(Interface): 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 """ + definition = { + **Interface.definition, + **{ + 'section': 'tunnel', + 'prefixes': ['tun',], + 'bridgeable': True, + }, + } # TODO: This is surely used for more than tunnels # TODO: could be refactored elsewhere diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index 75cdf8957..5678ad62e 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -19,6 +19,7 @@ from vyos import ConfigError from vyos.ifconfig.interface import Interface +@Interface.register class VXLANIf(Interface): """ The VXLAN protocol is a tunnelling protocol designed to solve the @@ -40,14 +41,6 @@ class VXLANIf(Interface): https://www.kernel.org/doc/Documentation/networking/vxlan.txt """ - options = ['group', 'remote', 'dev', 'port', 'vni'] - - mapping = { - 'ifname': 'add', - 'vni': 'id', - 'port': 'dstport', - } - default = { 'type': 'vxlan', 'vni': 0, @@ -57,6 +50,21 @@ class VXLANIf(Interface): 'port': 8472, # The Linux implementation of VXLAN pre-dates # the IANA's selection of a standard destination port } + definition = { + **Interface.definition, + **{ + 'section': 'vxlan', + 'prefixes': ['vxlan', ], + 'bridgeable': True, + } + } + options = ['group', 'remote', 'dev', 'port', 'vni'] + + mapping = { + 'ifname': 'add', + 'vni': 'id', + 'port': 'dstport', + } def _create(self): cmdline = set() diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index 71ee67c98..8cf1ff58c 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -22,10 +22,8 @@ from datetime import timedelta import time from hurry.filesize import size,alternative +@Interface.register class WireGuardIf(Interface): - options = ['port', 'private-key', 'pubkey', 'psk', - 'allowed-ips', 'fwmark', 'endpoint', 'keepalive'] - default = { 'type': 'wireguard', 'port': 0, @@ -37,6 +35,16 @@ class WireGuardIf(Interface): 'endpoint': None, 'keepalive': 0 } + definition = { + **Interface.definition, + **{ + 'section': 'wireguard', + 'prefixes': ['wg', ], + 'bridgeable': True, + } + } + 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 7f507ff6e..f94509c80 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -15,19 +15,29 @@ import os +from vyos.ifconfig.interface import Interface from vyos.ifconfig.vlan import VLANIf + +@Interface.register class WiFiIf(VLANIf): """ Handle WIFI/WLAN interfaces. """ - options = ['phy', 'op_mode'] - default = { 'type': 'wifi', 'phy': 'phy0' } + definition = { + **Interface.definition, + **{ + 'section': 'wireless', + 'prefixes': ['wlan', ], + 'bridgeable': True, + } + } + options = ['phy', 'op_mode'] def _create(self): # all interfaces will be added in monitor mode @@ -54,3 +64,15 @@ class WiFiIf(VLANIf): 'phy': 'phy0' } return config + + + +@Interface.register +class WiFiModemIf(WiFiIf): + definition = { + **WiFiIf.definition, + **{ + 'section': 'wirelessmodem', + 'prefixes': ['wlm', ], + } + } diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index fe94a5af4..245453307 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -23,7 +23,7 @@ def apply_vlan_config(vlan, config): to a VLAN interface """ - if vlan.__class__ != VLANIf: + if not vlan.definition['vlan']: raise TypeError() # get DHCP config dictionary and update values |