diff --git a/doc/interfaces-vxlan.scd b/doc/interfaces-vxlan.scd new file mode 100644 index 0000000..81da9c5 --- /dev/null +++ b/doc/interfaces-vxlan.scd @@ -0,0 +1,100 @@ +interfaces-vxlan(5) + +# NAME + +*interfaces-vxlan* - VXLAN extensions for the interfaces(5) file format + +# DESCRIPTION + +Virtual eXtensible LAN (VXLAN) is an overlay network to carry Layer 2 over +an IP network while accommodating a very large number of tenants. It is +defined in RFC 7348. + +Be aware that VXLAN encapsulation adds 50 bytes of overhead to the IP packet +header (inner Ethernet header + VXLAN + UDP + IP). This should be taken into +consideration when setting up overlay networks, particularly on underlay +networks with a conventional 1500 byte MTU. + +The following options set up VXLAN Tunnel EndPoints (VTEP) interfaces with +ifupdown-ng. + +See https://www.kernel.org/doc/Documentation/networking/vxlan.rst and +https://vincent.bernat.ch/en/blog/2017-vxlan-linux for more information. + +# VXLAN-RELATED OPTIONS + +A VXLAN Virtual Tunnel Endpoint (VTEP) interface must an ID set. All +other options are optional. + +*vxlan-id* _VNI ID_ + Denotes the VXLAN Network Identifier (VNI) ID for this interface. + This parameter is required for VTEP interfaces. + +*vxlan-physdev* _interface_ + Specifies the physical ("underlay") device to use for tunnel + endpoint communication. + +*vxlan-local-ip* _address_ + Specifies the source IP address to use in outgoing packets. + For compatiblity with ifupdown2 _vxlan-local-tunnelip_ is an + alias for this parameter. + +*vxlan-remote-ip* _address_ + Specifies the unicast destination IP address to use in outgoing + packets when the destination link layer address is not known in + the VXLAN device forwarding database. This parameter cannot be + specified with the _vxlan-remote-group_ parameter. + For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for + this parameter. + +*vxlan-remote-group* _multicast group_ + Specifies the multicast group IP address to join. This parameter + cannot be specified with the _vxlan-remote-ip_ parameter. + For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for + this parameter. + +*vxlan-learning* _on/off_ + Specifies if unknown source link layer addresses and IP addresses + are entered into the VXLAN device forwarding database. + +*vxlan-ageing* _seconds_ + Specifies the lifetime in seconds of FDB entries learnt by the kernel. + +*vxlan-dstport* _port_ + Specifies the UDP destination port of the remote VXLAN tunnel endpoint. + The default is 4789. + +# EXAMPLES + +A VTEP with multiple peers addressed via a multicast group: + +... +auto vx_v1001_padcty +iface vx_v1001_padcty + vxlan-id 655617 + vxlan-physdev vlan1001 + vxlan-remote-group 225.10.1.1 + # + hwaddress f2:00:c1:01:10:01 + mtu 1560 +... + +Note that the underlay must have an MTU of at least 1610 to +carry the encapsulated packets. + + +A VTEP with one peer (point-to-point configuration): + +... +auto vx_ptp1 +iface vx_ptp1 + vxlan-id 2342 + vxlan-local-ip 192.0.2.42 + vxlan-remote-ip 198.51.100.23 + # + hwaddress f2:00:c1:01:10:01 +... + +# AUTHORS + +Maximilian Wilhelm diff --git a/doc/interfaces.scd b/doc/interfaces.scd index f8ba926..6e01c74 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -110,8 +110,8 @@ the system will only respond to certain keywords by default: *post-up* _command_ Runs _command_ after bringing the interface up. -Additional packages such as *bonding*, *bridge*, *tunnel* and -*vrf* add additional keywords to this vocabulary. +Additional packages such as *bonding*, *bridge*, *tunnel*, *vrf* and +*vxlan* add additional keywords to this vocabulary. # OPTIONS @@ -144,6 +144,10 @@ most common options are: The interface is a VRF. Configuration of VRFs requires the *vrf* package to be installed. +*vxlan* + The interface is a Virtual Extensible LAN (VXLAN) tunnel + endpoint. + # EXAMPLES Configure a bridge interface *br0* with *bond0* attached to it, @@ -174,6 +178,10 @@ iface eth0 use dhcp ``` +# SEE ALSO + +*interfaces-vxlan*(5) + # AUTHORS Ariadne Conill diff --git a/executor-scripts/linux/vxlan b/executor-scripts/linux/vxlan new file mode 100755 index 0000000..67db07b --- /dev/null +++ b/executor-scripts/linux/vxlan @@ -0,0 +1,82 @@ +#!/bin/sh +# +# This executor is responsible for setting up the Virtual Extensible LAN (VXLAN) overlay interfaces. +# +# Fri, 02 Oct 2020 01:10:29 +0200 +# -- Maximilian Wilhelm +# +# Known options for the main interface are: +# +# IF_VXLAN_ID The VXLAN Network Identifier (VNI) +# IF_VXLAN_PHYSDEV Specifies the physical device to use for tunnel endpoint communication +# IF_VXLAN_LOCAL_IP Specifies the source IP address to use in outgoing packets +# IF_VXLAN_REMOTE_IP IP of the remote VTEP endpoint (for ptp mode) +# IF_VXLAN_REMOTE_GROUP Multicast group to use for this VNI (for ptmp mode) +# IF_VXLAN_LEARNING Wether to activate MAC learning on this instance (on/off) +# IF_VXLAN_AGEING Specifies the lifetime in seconds of FDB entries learnt by the kernel +# IF_VXLAN_DSTPORT UDP destination port to communicate to the remote VXLAN tunnel endpoint (default 4789) +# + +set -e + +[ -n "$VERBOSE" ] && set -x + +# No VNI, nuthin' to do for us +if [ ! "${IF_VXLAN_ID}" ]; then + exit 0 +fi + +case "$PHASE" in + depend) + if [ "${IF_VXLAN_PHYSDEV}" ]; then + echo "${IF_VXLAN_PHYSDEV}" + fi + ;; + + create) + if [ -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + + # Input validation + if [ "${IF_VXLAN_REMOTE_IP}" -a "${IF_VXLAN_REMOTE_GROUP}" ]; then + echo "Error on ${IFACE} (vxlan): Only one of 'remote' and 'group' can be given!" >&2 + exit 1 + fi + + # Gather arguments + ARGS="" + [ "${IF_VXLAN_PHYSDEV}" ] && ARGS="${ARGS} dev ${IF_VXLAN_PHYSDEV}" + [ "${IF_VXLAN_LOCAL_IP}" ] && ARGS="${ARGS} local ${IF_VXLAN_LOCAL_IP}" + [ "${IF_VXLAN_REMOTE_IP}" ] && ARGS="${ARGS} remote ${IF_VXLAN_REMOTE_IP}" + [ "${IF_VXLAN_REMOTE_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_REMOTE_GROUP}" + [ "${IF_VXLAN_AGEING}" ] && ARGS="${ARGS} ageing ${IF_VXLAN_AGEING}" + + # Linux uses non-standard default port - WTF? + if [ "${IF_VXLAN_DSTPORT}" ]; then + ARGS="${ARGS} dstport ${IF_VXLAN_DSTPORT}" + else + ARGS="${ARGS} dstport 4789" + fi + + case "${IF_VXLAN_LEARNING}" in + on|yes) + ARGS="${ARGS} learning" + ;; + + off|no) + ARGS="${ARGS} nolearning" + ;; + esac + + ${MOCK} ip link add "${IFACE}" type vxlan id "${IF_VXLAN_ID}" ${ARGS} + ;; + + destroy) + if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + + ${MOCK} ip link del "${IFACE}" + ;; +esac diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 31971aa..fbaaa96 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -88,6 +88,9 @@ static const struct remap_token tokens[] = { {"tx-offload", "ethtool-offload-tx"}, /* ifupdown2 */ {"ufo-offload", "ethtool-offload-ufo"}, /* ifupdown2 */ {"vrf", "vrf-member"}, /* ifupdown2 */ + {"vxlan-local-tunnelip", "vxlan-local-ip"}, /* ifupdown2 */ + {"vxlan-remoteip", "vxlan-remote-ip"}, /* ifupdown2 */ + {"vxlan-svcnodeip", "vxlan-remote-group"}, /* ifupdown2 */ }; static int diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 4e1c304..82b8e78 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -12,3 +12,4 @@ atf_test_program{name='tunnel_test'} atf_test_program{name='gre_test'} atf_test_program{name='wireguard_test'} atf_test_program{name='ethtool_test'} +atf_test_program{name='vxlan_test'} diff --git a/tests/linux/vxlan_test b/tests/linux/vxlan_test new file mode 100755 index 0000000..011a856 --- /dev/null +++ b/tests/linux/vxlan_test @@ -0,0 +1,55 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/vxlan" + +tests_init \ + create_simple \ + create_ucast \ + create_mcast \ + create_physdev \ + create_dstport \ + create_nolearning \ + destroy \ + +create_simple_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 4789' \ + ${EXECUTOR} +} + +create_ucast_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_IP=192.2.0.42 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 remote 192.2.0.42' \ + ${EXECUTOR} +} + +create_mcast_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_GROUP=225.0.8.15 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 group 225.0.8.15' \ + ${EXECUTOR} +} + +create_physdev_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PHYSDEV=eth0 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dev eth0' \ + ${EXECUTOR} +} + +create_dstport_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_DSTPORT=1234 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 1234' \ + ${EXECUTOR} +} + +create_nolearning_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_LEARNING=no + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 4789 nolearning' \ + ${EXECUTOR} +} + +destroy_body() { + export IFACE=vx_foo PHASE=destroy MOCK=echo IF_VXLAN_ID=2342 + atf_check -s exit:0 -o match:'ip link del vx_foo' \ + ${EXECUTOR} +}