diff options
| -rw-r--r-- | interface-definitions/interfaces-virtual-ethernet.xml.in | 36 | ||||
| -rw-r--r-- | python/vyos/ifconfig/__init__.py | 1 | ||||
| -rw-r--r-- | python/vyos/ifconfig/veth.py | 54 | ||||
| -rwxr-xr-x | src/conf_mode/interfaces-virtual-ethernet.py | 97 | 
4 files changed, 188 insertions, 0 deletions
| diff --git a/interface-definitions/interfaces-virtual-ethernet.xml.in b/interface-definitions/interfaces-virtual-ethernet.xml.in new file mode 100644 index 000000000..3b78b3637 --- /dev/null +++ b/interface-definitions/interfaces-virtual-ethernet.xml.in @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<interfaceDefinition> +  <node name="interfaces"> +    <children> +      <tagNode name="virtual-ethernet" owner="${vyos_conf_scripts_dir}/interfaces-virtual-ethernet.py"> +        <properties> +          <help>Virtual Ethernet Interface (veth)</help> +          <priority>300</priority> +          <constraint> +            <regex>veth[0-9]+</regex> +          </constraint> +          <constraintErrorMessage>Virutal Ethernet interface must be named vethN</constraintErrorMessage> +          <valueHelp> +            <format>vethN</format> +            <description>Virtual Ethernet interface name</description> +          </valueHelp> +        </properties> +        <children> +          #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> +          #include <include/interface/description.xml.i> +          #include <include/interface/disable.xml.i> +          #include <include/interface/vrf.xml.i> +          <leafNode name="peer-name"> +            <properties> +              <help>Virtual ethernet peer interface name</help> +              <constraint> +                <regex>veth[0-9]+</regex> +              </constraint> +              <constraintErrorMessage>Virutal Ethernet interface must be named vethN</constraintErrorMessage> +            </properties> +          </leafNode> +        </children> +      </tagNode> +    </children> +  </node> +</interfaceDefinition> diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index a37615c8f..d1ddaa13e 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -36,4 +36,5 @@ from vyos.ifconfig.tunnel import TunnelIf  from vyos.ifconfig.wireless import WiFiIf  from vyos.ifconfig.l2tpv3 import L2TPv3If  from vyos.ifconfig.macsec import MACsecIf +from vyos.ifconfig.veth import VethIf  from vyos.ifconfig.wwan import WWANIf diff --git a/python/vyos/ifconfig/veth.py b/python/vyos/ifconfig/veth.py new file mode 100644 index 000000000..aafbf226a --- /dev/null +++ b/python/vyos/ifconfig/veth.py @@ -0,0 +1,54 @@ +# Copyright 2022 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 VethIf(Interface): +    """ +    Abstraction of a Linux veth interface +    """ +    iftype = 'veth' +    definition = { +        **Interface.definition, +        **{ +            'section': 'virtual-ethernet', +            'prefixes': ['veth', ], +            'bridgeable': True, +        }, +    } + +    def _create(self): +        """ +        Create veth interface in OS kernel. Interface is administrative +        down by default. +        """ +        # check before create, as we have 2 veth interfaces in our CLI +        # interface virtual-ethernet veth0 peer-name 'veth1' +        # interface virtual-ethernet veth1 peer-name 'veth0' +        # +        # but iproute2 creates the pair with one command: +        # ip link add vet0 type veth peer name veth1 +        if self.exists(self.config['peer_name']): +            return + +        # create virtual-ethernet interface +        cmd = 'ip link add {ifname} type {type}'.format(**self.config) +        cmd += f' peer name {self.config["peer_name"]}' +        self._cmd(cmd) + +        # interface is always A/D down. It needs to be enabled explicitly +        self.set_admin_state('down') diff --git a/src/conf_mode/interfaces-virtual-ethernet.py b/src/conf_mode/interfaces-virtual-ethernet.py new file mode 100755 index 000000000..91609ded9 --- /dev/null +++ b/src/conf_mode/interfaces-virtual-ethernet.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +from sys import exit + +from netifaces import interfaces +from vyos import ConfigError +from vyos import airbag +from vyos.config import Config +from vyos.configdict import get_interface_dict +from vyos.configverify import verify_address +from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_vrf +from vyos.ifconfig import VethIf + +airbag.enable() + + +def get_config(config=None): +    """ +    Retrive CLI config as dictionary. Dictionary can never be empty, as at +    least the interface name will be added or a deleted flag +    """ +    if config: +        conf = config +    else: +        conf = Config() +    base = ['interfaces', 'virtual-ethernet'] +    ifname, veth = get_interface_dict(conf, base) + +    veth_dict = conf.get_config_dict(base, key_mangling=('-', '_'), +                                     get_first_key=True, +                                     no_tag_node_value_mangle=True) +    veth['config_dict'] = veth_dict + +    return veth + + +def verify(veth): +    if 'deleted' in veth: +        verify_bridge_delete(veth) +        return None + +    verify_vrf(veth) +    verify_address(veth) + +    if 'peer_name' not in veth: +        raise ConfigError( +            f'Remote peer name must be set for \"{veth["ifname"]}\"!') + +    if veth['peer_name'] not in veth['config_dict'].keys(): +        raise ConfigError( +            f'Interface \"{veth["peer_name"]}\" is not configured!') + +    return None + + +def generate(peth): +    return None + + +def apply(veth): +    # Check if the Veth interface already exists +    if 'rebuild_required' in veth or 'deleted' in veth: +        if veth['ifname'] in interfaces(): +            p = VethIf(veth['ifname']) +            p.remove() + +    if 'deleted' not in veth: +        p = VethIf(**veth) +        p.update(veth) + +    return None + + +if __name__ == '__main__': +    try: +        c = get_config() +        verify(c) +        generate(c) +        apply(c) +    except ConfigError as e: +        print(e) +        exit(1) | 
