From 7996908046d8e86e33f7c93ff45f73cb815a1c24 Mon Sep 17 00:00:00 2001
From: Helge Mader <ma@dev.tdt.de>
Date: Mon, 11 Jun 2018 15:52:15 +0200
Subject: [PATCH] net/bonding: added protohandler package for netifd

Signed-off-by: Helge Mader <ma@dev.tdt.de>
---
 net/bonding/Makefile                          |  41 ++++
 net/bonding/files/lib/netifd/proto/bonding.sh | 211 ++++++++++++++++++
 2 files changed, 252 insertions(+)
 create mode 100644 net/bonding/Makefile
 create mode 100755 net/bonding/files/lib/netifd/proto/bonding.sh

diff --git a/net/bonding/Makefile b/net/bonding/Makefile
new file mode 100644
index 000000000..c808666b3
--- /dev/null
+++ b/net/bonding/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2018 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=proto-bonding
+PKG_VERSION:=2018-06-11
+PKG_RELEASE:=1
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_MAINTAINER:=Helge Mader <ma@dev.tdt.de>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/proto-bonding
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=Link Aggregation (Channel Bonding) proto handler
+  DEPENDS:=+kmod-bonding
+endef
+
+define Package/proto-bonding/description
+  This package contains the channel bonding proto handler for netifd
+endef
+
+define Build/Compile
+endef
+
+define Package/proto-bonding/install
+	$(INSTALL_DIR) $(1)/lib/netifd/proto/
+	$(INSTALL_BIN) ./files/lib/netifd/proto/bonding.sh \
+		$(1)/lib/netifd/proto/
+endef
+
+$(eval $(call BuildPackage,proto-bonding))
diff --git a/net/bonding/files/lib/netifd/proto/bonding.sh b/net/bonding/files/lib/netifd/proto/bonding.sh
new file mode 100755
index 000000000..b624738fe
--- /dev/null
+++ b/net/bonding/files/lib/netifd/proto/bonding.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+#
+# Copyright (C) 2018 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+. /lib/functions.sh
+. ../netifd-proto.sh
+
+init_proto "$@"
+
+INCLUDE_ONLY=1
+
+BONDING_MASTERS="/sys/class/net/bonding_masters"
+
+set_driver_values() {
+	local varname
+
+	for varname in "$@"; do
+		local value
+		json_get_var value "$varname"
+
+		[ -n "$value" ] && echo "$value" > /sys/class/net/"$link"/bonding/"$varname"
+	done
+}
+
+proto_bonding_init_config() {
+	no_device=1
+	available=1
+
+	proto_config_add_string "ifname"
+
+	proto_config_add_string "ipaddr"
+	proto_config_add_string "netmask"
+
+	proto_config_add_string "bonding_policy"
+	proto_config_add_string "link_monitoring"
+	proto_config_add_string "slaves"
+	proto_config_add_string "all_slaves_active"
+
+	proto_config_add_string "min_links"
+	proto_config_add_string "ad_actor_sys_prio"
+	proto_config_add_string "ad_actor_system"
+	proto_config_add_string "ad_select"
+	proto_config_add_string "lacp_rate"
+	proto_config_add_string "packets_per_slave"
+	proto_config_add_string "xmit_hash_policy"
+	proto_config_add_string "primary"
+	proto_config_add_string "primary_reselect"
+	proto_config_add_string "lp_interval"
+	proto_config_add_string "tlb_dynamic_lb"
+	proto_config_add_string "resend_igmp"
+	proto_config_add_string "fail_over_mac"
+	proto_config_add_string "num_grat_arp__num_unsol_na"
+
+	proto_config_add_string "arp_interval"
+	proto_config_add_string "arp_ip_target"
+	proto_config_add_string "arp_all_targets"
+	proto_config_add_string "arp_validate"
+
+	proto_config_add_string "miimon"
+	proto_config_add_string "downdelay"
+	proto_config_add_string "updelay"
+	proto_config_add_string "use_carrier"
+}
+
+proto_bonding_setup() {
+	local cfg="$1"
+	local link="bonding-$cfg"
+
+	# Check for loaded kernel bonding driver (/sys/class/net/bonding_masters exists)
+	[ -f "$BONDING_MASTERS" ] || {
+		echo "$cfg" "setup: bonding_masters does not exist in sysfs (kernel module not loaded?)"
+		proto_notify_error "$cfg" "setup: bonding_masters does not exist in sysfs (kernel module not loaded?)"
+		proto_block_restart "$cfg"
+		return
+	}
+
+	# Add bonding interface to system
+	echo "+$link" > "$BONDING_MASTERS"
+
+	# Set bonding policy (with corresponding parameters)
+	local bonding_policy
+	json_get_vars bonding_policy
+
+	case "$bonding_policy" in
+
+		802.3ad)
+			echo "$bonding_policy" > /sys/class/net/"$link"/bonding/mode
+			set_driver_values min_links ad_actor_sys_prio ad_actor_system ad_select lacp_rate
+		;;
+
+		balance-rr)
+			echo "$bonding_policy" > /sys/class/net/"$link"/bonding/mode
+			set_driver_values packets_per_slave xmit_hash_policy
+		;;
+
+		balance-tlb)
+			echo "$bonding_policy" > /sys/class/net/"$link"/bonding/mode
+			set_driver_values primary primary_reselect lp_interval tlb_dynamic_lb resend_igmp xmit_hash_policy
+		;;
+
+		balance-alb)
+			echo "$bonding_policy" > /sys/class/net/"$link"/bonding/mode
+			set_driver_values primary primary_reselect lp_interval tlb_dynamic_lb resend_igmp xmit_hash_policy
+		;;
+
+		active-backup)
+			echo "$bonding_policy" > /sys/class/net/"$link"/bonding/mode
+			set_driver_values primary primary_reselect fail_over_mac num_grat_arp__num_unsol_na xmit_hash_policy
+		;;
+        esac
+
+	# Set link monitoring (with corresponding parameters)
+	local link_monitoring
+	json_get_vars link_monitoring
+
+	case "$link_monitoring" in
+
+		arp)
+			local arp_interval arp_ip_target arp_all_targets arp_validate
+			json_get_vars arp_interval arp_ip_target arp_all_targets arp_validate
+
+			[ -n "$arp_interval" -a "$arp_interval" != 0 ] && echo "$arp_interval" > /sys/class/net/"$link"/bonding/arp_interval
+
+			IFS=' '
+			for target in $arp_ip_target; do
+				echo "+$target" > /sys/class/net/"$link"/bonding/arp_ip_target
+			done
+
+			[ -n "$arp_all_targets" ] && echo "$arp_all_targets" > /sys/class/net/"$link"/bonding/arp_all_targets
+			[ -n "$arp_validate" ] && echo "$arp_validate" > /sys/class/net/"$link"/bonding/arp_validate
+		;;
+
+		mii)
+			local miimon downdelay updelay use_carrier
+			json_get_vars miimon downdelay updelay use_carrier
+
+			[ -n "$miimon" -a "$miimon" != 0 ] && echo "$miimon" > /sys/class/net/"$link"/bonding/miimon
+			[ -n "$downdelay" ] && echo "$downdelay" > /sys/class/net/"$link"/bonding/downdelay
+			[ -n "$updelay" ] && echo "$updelay" > /sys/class/net/"$link"/bonding/updelay
+			[ -n "$use_carrier" ] && echo "$use_carrier" > /sys/class/net/"$link"/bonding/use_carrier
+		;;
+	esac
+
+	# Add slaves to bonding interface
+	local slaves
+	json_get_vars slaves
+
+	for slave in $slaves; do
+
+		if [ "$(cat /proc/net/dev |grep "$slave")" == "" ]; then
+			echo "$cfg" "ERROR IN CONFIGURATION - $slave: No such device"
+			proto_notify_error "$cfg" "ERROR IN CONFIGURATION - $slave: No such device"
+			proto_block_restart "$cfg"
+			return
+		fi
+
+		ifconfig "$slave" down
+
+		sleep 1
+
+		echo "+$slave" > /sys/class/net/"$link"/bonding/slaves
+
+		ifconfig "$slave" up
+	done
+
+	[ -n "$all_slaves_active" ] && echo "$all_slaves_active" > /sys/class/net/"$link"/bonding/all_slaves_active
+
+	local ipaddr netmask
+	json_get_vars ipaddr netmask
+
+	# ATTENTION
+	#All json vars have to be read before the line below, as the
+	# json object will be overwritten by proto_init_update
+	# ATTENTION
+
+	proto_init_update "$link" 1
+
+	# For static configuration we _MUST_ have an IP address
+	[ -z "$ipaddr" ] && {
+		echo "$cfg" "INVALID LOCAL ADDRESS"
+		proto_notify_error "$cfg" "INVALID_LOCAL_ADDRESS"
+		proto_block_restart "$cfg"
+		return
+	}
+
+	proto_add_ipv4_address "$ipaddr" "$netmask"
+
+	proto_send_update "$cfg"
+}
+
+proto_bonding_teardown() {
+	local cfg="$1"
+	local link="bonding-$cfg"
+
+	# Check for loaded kernel bonding driver (/sys/class/net/bonding_masters exists)
+	[ -f "$BONDING_MASTERS" ] || {
+		echo "$cfg" "teardown: bonding_masters does not exist in sysfs (kernel module not loaded?)"
+		proto_notify_error "$cfg" "teardown: bonding_masters does not exist in sysfs (kernel module not loaded?)"
+		proto_block_restart "$cfg"
+		return
+	}
+
+	echo "-$link" > /sys/class/net/bonding_masters
+	logger "bonding_teardown($1): $2"
+}
+
+add_protocol bonding