Fixed softflowd init script - testing needed

We've had a couple of threads on here before about the broken softflowd init script.

I finally decided to debug it. If some testers can confirm it works for them as well, I'll make a PR for it (although I'll probably remove the taskset piece before doing so, since taskset requires a patch to the main repo's util-linux Makefile).

#!/bin/sh /etc/rc.common
# Copyright (C) 2007-2011 OpenWrt.org

USE_PROCD=1
START=99
SOFTFLOWD=/usr/sbin/softflowd
SOFTFLOWCTL=/usr/sbin/softflowctl
TASKSET=/usr/bin/taskset

append_bool() {
	local section="$1"
	local option="$2"
	local value="$3"
	local _val
	config_get_bool _val "$section" "$option" '0'
	[ "$_val" -gt 0 ] && append args "$3"
}

append_string() {
	local section="$1"
	local option="$2"
	local value="$3"
	local _val
	config_get _val "$section" "$option"
	[ -n "$_val" ] && append args "$3 $_val"
}

start_instance() {
	local section="$1"
	local affinity_mask="0xff"
	local taskset=""

	config_get_bool enabled "$section" 'enabled' '0'
	[ "$enabled" -gt 0 ] || return 1

	config_get affinity_mask "$section" 'affinity_mask'

	args=""
	append_string "$section" 'interface' '-i'
	append_bool   "$section" 'track_ipv6' '-6'
	append_string "$section" 'export_version' '-v'
	append_string "$section" 'host_port' '-n'
	append_string "$section" 'pcap_file' '-r'
	append_string "$section" 'timeout' '-t'
	append_string "$section" 'max_flows' '-m'
	append_string "$section" 'hoplimit' '-L'
	append_string "$section" 'tracking_level' '-T'
	append_string "$section" 'sampling_rate' '-s'
	append_string "$section" 'control_socket' '-c'

	[ -S ${control_socket} ] && rm -f ${control_socket}
	[ -f ${TASKSET} ] && taskset="${TASKSET} ${affinity_mask}"

	procd_open_instance
	procd_set_param command ${taskset} ${SOFTFLOWD} -d ${args}
	procd_set_param respawn
	procd_close_instance
}

start_service() {
	config_load 'softflowd'
	config_foreach start_instance 'softflowd'
}

stop_instance() {
	local section="$1"
	config_get control_socket "$section" 'control_socket'
	[ -S ${control_socket} ] && ${SOFTFLOWCTL} -c ${control_socket} shutdown
}

stop_service() {
	config_load 'softflowd'
	config_foreach stop_instance 'softflowd'
}

restart() {
	stop_service
	start_service
}

Here's my /etc/config/softflowd

config softflowd
	option enabled        '1'
	option interface      'br-lan'
	option pcap_file      ''
	option timeout        ''
	option max_flows      ''
	option host_port      '192.168.1.2:5000'
	option control_socket '/var/run/softflowd-br-lan.ctl'
	option export_version '9'
	option hoplimit       ''
	option tracking_level ''
	option track_ipv6     '1'
	option sampling_rate  ''
	option affinity_mask  '0x20'

config softflowd
	option enabled        '1'
	option interface      'br-guest'
	option pcap_file      ''
	option timeout        ''
	option max_flows      ''
	option host_port      '192.168.1.2:5000'
	option control_socket '/var/run/softflowd-br-guest.ctl'
	option export_version '9'
	option hoplimit       ''
	option tracking_level ''
	option track_ipv6     '1'
	option sampling_rate  ''
	option affinity_mask  '0x40'

I left the unused parameters in the config file so you know what they are and can use them if you wish.

If you have taskset installed you can specify that each specific instance is pinned to a core by using an affinity mask (man taskset). If you don't have taskset installed, the option (and tasket) will be silently ignored.

I've removed the pid file option. A pid file is not used if softflowd is run in the foreground as is the requirement for a procd instantiated process. It's only used for a daemonised process.

I made the startup sequence much later than 50, which is too early if you're wanting to run softflowd on a tunnel / vpn interface.

I added a graceful shutdown sequence. If this isn't done, the process simply exits without expiring the flows and sending them to the server, which is undesirable.

if you particularly want to use taskset and pin it to a core, then here's my patch that adds taskset and renice to util-linux

diff --git a/package/utils/util-linux/Makefile b/package/utils/util-linux/Makefile
index f4b870cc47..deccea7707 100644
--- a/package/utils/util-linux/Makefile
+++ b/package/utils/util-linux/Makefile
@@ -398,6 +398,15 @@ define Package/partx-utils/description
  contains partx, addpart, delpart
 endef
 
+define Package/renice
+$(call Package/util-linux/Default)
+  TITLE:=Alter the priority of running processes
+endef
+
+define Package/renice/description
+ Alter the priority of running processes
+endef
+
 define Package/script-utils
 $(call Package/util-linux/Default)
   TITLE:=make and replay typescript of terminal session
@@ -443,6 +452,15 @@ define Package/swap-utils/description
  contains: mkswap, swaplabel
 endef
 
+define Package/taskset
+$(call Package/util-linux/Default)
+  TITLE:=Set or retrieve a task's CPU affinity
+endef
+
+define Package/taskset/description
+ Alter the priority of running processes
+endef
+
 define Package/unshare
 $(call Package/util-linux/Default)
   TITLE:=unshare userspace tool
@@ -739,6 +757,11 @@ define Package/partx-utils/install
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/delpart $(1)/usr/sbin/
 endef
 
+define Package/renice/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/renice $(1)/usr/bin/
+endef
+
 define Package/script-utils/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/script $(1)/usr/bin/
@@ -761,6 +784,11 @@ define Package/swap-utils/install
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/swaplabel $(1)/usr/sbin/
 endef
 
+define Package/taskset/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/taskset $(1)/usr/bin/
+endef
+
 define Package/unshare/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/unshare $(1)/usr/bin/
@@ -823,10 +851,12 @@ $(eval $(call BuildPackage,nsenter))
 $(eval $(call BuildPackage,prlimit))
 $(eval $(call BuildPackage,rename))
 $(eval $(call BuildPackage,partx-utils))
+$(eval $(call BuildPackage,renice))
 $(eval $(call BuildPackage,script-utils))
 $(eval $(call BuildPackage,setterm))
 $(eval $(call BuildPackage,sfdisk))
 $(eval $(call BuildPackage,swap-utils))
+$(eval $(call BuildPackage,taskset))
 $(eval $(call BuildPackage,unshare))
 $(eval $(call BuildPackage,uuidd))
 $(eval $(call BuildPackage,uuidgen))
2 Likes

Nice. I'm stumbling upon this post via search, because I had adopted the custom version by @RuralRoots at Help with Softflowd and exporting netflow data to PRTG - #23 by RuralRoots, but it now refuses to start after I updated from a nightly trunk (19.07.x? circa Feb. 2021) to the 19.07.8 release (circa Aug. 2021).

I tried your version, which works as is. However, am I hallucinating? I had export version set to "10" in the nightly trunk (19.07.x? circa Feb. 2021) without issue, but now softflowd refuses to start up because of this.

2 posts were merged into an existing topic: Help with Softflowd and exporting netflow data to PRTG