#!/bin/sh . /lib/functions.sh configure() { local proto local peerip local otherpeers local fields=" proto port vid ttl tos mtu macaddr zone rxcsum txcsum srcportmin srcportmax ageing maxaddress learning rsc proxy l2miss l3miss gbp tunlink ipaddr ip6addr " # cleanup old vxmesh and peer entries uci -q delete network.vxmesh0 while uci -q delete network.@vxlan_peer[-1]; do :; done # remove vxmesh0 entry from the client bridge and remove extra whitespaces uci set network.client.ifname="$(uci -q get network.client.ifname | sed s/vxmesh0// | xargs)" # reset dns to authorative uci set dhcp.@dnsmasq[0].authoritative="1" # check if a vxmesh config is available, otherwise quit uci -q get gateway.@vxmesh[0] > /dev/null || return 0 # check if proto is set and probe for the correct peer ip proto="$(uci -q get gateway.@vxmesh[0].proto)" case "$proto" in vxlan6) peerip="$(uci -q get gateway.@gateway[0].peer_ip6)" ;; vxlan) peerip="$(uci -q get gateway.@gateway[0].peer_ip)" ;; *) echo "FATAL: vxmesh: option proto 'vxlan|vxlan6' required!" return 1 ;; esac # vxmesh needs a separate peer ip as the ip on the client interface ip # might be shared over multiple devices [ -z "$peerip" ] && { echo "FATAL: vxmesh: peer_ip|peer_ip6 required!" return 1 } uci -q get gateway.@vxmesh[0].vid > /dev/null || { echo "FATAL: vxmesh: missing vid!" return 1 } # copy main options over uci set network.vxmesh0="interface" for option in $fields; do uci set network.vxmesh0."$option"="$(uci -q get gateway.@vxmesh[0]."$option")" done # exclude peerip from the local router, so packets aren't sent to itself otherpeers=$(uci -q get gateway.@vxmesh[0].peer | xargs -n1 | grep -v -e "$peerip") for peer in $otherpeers; do # create peer sections if ! uci -q batch > /dev/null; then echo "FATAL: vxmesh: error setting up peer!" echo " peer: \"$peer\"" return 1 fi <<- EOF add network vxlan_peer set network.@vxlan_peer[-1].vxlan="vxmesh0" set network.@vxlan_peer[-1].dst="$peer" EOF done # learn routes to other peers only over babel interfaces with sufficient mtu # - according to the rfc, vxlan packets must not be fragmented by a VTEP # - the vxlan tunnel requires an mtu of 1570 when using ipv6 # # -> to avoid sending too large packets over an interface with too small mtu, # don't learn a route to a peer over that interface in the first place babel_filter_mtu() { local config="$1" local otherpeers="$2" local mtu local ifname case $config in babelpeer*) ;; wireguardpeer*) ;; *) return ;; esac config_get mtu "$config" mtu config_get ifname "$config" ifname [ "${mtu:-0}" -ge "1570" ] && return [ -z "${ifname}" ] && { echo "WARNING: could not determine ifname from \"$config\"" return } for peer in $otherpeers; do if ! uci -q batch > /dev/null; then echo "FATAL: error adding babel filter for vxlan peer!" echo " peer: \"$peer\"" echo " interface: \"$ifname\"" return 1 fi <<- EOF add babeld filter set babeld.@filter[-1].type="in" set babeld.@filter[-1].ip="$peer" set babeld.@filter[-1].if="$ifname" set babeld.@filter[-1].addedbyautoconfig="true" set babeld.@filter[-1].action="deny" EOF done } config_load network config_foreach babel_filter_mtu interface "$otherpeers" # with multiple routers in the network, there shouldn't be an authoritative # dhcp server uci set dhcp.@dnsmasq[0].authoritative="0" # add the vxlan interface to the client bridge uci set network.client.ifname="$(uci -q get network.client.ifname) vxmesh0" } apply() { uci commit network uci commit dhcp uci commit babeld } revert() { uci revert network uci revert dhcp uci revert babeld }