bridge: Rework vlan handling
Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
This commit is contained in:
parent
fb1d3181fe
commit
02a74985ab
1 changed files with 126 additions and 40 deletions
|
@ -1,6 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
[ -n "$VERBOSE" ] && set -x
|
||||
|
||||
# Copyright (C) 2012, 2020 Natanael Copa <ncopa@alpinelinux.org>
|
||||
# Copyright (C) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||
|
@ -14,6 +15,10 @@ set -e
|
|||
# implied. In no event shall the authors be liable for any damages arising
|
||||
# from the use of this software.
|
||||
|
||||
################################################################################
|
||||
# Bridge management functions #
|
||||
################################################################################
|
||||
|
||||
all_ports_exist() {
|
||||
local i=
|
||||
for i in "$@"; do
|
||||
|
@ -123,33 +128,6 @@ set_bridge_opts() {
|
|||
[ -x /sbin/brctl ] && set_bridge_opts_brctl && return 0
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
all_ports_ready() {
|
||||
local port=
|
||||
|
@ -180,6 +158,93 @@ wait_bridge() {
|
|||
done
|
||||
}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Bridge port management functions #
|
||||
################################################################################
|
||||
|
||||
configure_access_port() {
|
||||
port="$1"
|
||||
vlan="$2"
|
||||
self="$3"
|
||||
|
||||
# Cleans all existing VLANs (probably at least VLAN 1)
|
||||
bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | while read vid flags; do
|
||||
bridge vlan del vid "${vid}" dev "${port}" ${self}
|
||||
done
|
||||
|
||||
bridge vlan add vid "${vlan}" pvid untagged dev "${port}" ${self}
|
||||
}
|
||||
|
||||
configure_trunk_port() {
|
||||
port="$1"
|
||||
self="$2"
|
||||
|
||||
# Working on the bridge itself?
|
||||
if [ "${self}" ]; then
|
||||
allow_untagged="${IF_BRIDGE_ALLOW_UNTAGGED}"
|
||||
pvid="${IF_BRIDGE_PVID}"
|
||||
vids="${IF_BRIDGE_VIDS}"
|
||||
else
|
||||
allow_untagged=$(ifquery -p bridge-allow-untagged ${port} 2>/dev/null || true)
|
||||
pvid=$(ifquery -p bridge-pvid ${port} 2>/dev/null || true)
|
||||
vids=$(ifquery -p bridge-vids ${port} 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
# If bridge-allow-untagged if set to off, remove untagged VLAN. If it's
|
||||
# one of our bridge-vids, it will be set again later.
|
||||
if [ "${allow_untagged}" -a "$(yesno ${allow_untagged})" = 0 ]; then
|
||||
untagged_vid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/Untagged/ { print $1 }')
|
||||
if [ "${untagged_vid}" ]; then
|
||||
bridge vlan del vid "${untagged_vid}" dev "${port}" ${self}
|
||||
fi
|
||||
fi
|
||||
|
||||
# The vlan specified is to be considered a PVID at ingress.
|
||||
# Any untagged frames will be assigned to this VLAN.
|
||||
if [ "${pvid}" ]; then
|
||||
cur_pvid=$(bridge vlan show dev ${port} | tail -n +2 | grep -v '^$' | sed -e "s/^${port}//" | awk '/PVID/ { print $1 }')
|
||||
if [ "${cur_pvid}" ]; then
|
||||
bridge vlan del vid ${cur_pvid} dev "${port}" ${self}
|
||||
fi
|
||||
|
||||
bridge vlan add vid "${pvid}" dev "${port}" pvid untagged ${self}
|
||||
fi
|
||||
|
||||
# Add regular tagged VLANs
|
||||
for vid in ${vids}; do
|
||||
bridge vlan add vid $vid dev "${port}" ${self}
|
||||
done
|
||||
}
|
||||
|
||||
# Configure VLANs on the bridge interface itself
|
||||
set_bridge_vlans() {
|
||||
# Shall the bridge interface be an untagged port?
|
||||
if [ "${IF_BRIDGE_ACCESS}" ]; then
|
||||
configure_access_port "${IFACE}" "${IF_BRIDGE_ACCESS}" "self"
|
||||
|
||||
# Configure bridge interface as trunk port
|
||||
else
|
||||
configure_trunk_port "${IFACE}" "self"
|
||||
fi
|
||||
}
|
||||
|
||||
# Configure VLANs on the bridge-ports
|
||||
set_bridge_port_vlans() {
|
||||
for port in ${PORTS}; do
|
||||
access_vlan=$(ifquery -p bridge-access ${port} 2>/dev/null || true)
|
||||
|
||||
# Shall this prot interface be an untagged port?
|
||||
if [ "${access_vlan}" ]; then
|
||||
configure_access_port "${port}" "${access_vlan}"
|
||||
|
||||
# Configure port as trunk
|
||||
else
|
||||
configure_trunk_port "${port}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case "$IF_BRIDGE_PORTS" in
|
||||
"") ;;
|
||||
none) PORTS="";;
|
||||
|
@ -187,31 +252,52 @@ all) PORTS=$(all_ports);;
|
|||
*) PORTS="$IF_BRIDGE_PORTS";;
|
||||
esac
|
||||
|
||||
[ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit
|
||||
|
||||
case "$PHASE" in
|
||||
depend)
|
||||
echo "$PORTS"
|
||||
# Called for the bridge interface
|
||||
if [ "${IF_BRIDGE_PORTS}" ]; then
|
||||
echo "$PORTS"
|
||||
fi
|
||||
;;
|
||||
|
||||
create)
|
||||
if [ ! -d "/sys/class/net/${IFACE}" ]; then
|
||||
# Called for the bridge interface
|
||||
if [ "${IF_BRIDGE_PORTS}" -a ! -d "/sys/class/net/${IFACE}" ]; then
|
||||
ip link add "${IFACE}" type bridge
|
||||
fi
|
||||
;;
|
||||
|
||||
pre-up)
|
||||
wait_ports
|
||||
set_bridge_opts
|
||||
set_bridge_default_vlans
|
||||
set_bridge_access_vlans
|
||||
add_ports
|
||||
wait_bridge
|
||||
# Called for the bridge interface
|
||||
if [ "${IF_BRIDGE_PORTS}" ]; then
|
||||
wait_ports
|
||||
set_bridge_opts
|
||||
set_bridge_vlans
|
||||
add_ports
|
||||
set_bridge_port_vlans
|
||||
wait_bridge
|
||||
|
||||
# Called for a bridge member port
|
||||
elif [ "${IF_BRIDGE_VIDS}" -o "${IF_BRIDGE_PVID}" -o "${IF_BRIDGE_ACCESS}" -o "${IF_BRIDGE_ALLOW_UNTAGGED}" ]; then
|
||||
# Eventually we want to configure VLAN settings of member ports here.
|
||||
# The current execution model does not allow this, so this is a no-op
|
||||
# for now and we work around this by configuring ports while configuring
|
||||
# the bridge.
|
||||
true
|
||||
fi
|
||||
;;
|
||||
|
||||
post-down)
|
||||
del_ports
|
||||
ip link set dev $IFACE down
|
||||
# Called for the bridge interface
|
||||
if [ "${IF_BRIDGE_PORTS}" ]; then
|
||||
del_ports
|
||||
ip link set dev $IFACE down
|
||||
fi
|
||||
;;
|
||||
|
||||
destroy)
|
||||
if [ -d "/sys/class/net/${IFACE}" ]; then
|
||||
# Called for the bridge interface
|
||||
if [ "${IF_BRIDGE_PORTS}" -a -d "/sys/class/net/${IFACE}" ]; then
|
||||
ip link del "${IFACE}"
|
||||
fi
|
||||
;;
|
||||
|
|
Loading…
Reference in a new issue