diff --git a/net/mstpd/Config.in b/net/mstpd/Config.in new file mode 100644 index 0000000000..84d5147895 --- /dev/null +++ b/net/mstpd/Config.in @@ -0,0 +1,12 @@ +menu "Configuration" + depends on PACKAGE_mstpd + +config MSTPD_RTNL_RCV_BUFSIZE + int "Netlink receive buffer size" + default 262144 + +config MSTPD_RTNL_SND_BUFSIZE + int "Netlink send buffer size" + default 262144 + +endmenu diff --git a/net/mstpd/Makefile b/net/mstpd/Makefile new file mode 100644 index 0000000000..f6c67dfed5 --- /dev/null +++ b/net/mstpd/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2019 Alexandru Ardelean +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mstpd +PKG_VERSION:=0.0.8 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/mstpd/mstpd/tar.gz/$(PKG_VERSION)? +PKG_HASH:=dd6492039368efff0bd13b3f9c8bb32d859ebfe258a70ef23b2163c4b6c35f0c + +PKG_MAINTAINER:=Alexandru Ardelean +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=LICENSE + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/mstpd + SECTION:=net + CATEGORY:=Network + TITLE:=Multiple Spanning Tree Protocol daemon + URL:=https://github.com/mstpd/mstpd +endef + +define Package/mstpd/description + Multiple Spanning Tree Protocol daemon. + Implements MSTP which is not implemented yet in the Linux kernel. +endef + +define Package/mstpd/config + source "$(SOURCE)/Config.in" +endef + +TARGET_CFLAGS += \ + -DRTNL_RCV_BUFSIZE=$(CONFIG_MSTPD_RTNL_RCV_BUFSIZE) \ + -DRTNL_SND_BUFSIZE=$(CONFIG_MSTPD_RTNL_SND_BUFSIZE) + +MAKE_VARS+=MODE=prod + +define Package/mstpd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mstpd $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mstpctl $(1)/usr/sbin + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) ./files/etc/init.d/mstpd.init $(1)/etc/init.d/mstpd + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) ./files/sbin/bridge-stp $(1)/sbin +endef + +$(eval $(call BuildPackage,mstpd)) diff --git a/net/mstpd/files/etc/init.d/mstpd.init b/net/mstpd/files/etc/init.d/mstpd.init new file mode 100644 index 0000000000..bade419e05 --- /dev/null +++ b/net/mstpd/files/etc/init.d/mstpd.init @@ -0,0 +1,124 @@ +#!/bin/sh /etc/rc.common + +# shellcheck disable=SC2034 # foo appears unused. Verify it or export it. + +START=25 +STOP=99 + +MSTPCTL="/usr/sbin/mstpctl" +MSTPD="/usr/sbin/mstpd" + +USE_PROCD=1 + +mstpd_get_bridges() { + "$MSTPCTL" showbridge | grep -v "^ " | cut -d " " -f 1 2>/dev/null +} + +# mstpd log levels +# LOG_LEVEL_NONE 0 +# LOG_LEVEL_ERROR 1 +# LOG_LEVEL_INFO 2 +# LOG_LEVEL_DEBUG 3 +# LOG_LEVEL_STATE_MACHINE_TRANSITION 4 +# LOG_LEVEL_MAX 100 + +config_bridge_port_mstpd() { + local config="$1" + local index=$2 # FIXME: maybe remove index later + local name=$3 + + [ -n "$index" -a -n "$name" ] || return 0 + + config_get br_index "$config" br_index + [ -n "$br_index" ] || return 0 + [ "$index" = "$br_index" ] || return 0 + + config_get port_name "$config" name + [ -n "$port_name" ] || return 0 + + for opt in bpduguard; do + config_get $opt "$config" $opt + eval optval=\$$opt + [ -z "$optval" ] || "$MSTPCTL" "set$opt" "$name" "$port_name" "$optval" + done +} + +config_bridge_mstpd() { + local config="$1" + local optval= + local name= + local enable= + local mstid=0 # for the moment, using only MSTID + + config_get index "$config" index + [ -n "$index" ] || return 1 + + # Get bridge name + config_get name "$config" name + [ -n "$name" ] || return 0 + + config_get enable "$config" enable + if [ "$enable" != "1" ] ; then + return 0 + fi + + list_contains MSTPD_PREINSTALLED_BRIDGES "$name" || \ + "$MSTPCTL" addbridge "$name" + # All options here have 'set$opt' equivalent calls in mstpd, + # hence this trick with the loop + for opt in maxage fdelay maxhops hello ageing forcevers txholdcount; do + config_get $opt "$config" "$opt" + eval optval=\$$opt + [ -z "$optval" ] || "$MSTPCTL" set$opt "$name" "$optval" + done + config_get treeprio "$config" treeprio + [ -z "$treeprio" ] || $MSTPCTL settreeprio "$name" "$mstid" "$treeprio" + config_foreach config_bridge_port_mstpd bridge_port "$index" "$name" + CONFIGURED_BRIDGES="$CONFIGURED_BRIDGES $name" + export CONFIGURED_BRIDGES +} + +start_service() { + procd_open_instance + procd_set_param command $MSTPD + procd_append_param command -v 2 + procd_append_param command -d # don't daemonize, procd will handle that for us + procd_append_param command -s # print to syslog + + # set auto respawn behavior + procd_set_param respawn + + # reload config on respawn + procd_open_trigger + procd_add_raw_trigger "instance.start" 2000 "/etc/init.d/mstpd" "reload" + procd_close_trigger + + procd_close_instance +} + +service_running() { + pgrep mstpd >/dev/null 2>&1 +} + +reload_service() { + if ! running ; then + start + return + fi + + unset CONFIGURED_BRIDGES + MSTPD_PREINSTALLED_BRIDGES="$(mstpd_get_bridges)" + export MSTPD_PREINSTALLED_BRIDGES + + config_load 'mstpd' + config_foreach config_bridge_mstpd bridge + + for bridge in $(mstpd_get_bridges) ; do + list_contains CONFIGURED_BRIDGES "$bridge" || \ + $MSTPCTL delbridge "$bridge" + done + # return 0 (success) here, otherwise, and endless restart loop will occur from procd + # because the last return code may be mstpctl failing + return 0 +} + diff --git a/net/mstpd/files/sbin/bridge-stp b/net/mstpd/files/sbin/bridge-stp new file mode 100644 index 0000000000..7b2cbc04b2 --- /dev/null +++ b/net/mstpd/files/sbin/bridge-stp @@ -0,0 +1,9 @@ +#!/bin/sh + +# Dummy file ; don't do anything ; +# Returning success here, tells the kernel to allow +# a userspace module to handle STP states +# +# Meanwhile, procd will start mstpd, and all will be well + +exit 0