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 @@ -1,39 +1,40 @@ # 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 # 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.section import Section from vyos.ifconfig.control import Control from vyos.ifconfig.interface import Interface from vyos.ifconfig.operational import Operational from vyos.ifconfig.vrrp import VRRP from vyos.ifconfig.bond import BondIf from vyos.ifconfig.bridge import BridgeIf from vyos.ifconfig.dummy import DummyIf from vyos.ifconfig.ethernet import EthernetIf from vyos.ifconfig.geneve import GeneveIf from vyos.ifconfig.loopback import LoopbackIf from vyos.ifconfig.macvlan import MACVLANIf from vyos.ifconfig.input import InputIf 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 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)