Skip to content

Commit

Permalink
mldpoker: initial package
Browse files Browse the repository at this point in the history
A small utility that pokes sleepy devices for MLD Reports.

A workaround for:

* Roaming issues with Linux <= 4.9:
  -> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a088d1d73a4bcfd7bc482f8d08375b9b665dc3e5

* Android devices being unresponsive to MLD Queries in sleep mode:
  -> freifunk-gluon/gluon#1832
  -> https://issuetracker.google.com/issues/149630944
  • Loading branch information
T-X committed Mar 10, 2020
1 parent 12e41d0 commit bf3df91
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
51 changes: 51 additions & 0 deletions net/mldpoker/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=mldpoker
PKG_VERSION:=1
PKG_RELEASE:=1

PKG_LICENSE:=GPLv2
PKG_LICENSE_FILES:=

PKG_SOURCE_URL:=https://github.com/T-X/mldpoker.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2019-03-08
PKG_SOURCE_VERSION:=1b14b2da34239b7954767e7a9c6c759bab3d72de
PKG_MIRROR_HASH:=skip


include $(INCLUDE_DIR)/package.mk

define Package/mldpoker
TITLE:=A small utility that pokes sleepy devices for MLD Reports
SECTION:=net
CATEGORY:=Network
endef

define Package/mldpoker/description
A small utility that pokes sleepy devices for MLD Reports

If a host behind IFNAME newly appeared or was unresponsive for
at least 15 seconds and now reappeared then MLD Poker sends a
general MLDv1 Query with an MLD Maximum Query Response Delay of
0 to it (request for an immediate, undelayed MLD Report). The
MLD Query is sent to the target host directly via its unicast MAC
address.

This tool was written to work around the following two issues:

Roaming issues with Linux <= 4.9:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a088d1d73a4bcfd7bc482f8d08375b9b665dc3e5

Android devices being unresponsive to MLD Queries in sleep mode:
https://github.com/freifunk-gluon/gluon/issues/1832
https://issuetracker.google.com/issues/149630944
endef

define Package/mldpoker/install
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/usr/sbin/
$(CP) $(PKG_BUILD_DIR)/mldpoker $(1)/usr/sbin/mldpoker
endef

$(eval $(call BuildPackage,mldpoker))
41 changes: 41 additions & 0 deletions net/mldpoker/files/etc/hotplug.d/iface/60-mldpoker
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
mldpoker_start_check() {
local brtype="`uci get network.$INTERFACE.type`"

if [ ! "$brtype" = "bridge" ] ||
[ ! "`cat /sys/class/net/$DEVICE/bridge/multicast_snooping`" = "1" ] ||
[ ! "`cat /sys/class/net/$DEVICE/bridge/multicast_querier`" = "1" ]; then
return 1
fi

return 0
}

mldpoker_start() {
local iface

mldpoker_start_check || exit 0

for iface in /sys/class/net/$DEVICE/brif/*; do
/etc/init.d/mldpoker start "${iface##*/}"
done
}

mldpoker_stop() {
for iface in /sys/class/net/$DEVICE/brif/*; do
/etc/init.d/mldpoker stop "${iface##*/}"
done
}


[ "`uci get mldpoker.@general[0].disabled`" = "1" ] && exit 0


if [ "$ACTION" = "ifup" ]; then
logger -t mldpoker "Hotplug: Starting mldpokers for bridge $DEVICE"
mldpoker_start
elif ["$ACTION" = "ifdown" ]; then
logger -t mldpoker "Hotplug: Stopping mldpokers for bridge $DEVICE"
mldpoker_stop
else
logger -t mldpoker "Hotplug: Unknown ACTION: $ACTION for $DEVICE"
fi
105 changes: 105 additions & 0 deletions net/mldpoker/files/etc/init.d/mldpoker
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/sh /etc/rc.common

USE_PROCD=1

br_is_querier() {
local brport="$1"
local has_snooping="`cat /sys/class/net/$brport/brport/bridge/bridge/multicast_snooping 2>/dev/null`"
local has_querier="`cat /sys/class/net/$brport/brport/bridge/bridge/multicast_querier 2>/dev/null`"

[ "$has_snooping" = "1" ] && [ "$has_querier" = "1" ] && \
return 0

return 1
}

check_blacklisted() {
local iface="$1"
local ret=0

for blk in `uci get mldpoker.@blacklist[0].ifname`; do
echo "$blk" | grep -q "^$iface\$" && {
ret=1
break
}
done

return $ret
}

start_instance() {
local iface="$1"
local briface

briface="`grep "INTERFACE" /sys/class/net/bat0/brport/bridge/uevent 2>/dev/null`"
briface="${briface#*=}"

check_blacklisted "$iface" || return

procd_open_instance "mldpoker-$iface"
procd_set_param command /usr/sbin/mldpoker $iface

# respawn automatically if something died, be careful if you have an alternative process supervisor
# if process dies sooner than respawn_threshold, it is considered crashed and after 5 retries the service is stopped
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}

procd_set_param netdev $iface # likewise, except if dev's ifindex changes.
procd_set_param stdout 0 # forward stdout of the command to logd
procd_set_param stderr 1 # same for stderr
procd_set_param pidfile /var/run/mldpoker-$iface.pid # write a pid file on instance start and remove it on stop
procd_close_instance

logger -t mldpoker "Starting mldpoker instance for $iface on $briface"
}

start_all_instances() {
for brport in /sys/class/net/*/brport/; do
brport=${brport%/*/}
brport=${brport##*/}

br_is_querier "$brport" || continue

start_instance "$brport"
done
}

start_service() {
[ "`uci get mldpoker.@general[0].disabled 2> /dev/null`" = "1" ] && exit 0

if [ $# -eq 0 ]; then
start_all_instances
elif [ $# -gt 0 ] && [ -n "$1" ]; then
start_instance "$1"
else
echo "Error: Unknown start command: $@" >&2
exit 1
fi
}

stop_instance() {
procd_kill mldpoker mldpoker-$1
}

stop_all_instances() {
local brport

for brport in /sys/class/net/*/brport/; do
brport=${brport%/*/}
brport=${brport##*/}

br_is_querier "$brport" || continue

stop_instance "$brport"
done
}

stop_service() {
if [ $# -eq 0 ]; then
stop_all_instances
elif [ $# -gt 0 ] && [ -n "$1" ]; then
stop_instance "$1"
else
echo "Error: Unknown stop command: $@" >&2
exit 1
fi
}

0 comments on commit bf3df91

Please sign in to comment.