mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
mcastmngr: fixed mcproxy crash for multiupstream config
If more than one upstream iface is defined, mcastmngr runs mcproxy multiple times for each protocol (e.g. igmp) with the same config. So second mcproxy process fails because it can't lock the MRT flag (/proc/sys/net/ipv/default/mc_forwarding) already blocked by the first process. If one good and one bad (no IP address) upstream interfaces are defined, mcastmngr generates wrong filter configuration and mcproxy cannot start at all. Now upstream and downstream ifaces are checked in the 'config_mcproxy_interfaces' function and only good interfaces (with IP) are written to the mcproxy config. Only one mcproxy process is started per protocol (igmp, mld), configured to handle multiple interfaces if necessary. 'get_network_of' function removed. This function fails in some uci configurations for interfaces that refer to a device indirectly. Example - network.wan6.device='@wan'
This commit is contained in:
parent
3f398d1016
commit
7c3d1f919c
1 changed files with 112 additions and 130 deletions
|
|
@ -10,70 +10,81 @@ PROG_EXE=/usr/sbin/mcproxy
|
|||
PROG_PARAMS=
|
||||
PROG_PARAMS_SEPARATOR=:
|
||||
|
||||
setup_mcast_mode() {
|
||||
local snooped_interface=$1
|
||||
local mcast_mode=$2
|
||||
|
||||
local mcast_flood=
|
||||
__device_is_bridge() {
|
||||
local device="$2"
|
||||
local devsec__="$(uci show network | grep name=.*$device | cut -d'.' -f2)"
|
||||
local sectype="$(uci -q get network.$devsec__)"
|
||||
local devtype="$(uci -q get network.$devsec__.type)"
|
||||
[ "$sectype" != "device" -o "$devtype" != "bridge" ] && return 1
|
||||
eval "$1=$devsec__"
|
||||
}
|
||||
|
||||
device_is_bridge() {
|
||||
local device="$1"
|
||||
local devsec=
|
||||
local sectype=
|
||||
local devtype=
|
||||
local ports=
|
||||
if [ -z "$snooped_interface" ]; then
|
||||
return
|
||||
fi
|
||||
__device_is_bridge devsec "$device" || return 1
|
||||
}
|
||||
|
||||
if [ $mcast_mode == "2" ]; then # disable mcast flood
|
||||
mcast_flood=0
|
||||
device_ports() {
|
||||
local device="$1"
|
||||
local devsec=
|
||||
|
||||
if __device_is_bridge devsec "$device"; then
|
||||
echo "$(uci get network.$devsec.ports)"
|
||||
else
|
||||
mcast_flood=1
|
||||
echo "$device"
|
||||
fi
|
||||
}
|
||||
|
||||
for intf in $snooped_interface;
|
||||
do
|
||||
devsec="$(uci show network | grep name=.*$intf | cut -d'.' -f2)"
|
||||
sectype="$(uci -q get network.$devsec)"
|
||||
devtype="$(uci -q get network.$devsec.type)"
|
||||
if [ "$sectype" == "device" -a "$devtype" == "bridge" ]; then
|
||||
ports="$(uci get network.$devsec.ports)"
|
||||
for prt in $ports; do
|
||||
echo $mcast_flood > /sys/class/net/$prt/brport/multicast_flood
|
||||
done
|
||||
else
|
||||
if [ -f /sys/class/net/$intf/brport/multicast_flood ]; then
|
||||
echo $mcast_flood > /sys/class/net/$intf/brport/multicast_flood
|
||||
fi
|
||||
fi
|
||||
device_has_ip() {
|
||||
local protocol="$1"
|
||||
local device="$2"
|
||||
|
||||
# Read the openwrt interface for the device.
|
||||
# Device can have multiple logical interfaces like wan and wan6
|
||||
# but same l3 device
|
||||
# NB. Don't use 'get_network_of' here.
|
||||
# This function fails in some uci configurations for interfaces that refer
|
||||
# to a device indirectly.
|
||||
local ifaces=$(ubus call network.interface dump | jsonfilter -e "@.interface[@.device='$device'].interface")
|
||||
for iface in $ifaces; do
|
||||
local ip=
|
||||
case "$protocol" in
|
||||
"igmp") network_get_ipaddr ip "$iface" ;;
|
||||
"mld") network_get_ipaddr6 ip "$iface" ;;
|
||||
esac
|
||||
[ -n "$ip" ] && return
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
config_mcproxy_interfaces() {
|
||||
local upstreams="$1"
|
||||
local downstreams="$2"
|
||||
local exceptions="$3"
|
||||
local protocol="$1"
|
||||
local upstreams="$2"
|
||||
local downstreams="$3"
|
||||
local exceptions="$4"
|
||||
|
||||
if [ -z "$upstreams" ] || [ -z "$downstreams" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local str_up=""
|
||||
if [ -n "$upstreams" ]; then
|
||||
for upstream in $upstreams; do
|
||||
str_up="$str_up \"$upstream\""
|
||||
done
|
||||
fi
|
||||
for upstream in $upstreams; do
|
||||
device_has_ip "$protocol" "$upstream" || continue
|
||||
str_up="$str_up \"$upstream\""
|
||||
done
|
||||
[ -z "$str_up" ] && return 1
|
||||
|
||||
local str_down=""
|
||||
if [ -n "$downstreams" ]; then
|
||||
for downstream in $downstreams; do
|
||||
str_down="$str_down \"$downstream\""
|
||||
done
|
||||
fi
|
||||
for downstream in $downstreams; do
|
||||
device_has_ip "$protocol" "$downstream" || continue
|
||||
str_down="$str_down \"$downstream\""
|
||||
done
|
||||
[ -z "$str_down" ] && return 1
|
||||
|
||||
if [ ! -z $downstream ]; then
|
||||
echo -e "pinstance main:$str_up ==>$str_down;\n" >> $CONFFILE
|
||||
fi
|
||||
|
||||
|
||||
if [ -z "$exceptions" ] || [ -z "$upstreams" ]; then
|
||||
return
|
||||
fi
|
||||
echo -e "pinstance main:$str_up ==>$str_down;\n" >> $CONFFILE
|
||||
|
||||
for excp in $exceptions; do
|
||||
local filter=""
|
||||
|
|
@ -89,34 +100,63 @@ config_mcproxy_interfaces() {
|
|||
;;
|
||||
esac
|
||||
|
||||
for upstream in $upstreams; do
|
||||
echo "pinstance main upstream \"$upstream\" in blacklist table{$filter };" >> $CONFFILE
|
||||
echo "pinstance main upstream \"$upstream\" out blacklist table{$filter };" >> $CONFFILE
|
||||
for upstream in $str_up; do
|
||||
echo "pinstance main upstream $upstream in blacklist table{$filter };" >> $CONFFILE
|
||||
echo "pinstance main upstream $upstream out blacklist table{$filter };" >> $CONFFILE
|
||||
done
|
||||
|
||||
for downstream in $downstreams; do
|
||||
echo "pinstance main downstream \"$downstream\" in blacklist table{$filter };" >> $CONFFILE
|
||||
echo "pinstance main downstream \"$downstream\" out blacklist table{$filter };" >> $CONFFILE
|
||||
for downstream in $str_down; do
|
||||
echo "pinstance main downstream $downstream in blacklist table{$filter };" >> $CONFFILE
|
||||
echo "pinstance main downstream $downstream out blacklist table{$filter };" >> $CONFFILE
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
config_sysfs_mcast_snooping() {
|
||||
local devsec=
|
||||
local sectype=
|
||||
local devtype=
|
||||
local ports=
|
||||
local downstreams="$1"
|
||||
|
||||
for downstream in $downstreams; do
|
||||
devsec="$(uci show network | grep name=.*$downstream | cut -d'.' -f2)"
|
||||
sectype="$(uci -q get network.$devsec)"
|
||||
devtype="$(uci -q get network.$devsec.type)"
|
||||
if [ "$sectype" == "device" -a "$devtype" == "bridge" ]; then
|
||||
if device_is_bridge "$downstream"; then
|
||||
echo 1 > /sys/class/net/$downstream/bridge/multicast_snooping
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
config_sysfs_mcast_fastleave() {
|
||||
local downstreams="$1"
|
||||
local fastleave="$2"
|
||||
local prt
|
||||
|
||||
for downstream in $downstreams; do
|
||||
for prt in $(device_ports $downstream); do
|
||||
if [ -f /sys/class/net/$prt/brport/multicast_fast_leave ]; then
|
||||
echo $fastleave > /sys/class/net/$prt/brport/multicast_fast_leave
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
config_sysfs_mcast_mode() {
|
||||
local downstreams=$1
|
||||
local mcast_mode=$2
|
||||
local prt
|
||||
|
||||
local mcast_flood=
|
||||
if [ $mcast_mode == "2" ]; then # disable mcast flood
|
||||
mcast_flood=0
|
||||
else
|
||||
mcast_flood=1
|
||||
fi
|
||||
|
||||
for downstream in $downstreams; do
|
||||
for prt in $(device_ports $downstream); do
|
||||
if [ -f /sys/class/net/$prt/brport/multicast_flood ]; then
|
||||
echo $mcast_flood > /sys/class/net/$prt/brport/multicast_flood
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
config_mcproxy_instance() {
|
||||
local protocol="$1"
|
||||
local version="$2"
|
||||
|
|
@ -129,7 +169,6 @@ config_mcproxy_instance() {
|
|||
local exceptions=
|
||||
local upstreams=
|
||||
local downstreams=
|
||||
local intf_has_ip=
|
||||
local mcast_mode=2 # default value 2 is for blocking mode
|
||||
|
||||
CONFFILE=/var/etc/mcproxy_"$protocol".conf
|
||||
|
|
@ -178,58 +217,23 @@ config_mcproxy_instance() {
|
|||
mcast_mode=$mld_p_mode
|
||||
fi
|
||||
|
||||
# for snooping to work we should enable it on the bridge, doing it from
|
||||
# here instead of from inside network config
|
||||
config_sysfs_mcast_snooping
|
||||
|
||||
[ -n "$max_groups" ] && echo -e "max_groups $max_groups;" >> $CONFFILE
|
||||
[ -n "$robustness" ] && echo -e "rv $robustness;" >> $CONFFILE
|
||||
[ -n "$query_interval" ] && echo -e "qi $query_interval;" >> $CONFFILE
|
||||
[ -n "$q_resp_interval" ] && echo -e "qri $q_resp_interval;" >> $CONFFILE
|
||||
[ -n "$last_mem_q_int" ] && echo -e "lmqi $last_mem_q_int;" >> $CONFFILE
|
||||
if [[ -n $fast_leave ]]; then
|
||||
echo -e "fastleave $fast_leave;\n" >> $CONFFILE
|
||||
config_sysfs_mcast_fastleave $fast_leave
|
||||
fi
|
||||
[ -n "$fast_leave" ] && echo -e "fastleave $fast_leave;\n" >> $CONFFILE
|
||||
|
||||
setup_mcast_mode $downstreams $mcast_mode
|
||||
[ -n "$upstreams" ] && [ -n "$downstreams" ] &&
|
||||
config_mcproxy_interfaces "$upstreams" "$downstreams" "$exceptions"
|
||||
config_mcproxy_interfaces "$protocol" "$upstreams" "$downstreams" "$exceptions" || return
|
||||
|
||||
# In case on proxy, upstreams is a list. Iterating and running the mcproxy
|
||||
# for each valid upstream interface
|
||||
for upstream_device in $upstreams;
|
||||
do
|
||||
# Read the upstream interface for the upstream device
|
||||
# upstream device can have multiple logical interfaces like wan and wan6
|
||||
# but same l3 device
|
||||
local upstream_ifaces=$(get_network_of $upstream_device)
|
||||
# for snooping to work we should enable it on the bridge, doing it from
|
||||
# here instead of from inside network config
|
||||
config_sysfs_mcast_snooping "$downstreams"
|
||||
[ -n $fast_leave ] &&
|
||||
config_sysfs_mcast_fastleave "$downstreams" "$fast_leave"
|
||||
config_sysfs_mcast_mode "$downstreams" "$mcast_mode"
|
||||
|
||||
for iface in $upstream_ifaces;
|
||||
do
|
||||
if [ "$protocol" == "igmp" ]; then
|
||||
network_get_ipaddr upstream_ip $iface
|
||||
if [ ! -z "${upstream_ip}" ]; then
|
||||
intf_has_ip=1
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$protocol" == "mld" ]; then
|
||||
network_get_ipaddr6 upstream_ip $iface
|
||||
if [ ! -z "${upstream_ip}" ]; then
|
||||
intf_has_ip=1
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${intf_has_ip}" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
PROG_PARAMS="${PROG_PARAMS} -f ${CONFFILE}${PROG_PARAMS_SEPARATOR}"
|
||||
done
|
||||
PROG_PARAMS="${PROG_PARAMS} -f ${CONFFILE}${PROG_PARAMS_SEPARATOR}"
|
||||
}
|
||||
|
||||
config_mcproxy() {
|
||||
|
|
@ -242,28 +246,6 @@ config_mcproxy() {
|
|||
fi
|
||||
}
|
||||
|
||||
config_sysfs_mcast_fastleave() {
|
||||
local devsec=
|
||||
local sectype=
|
||||
local devtype=
|
||||
local ports=
|
||||
|
||||
for downstream in $downstreams; do
|
||||
devsec="$(uci show network | grep name=.*$downstream | cut -d'.' -f2)"
|
||||
sectype="$(uci -q get network.$devsec)"
|
||||
devtype="$(uci -q get network.$devsec.type)"
|
||||
if [ "$sectype" == "device" -a "$devtype" == "bridge" ]; then
|
||||
ports="$(uci get network.$devsec.ports)"
|
||||
for prt in $ports; do
|
||||
echo $1 > /sys/class/net/$prt/brport/multicast_fast_leave
|
||||
done
|
||||
else
|
||||
[[ -f /sys/class/net/$downstream/brport/multicast_fast_leave ]] && echo $1 > /sys/class/net/$downstream/brport/multicast_fast_leave
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
configure_mcast() {
|
||||
config_global_params "set_max_groups_and_sources"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue