2020-07-28 14:34:20 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
2020-08-26 09:35:18 +00:00
|
|
|
set -e
|
|
|
|
|
2020-07-28 14:34:20 +00:00
|
|
|
# Copyright (C) 2012, 2020 Natanael Copa <ncopa@alpinelinux.org>
|
|
|
|
# Copyright (C) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
2020-09-09 22:48:35 +00:00
|
|
|
# Copyright (C) 2020 Maximilian Wilhelm <max@sdn.clinic>
|
2020-07-28 14:34:20 +00:00
|
|
|
#
|
|
|
|
# Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
|
|
# copyright notice and this permission notice appear in all copies.
|
|
|
|
#
|
|
|
|
# This software is provided 'as is' and without any warranty, express or
|
|
|
|
# implied. In no event shall the authors be liable for any damages arising
|
|
|
|
# from the use of this software.
|
|
|
|
|
|
|
|
all_ports_exist() {
|
|
|
|
local i=
|
|
|
|
for i in "$@"; do
|
|
|
|
[ -d /sys/class/net/$i ] || return 1
|
|
|
|
done
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
wait_ports() {
|
|
|
|
local timeout= waitports=
|
|
|
|
[ -z "$IF_BRIDGE_WAITPORT" ] && return 0
|
|
|
|
set -- $IF_BRIDGE_WAITPORT
|
|
|
|
timeout="$1"
|
|
|
|
shift
|
|
|
|
waitports="$@"
|
|
|
|
[ -z "$waitports" ] && waitports="$PORTS"
|
|
|
|
while ! all_ports_exist $waitports; do
|
|
|
|
[ "$timeout" -eq 0 ] && return 0
|
|
|
|
timeout=$(($timeout - 1))
|
|
|
|
sleep 1
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
all_ports() {
|
|
|
|
local i=
|
|
|
|
for i in /sys/class/net/*/ifindex; do
|
|
|
|
i=${i%/*}
|
|
|
|
i=${i##*/}
|
|
|
|
case "$i" in
|
|
|
|
lo|$IFACE) continue;;
|
|
|
|
*) echo $i;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
add_ports() {
|
|
|
|
local port=
|
|
|
|
for port in $PORTS; do
|
|
|
|
if [ -n "$IF_BRIDGE_HW" ]; then
|
|
|
|
ip link set dev $port addr $IF_BRIDGE_HW
|
|
|
|
fi
|
2020-10-14 19:15:48 +00:00
|
|
|
ip link set dev $port master $IFACE && ip link set dev $port up
|
2020-07-28 14:34:20 +00:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
del_ports() {
|
|
|
|
local port=
|
|
|
|
for port in $PORTS; do
|
|
|
|
ip link set dev $port down
|
2020-10-14 19:15:48 +00:00
|
|
|
ip link set dev $port nomaster
|
2020-07-28 14:34:20 +00:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2020-10-14 19:19:17 +00:00
|
|
|
set_bridge_opts_brctl() {
|
2020-07-28 14:34:20 +00:00
|
|
|
[ -n "$IF_BRIDGE_AGEING" ] \
|
|
|
|
&& brctl setageing $IFACE $IF_BRIDGE_AGEING
|
|
|
|
[ -n "$IF_BRIDGE_BRIDGEPRIO" ] \
|
|
|
|
&& brctl setbridgeprio $IFACE $IF_BRIDGE_BRIDGEPRIO
|
|
|
|
[ -n "$IF_BRIDGE_FD" ] \
|
|
|
|
&& brctl setfd $IFACE $IF_BRIDGE_FD
|
|
|
|
[ -n "$IF_BRIDGE_HELLO" ] \
|
|
|
|
&& brctl sethello $IFACE $IF_BRIDGE_HELLO
|
|
|
|
[ -n "$IF_BRIDGE_MAXAGE" ] \
|
|
|
|
&& brctl setmaxage $IFACE $IF_BRIDGE_MAXAGE
|
|
|
|
[ -n "$IF_BRIDGE_PATHCOST" ] \
|
|
|
|
&& brctl setpathcost $IFACE $IF_BRIDGE_PATHCOST
|
|
|
|
[ -n "$IF_BRIDGE_PORTPRIO" ] \
|
|
|
|
&& brctl setportprio $IFACE $IF_BRIDGE_PORTPRIO
|
|
|
|
[ -n "$IF_BRIDGE_STP" ] \
|
|
|
|
&& brctl stp $IFACE $IF_BRIDGE_STP
|
|
|
|
}
|
|
|
|
|
2020-10-14 20:04:09 +00:00
|
|
|
yesno() {
|
|
|
|
case "$1" in
|
|
|
|
yes|YES|true|TRUE|1)
|
|
|
|
echo 1
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
echo 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2020-10-14 19:19:17 +00:00
|
|
|
set_bridge_opts_iproute2() {
|
2020-10-14 19:44:37 +00:00
|
|
|
[ -n "$IF_BRIDGE_AGEING" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge ageing_time $IF_BRIDGE_AGEING
|
|
|
|
[ -n "$IF_BRIDGE_BRIDGEPRIO" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge priority $IF_BRIDGE_BRIDGEPRIO
|
|
|
|
[ -n "$IF_BRIDGE_FD" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge forward_delay $IF_BRIDGE_FD
|
|
|
|
[ -n "$IF_BRIDGE_HELLO" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge hello_time $IF_BRIDGE_HELLO
|
|
|
|
[ -n "$IF_BRIDGE_MAXAGE" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge max_age $IF_BRIDGE_MAXAGE
|
|
|
|
[ -n "$IF_BRIDGE_PATHCOST" ] \
|
|
|
|
&& bridge link set dev $IFACE cost $IF_BRIDGE_PATHCOST
|
|
|
|
[ -n "$IF_BRIDGE_PORTPRIO" ] \
|
|
|
|
&& bridge link set dev $IFACE priority $IF_BRIDGE_PORTPRIO
|
|
|
|
[ -n "$IF_BRIDGE_STP" ] \
|
2020-10-18 19:28:10 +00:00
|
|
|
&& ip link set dev $IFACE type bridge stp $(yesno $IF_BRIDGE_STP)
|
2020-10-14 20:04:09 +00:00
|
|
|
[ -n "$IF_BRIDGE_VLAN_AWARE" ] \
|
|
|
|
&& ip link set dev $IFACE type bridge vlan_filtering $(yesno $IF_BRIDGE_VLAN_AWARE)
|
2020-10-14 19:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set_bridge_opts() {
|
|
|
|
[ -x /sbin/bridge ] && set_bridge_opts_iproute2 && return 0
|
|
|
|
[ -x /sbin/brctl ] && set_bridge_opts_brctl && return 0
|
|
|
|
}
|
|
|
|
|
2020-10-15 04:14:58 +00:00
|
|
|
set_bridge_default_vlans() {
|
|
|
|
[ -x /sbin/bridge ] || return 0
|
|
|
|
|
|
|
|
[ -z "$IF_BRIDGE_PORTS" ] && return 0
|
|
|
|
for port in $IF_BRIDGE_PORTS; do
|
|
|
|
vids=$(ifquery -p bridge-vids $port)
|
|
|
|
[ -z "$vids" ] && vids="$IF_BRIDGE_VIDS"
|
|
|
|
|
|
|
|
for vid in $vids; do
|
|
|
|
bridge vlan add vid $vid dev $port
|
|
|
|
done
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
set_bridge_access_vlans() {
|
|
|
|
[ -z "$IF_BRIDGE_PORTS" ] || return 0
|
|
|
|
[ -z "$IF_BRIDGE_ACCESS" ] && return 0
|
|
|
|
[ -x /sbin/bridge ] || return 0
|
|
|
|
|
|
|
|
if [ "$IF_BRIDGE_PVID" = "$IF_BRIDGE_ACCESS" ]; then
|
|
|
|
PVID="pvid"
|
|
|
|
else
|
|
|
|
PVID=""
|
|
|
|
fi
|
|
|
|
|
|
|
|
bridge vlan add vid $IF_BRIDGE_ACCESS $PVID untagged dev $IFACE
|
|
|
|
}
|
|
|
|
|
2020-07-28 14:34:20 +00:00
|
|
|
all_ports_ready() {
|
|
|
|
local port=
|
|
|
|
for port in $PORTS; do
|
|
|
|
case $(cat /sys/class/net/$IFACE/brif/$port/state) in
|
|
|
|
""|0|3) ;; # 0 = disabled, 3 = forwarding
|
|
|
|
[12]) return 1;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
find_maxwait() {
|
|
|
|
awk '{printf("%.f\n", 2 * $0 / 100); }' \
|
|
|
|
/sys/class/net/$IFACE/bridge/forward_delay
|
|
|
|
}
|
|
|
|
|
|
|
|
wait_bridge() {
|
|
|
|
local timeout=$IF_BRIDGE_MAXWAIT
|
|
|
|
if [ -z "$timeout" ]; then
|
|
|
|
timeout=$(find_maxwait)
|
|
|
|
fi
|
|
|
|
ip link set dev $IFACE up
|
|
|
|
while ! all_ports_ready; do
|
|
|
|
[ $timeout -eq 0 ] && break
|
|
|
|
timeout=$(($timeout - 1))
|
|
|
|
sleep 1
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
case "$IF_BRIDGE_PORTS" in
|
|
|
|
"") ;;
|
|
|
|
none) PORTS="";;
|
|
|
|
all) PORTS=$(all_ports);;
|
|
|
|
*) PORTS="$IF_BRIDGE_PORTS";;
|
|
|
|
esac
|
|
|
|
|
|
|
|
[ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit
|
|
|
|
|
|
|
|
case "$PHASE" in
|
2020-09-09 22:05:32 +00:00
|
|
|
depend)
|
|
|
|
echo "$PORTS"
|
|
|
|
;;
|
2020-09-09 22:48:35 +00:00
|
|
|
create)
|
|
|
|
if [ ! -d "/sys/class/net/${IFACE}" ]; then
|
2020-10-14 19:15:48 +00:00
|
|
|
ip link add "${IFACE}" type bridge
|
2020-09-09 22:48:35 +00:00
|
|
|
fi
|
|
|
|
;;
|
2020-07-28 14:34:20 +00:00
|
|
|
pre-up)
|
|
|
|
wait_ports
|
|
|
|
set_bridge_opts
|
2020-10-15 04:14:58 +00:00
|
|
|
set_bridge_default_vlans
|
|
|
|
set_bridge_access_vlans
|
2020-07-28 14:34:20 +00:00
|
|
|
add_ports
|
|
|
|
wait_bridge
|
|
|
|
;;
|
|
|
|
post-down)
|
|
|
|
del_ports
|
|
|
|
ip link set dev $IFACE down
|
2020-09-09 22:48:35 +00:00
|
|
|
;;
|
|
|
|
destroy)
|
|
|
|
if [ -d "/sys/class/net/${IFACE}" ]; then
|
2020-10-14 19:15:48 +00:00
|
|
|
ip link del "${IFACE}"
|
2020-09-09 22:48:35 +00:00
|
|
|
fi
|
2020-07-28 14:34:20 +00:00
|
|
|
;;
|
|
|
|
esac
|