Merge pull request #7023 from luizluca/switchdev_poller
switchdev_poller: add new package (RFC)
This commit is contained in:
commit
3afa70ddea
3 changed files with 217 additions and 0 deletions
40
net/switchdev-poller/Makefile
Normal file
40
net/switchdev-poller/Makefile
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018-2019 Luiz Angelo Daros de Luca
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=switchdev-poller
|
||||||
|
PKG_VERSION:=1.0.1
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
PKG_MAINTAINER:=Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||||
|
PKG_LICENSE:=GPLv2
|
||||||
|
|
||||||
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
define Package/switchdev-poller
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
DEPENDS:=+swconfig
|
||||||
|
TITLE:=Poll switchdev port to bring CPU ports up/down
|
||||||
|
PKGARCH:=all
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/switchdev-poller/description
|
||||||
|
This service monitors switchdev ports and brings down CPU ports when
|
||||||
|
all related non-CPU vlan ports are also down. Otherwise, it brings
|
||||||
|
the port up.
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/switchdev-poller/install
|
||||||
|
$(CP) ./files/* $(1)
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,switchdev-poller))
|
18
net/switchdev-poller/files/etc/init.d/switchdev-poller
Executable file
18
net/switchdev-poller/files/etc/init.d/switchdev-poller
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
# Copyright (C) 2018-2019 Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||||
|
|
||||||
|
START=99
|
||||||
|
USE_PROCD=1
|
||||||
|
|
||||||
|
start_service() {
|
||||||
|
procd_open_instance switchdev-poller
|
||||||
|
procd_set_param command /usr/lib/switchdev-poller/switchdev-poller
|
||||||
|
procd_set_param stdout 1
|
||||||
|
procd_set_param stderr 0 # enable for extra debug info
|
||||||
|
procd_set_param respawn 3600 5 5
|
||||||
|
procd_close_instance
|
||||||
|
}
|
||||||
|
|
||||||
|
service_triggers() {
|
||||||
|
procd_add_reload_trigger network
|
||||||
|
}
|
159
net/switchdev-poller/files/usr/lib/switchdev-poller/switchdev-poller
Executable file
159
net/switchdev-poller/files/usr/lib/switchdev-poller/switchdev-poller
Executable file
|
@ -0,0 +1,159 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# shellcheck disable=SC2039,SC1091
|
||||||
|
# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, SC2039: In POSIX sh, string replacement is undefined.
|
||||||
|
# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, string indexing is undefined.
|
||||||
|
# https://www.shellcheck.net/wiki/SC1091 -- Not following: /lib/functions.sh:...
|
||||||
|
# Copyright (C) 2018 Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||||
|
#
|
||||||
|
# Pools switchdev for port changes
|
||||||
|
#
|
||||||
|
|
||||||
|
[ -n "$NICED" ] && NICED=1 exec nice -n 19 "$0" "$@"
|
||||||
|
|
||||||
|
. /usr/share/libubox/jshn.sh
|
||||||
|
. /lib/functions.sh
|
||||||
|
|
||||||
|
cpu_ports=""
|
||||||
|
|
||||||
|
json_init
|
||||||
|
json_load "$(cat /etc/board.json)"
|
||||||
|
|
||||||
|
switches=
|
||||||
|
json_get_keys switches switch
|
||||||
|
json_select switch
|
||||||
|
for switch in $switches; do
|
||||||
|
echo Loading $switch >&2
|
||||||
|
json_select "$switch"
|
||||||
|
if json_is_a ports array; then
|
||||||
|
ports=
|
||||||
|
json_get_keys ports ports
|
||||||
|
json_select ports
|
||||||
|
|
||||||
|
for port in $ports; do
|
||||||
|
echo Checking port "$port" in "$switch" >&2
|
||||||
|
json_select "$port"
|
||||||
|
num=
|
||||||
|
json_get_vars num device
|
||||||
|
if [ -n "$device" ]; then
|
||||||
|
echo "Port ${switch}_$num is CPU port as $device" >&2
|
||||||
|
cpu_ports="$cpu_ports ${switch}_$num=$device"
|
||||||
|
fi
|
||||||
|
json_select ..
|
||||||
|
done
|
||||||
|
json_select ..
|
||||||
|
fi
|
||||||
|
json_select ..
|
||||||
|
done
|
||||||
|
|
||||||
|
each_switch_vlan() {
|
||||||
|
switch=
|
||||||
|
vlan=
|
||||||
|
ports=
|
||||||
|
config_get switch "$1" device
|
||||||
|
config_get vlan "$1" vlan
|
||||||
|
config_get ports "$1" ports
|
||||||
|
|
||||||
|
[ -n "$vlan" ] || { echo "No vlan for '$1'" >&2; return 1; }
|
||||||
|
[ -n "$switch" ] || { echo "No device for '$1'" >&2; return 1; }
|
||||||
|
|
||||||
|
vlan_ifnames=""
|
||||||
|
vlan_non_cpu_ports=""
|
||||||
|
echo Checking vlan "$vlan" in $switch >&2
|
||||||
|
for port in $ports; do
|
||||||
|
case $port in
|
||||||
|
*t) tagged=1; port=${port:0:-1} ;;
|
||||||
|
*) tagged= ;;
|
||||||
|
esac
|
||||||
|
echo "Checking port $port in $switch used by vlan $vlan" >&2
|
||||||
|
|
||||||
|
cpu_port_ifname=""
|
||||||
|
for cpu_port in $cpu_ports; do
|
||||||
|
device=${cpu_port#*=}
|
||||||
|
cpu_switchport=${cpu_port%=*}
|
||||||
|
[ "${cpu_switchport}" = "${switch}_${port}" ] || continue
|
||||||
|
echo "Port $port in $switch used by $vlan is a CPU port at $device" >&2
|
||||||
|
|
||||||
|
for device_tagged in $device_tagged; do
|
||||||
|
[ "${tagged}" = 1 ] && not_tagged=0 || not_tagged=1
|
||||||
|
if [ "$device_tagged" = "$device=${not_tagged}" ]; then
|
||||||
|
echo "Cannot control CPU port ${cpu_switchport} when it is used both as tagged and not tagged"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
device_tagged="${device_tagged} ${device}=${tagged:-0}"
|
||||||
|
cpu_port_ifname=${device}${tagged+.$vlan}
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$cpu_port_ifname" ]; then
|
||||||
|
vlan_ifnames="$vlan_ifnames $cpu_port_ifname"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
vlan_non_cpu_ports="$vlan_non_cpu_ports ${port}"
|
||||||
|
done
|
||||||
|
vlan_non_cpu_switch_ports="${vlan_non_cpu_ports// /:${switch}_}"
|
||||||
|
vlan_non_cpu_switch_ports="${vlan_non_cpu_switch_ports:1}"
|
||||||
|
vlan_non_cpu_ports="${vlan_non_cpu_ports:1}"
|
||||||
|
for vlan_ifname in $vlan_ifnames; do
|
||||||
|
devices2ports="$devices2ports $vlan_ifname=${vlan_non_cpu_switch_ports}"
|
||||||
|
echo "Monitoring $switch (ports ${vlan_non_cpu_ports// /,}) for $vlan_ifname"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
device_tagged=""
|
||||||
|
devices2ports=""
|
||||||
|
config_load network
|
||||||
|
config_foreach each_switch_vlan switch_vlan
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
for device2ports in $devices2ports; do
|
||||||
|
device=${device2ports%=*}
|
||||||
|
ip link show dev ${device}_down >/dev/null 2>&1 && {
|
||||||
|
echo "Bringing up $device on exit..."
|
||||||
|
ip link set dev ${device}_down name ${device}
|
||||||
|
ip link set dev ${device} up >/dev/null 2>&1;
|
||||||
|
}
|
||||||
|
done
|
||||||
|
echo "Stopped poller"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
trap cleanup INT TERM
|
||||||
|
echo "Starting poller"
|
||||||
|
while true; do (
|
||||||
|
for device2ports in $devices2ports; do
|
||||||
|
device=${device2ports%=*}
|
||||||
|
switch_ports=${device2ports#*=}
|
||||||
|
switch_ports=${switch_ports//:/ }
|
||||||
|
should_be_up=false
|
||||||
|
for switch_port in $switch_ports; do
|
||||||
|
state=$(eval echo \$${switch_port})
|
||||||
|
if [ -z "${state}" ]; then
|
||||||
|
switch=${switch_port%_*}
|
||||||
|
port=${switch_port#*_}
|
||||||
|
echo "Polling $switch_port..." >&2
|
||||||
|
swconfig dev $switch port $port get link | grep -q 'link:up' &&
|
||||||
|
state=up || state=down
|
||||||
|
eval "$switch_port=$state"
|
||||||
|
echo "State of $switch_port, used by $device, is $state" >&2
|
||||||
|
else
|
||||||
|
echo "State of $switch_port, used by $device, is $state (cached)" >&2
|
||||||
|
fi
|
||||||
|
[ $state = up ] && should_be_up=true
|
||||||
|
done
|
||||||
|
|
||||||
|
if $should_be_up; then
|
||||||
|
ip link show dev ${device}_down >/dev/null 2>&1 && {
|
||||||
|
echo "Bringing up $device..."
|
||||||
|
ip link set dev ${device}_down name ${device}
|
||||||
|
ip link set dev ${device} up >/dev/null 2>&1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ip link show dev ${device} >/dev/null 2>&1 && {
|
||||||
|
echo "Bringing down $device..."
|
||||||
|
ip link set dev ${device} down >/dev/null 2>&1;
|
||||||
|
ip link set dev ${device} name ${device}_down
|
||||||
|
}
|
||||||
|
|
||||||
|
fi
|
||||||
|
done )
|
||||||
|
sleep 3
|
||||||
|
done
|
Loading…
Reference in a new issue