From 80f767d09390e69baeeca3f039e2b44bad4c6913 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Thu, 3 Dec 2015 16:25:19 +0000
Subject: [PATCH] base-files: uci-defaults-new, config_generate: refactor code
 and drop old vlans

Remove support for now unused ucidef_add_switch_vlan(), move port->vlan and
vlan->interfaces conversion to uci-defaults-new.sh and massively simplify
config_generate.

This change prepares the following upcoming steps:

 * Eliminate use of ucidef_set_interface_lan_wan() for switch only devices
 * Merge ucidef_add_switch() with ucidef_add_switch_ports()

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>

SVN-Revision: 47719
---
 package/base-files/files/bin/config_generate  | 227 ++++--------------
 .../files/lib/functions/uci-defaults-new.sh   | 158 ++++++++----
 2 files changed, 157 insertions(+), 228 deletions(-)

diff --git a/package/base-files/files/bin/config_generate b/package/base-files/files/bin/config_generate
index 1aa6d43e3f..7e0e2acd3b 100755
--- a/package/base-files/files/bin/config_generate
+++ b/package/base-files/files/bin/config_generate
@@ -20,34 +20,26 @@ generate_static_network() {
 	EOF
 }
 
-next_vlan=3
 generate_network() {
-	local vlan
+	local ifname macaddr type
 
 	json_select network
-	json_select "$1"
-	json_get_vars ifname create_vlan macaddr
-	json_select ..
+		json_select "$1"
+			json_get_vars ifname macaddr
+		json_select ..
 	json_select ..
 
 	[ -n "$ifname" ] || return
 
-	if [ "${create_vlan:-0}" -eq 1 ]; then
-		case "$1" in
-			lan) vlan=1;;
-			wan) vlan=2;;
-			*)
-				vlan=$next_vlan
-				next_vlan=$((next_vlan + 1))
-			;;
-		esac
-	fi
-
-	[ -n "$vlan" ] && ifname=${ifname}.${vlan}
+	# force bridge for multi-interface devices (and lan)
+	case "$1:$ifname" in
+		*\ * | lan:*) type="bridge" ;;
+	esac
 
 	uci -q batch <<-EOF
 		delete network.$1
 		set network.$1='interface'
+		set network.$1.type='$type'
 		set network.$1.ifname='$ifname'
 		set network.$1.proto='none'
 		set network.$1.macaddr='$macaddr'
@@ -56,198 +48,82 @@ generate_network() {
 	case "$1" in
 		lan)
 			uci -q batch <<-EOF
-				set network.$1.type='bridge'
 				set network.$1.proto='static'
 				set network.$1.ipaddr='192.168.1.1'
 				set network.$1.netmask='255.255.255.0'
 				set network.$1.ip6assign='60'
 			EOF
 		;;
-
 		wan)
 			uci -q batch <<-EOF
 				set network.$1.proto='dhcp'
 				delete network.wan6
 				set network.wan6='interface'
+				set network.wan6.type='$type'
 				set network.wan6.ifname='$ifname'
 				set network.wan6.proto='dhcpv6'
 			EOF
 		;;
-
-		*)
-			uci -q batch <<-EOF
-				set network.$1.force_link=1
-			EOF
-		;;
 	esac
 }
 
-generate_switch_vlan() {
-	local device="$1"
-	local vlan="$2"
-	local cpu_port="$3"
+generate_switch_vlans_ports() {
+	local switch="$1"
+	local port ports role roles num attr val
 
-	case "$vlan" in
-		lan) vlan=1;;
-		wan) vlan=2;;
-		*) vlan="${vlan##vlan}";;
-	esac
+	#
+	# autogenerate vlans
+	#
+
+	json_get_keys roles roles
+	json_select roles
+
+	for role in $roles; do
+		json_select "$role"
+			json_get_vars ports
+		json_select ..
+
+		uci -q batch <<-EOF
+			add network switch_vlan
+			set network.@switch_vlan[-1].device='$switch'
+			set network.@switch_vlan[-1].vlan='$role'
+			set network.@switch_vlan[-1].ports='$ports'
+		EOF
+	done
 
-	json_select vlans
-	json_select "$2"
-	json_get_values ports
-	json_select ..
 	json_select ..
 
-	uci -q batch <<-EOF
-		add network switch_vlan
-		set network.@switch_vlan[-1].device='$device'
-		set network.@switch_vlan[-1].vlan='$vlan'
-		set network.@switch_vlan[-1].ports='$ports ${cpu_port}t'
-	EOF
-}
 
-calculate_switch_vlans() {
-	local switch="$1"
-	local ports port attr val prev_role
-	local num device role index need_tag
-	local cpu0 cpu1 cpu2 cpu3
-	local dev0 dev1 dev2 dev3
-	local tag0 tag1 tag2 tag3
-	local role0 role1 role2 role3
-	local n_cpu=0  n_vlan=0 vlan_off=-1
-	local vlan_ports cpu_port
+	#
+	# write port specific settings
+	#
 
 	json_get_keys ports ports
-
 	json_select ports
 
-	# gather all cpu ports and count vlans
 	for port in $ports; do
 		json_select "$port"
-		json_get_vars num device role need_tag
-
-		if json_is_a attr object; then
-			json_get_keys attr attr
-			json_select attr
-
-			uci -q batch <<-EOF
-				add network switch_port
-				set network.@switch_port[-1].device='$switch'
-				set network.@switch_port[-1].port=$num
-			EOF
-
-			for attr in $attr; do
-				json_get_var val "$attr"
-				uci -q set network.@switch_port[-1].$attr="$val"
-			done
-
-			json_select ..
-		fi
-
-		json_select ..
-
-		if [ -n "$num" ] && [ -n "$device" ]; then
-			export "cpu$n_cpu=$num"
-			export "dev$n_cpu=$device"
-			export "tag$n_cpu=${need_tag:-0}"
-			n_cpu=$((n_cpu + 1))
-		elif [ -n "$num" ] && [ -n "$role" ] && [ "$role" != "$prev_role" ]; then
-			export "role$n_vlan=$role"
-			n_vlan=$((n_vlan + 1))
-			prev_role="$role"
-		fi
-	done
-
-	unset prev_role
-
-	# autogenerate vlans
-	for port in $ports ""; do
-		if [ -n "$port" ]; then
-			json_select "$port"
-			json_get_vars num device role
-			json_select ..
-		else
-			num="-"; role="-"
-		fi
-
-		if [ -n "$num" ] && [ -n "$role" ]; then
-			if [ "$role" != "$prev_role" ]; then
-				if [ -n "$vlan_ports" ]; then
-					let cpu_port="cpu$((vlan_off % n_cpu))"
-					let need_tag="tag$((vlan_off % n_cpu))"
-					[ $n_vlan -gt $n_cpu -o $need_tag -eq 1 ] && cpu_port="${cpu_port}t"
+			json_get_vars num
 
+			if json_is_a attr object; then
+				json_get_keys attr attr
+				json_select attr
 					uci -q batch <<-EOF
-						add network switch_vlan
-						set network.@switch_vlan[-1].device='$switch'
-						set network.@switch_vlan[-1].vlan='$((vlan_off + 1))'
-						set network.@switch_vlan[-1].ports='$vlan_ports $cpu_port'
+						add network switch_port
+						set network.@switch_port[-1].device='$switch'
+						set network.@switch_port[-1].port=$num
 					EOF
-				fi
 
-				vlan_off=$((vlan_off + 1))
-				vlan_ports="$num"
-				prev_role="$role"
-			else
-				vlan_ports="$vlan_ports $num"
+					for attr in $attr; do
+						json_get_var val "$attr"
+						uci -q set network.@switch_port[-1].$attr="$val"
+					done
+				json_select ..
 			fi
-
-		fi
+		json_select ..
 	done
 
 	json_select ..
-
-	# autogenerate interfaces
-	vlan_off=0; while [ $vlan_off -lt $n_vlan ]; do
-		eval role="\$role$((vlan_off))"
-		eval device="\$dev$((vlan_off % n_cpu))"
-		let need_tag="tag$((vlan_off++ % n_cpu))"
-		[ $n_vlan -gt $n_cpu -o $need_tag -eq 1 ] && device="$device.$vlan_off"
-
-		# quirk: append ifnames for subsequent switches
-		case "$switch" in switch[1-9])
-			local prev_devs="$(uci -q get "network.$role.ifname")"
-			if echo "$prev_devs" | grep -wq "$device"; then
-				device="$prev_devs"
-			else
-				device="$prev_devs $device"
-			fi
-		;; esac
-
-		uci -q batch <<-EOF
-			set network.$role='interface'
-			set network.$role.ifname='$device'
-		EOF
-
-		case $role in
-			lan)
-				uci -q batch <<-EOF
-					set network.lan.type='bridge'
-					set network.lan.proto='static'
-					set network.lan.ipaddr='192.168.1.1'
-					set network.lan.netmask='255.255.255.0'
-					set network.lan.ip6assign='60'
-				EOF
-			;;
-
-			wan)
-				uci -q batch <<-EOF
-					set network.wan.proto='dhcp'
-					set network.wan6='interface'
-					set network.wan6.ifname='$device'
-					set network.wan6.proto='dhcpv6'
-				EOF
-			;;
-
-			*)
-				uci -q batch <<-EOF
-					set network.$role.force_link='1'
-					set network.$role.proto='none'
-				EOF
-			;;
-		esac
-	done
 }
 
 generate_switch() {
@@ -266,12 +142,7 @@ generate_switch() {
 		set network.@switch[-1].blinkrate='$blinkrate'
 	EOF
 
-	if [ -n "$cpu_port" ]; then
-		json_get_keys vlans vlans
-		for vlan in $vlans; do generate_switch_vlan $1 $vlan $cpu_port; done
-	elif json_is_a ports array; then
-		calculate_switch_vlans $1
-	fi
+	generate_switch_vlans_ports "$1"
 
 	json_select ..
 	json_select ..
diff --git a/package/base-files/files/lib/functions/uci-defaults-new.sh b/package/base-files/files/lib/functions/uci-defaults-new.sh
index ae23d22a79..4a7cca4df0 100755
--- a/package/base-files/files/lib/functions/uci-defaults-new.sh
+++ b/package/base-files/files/lib/functions/uci-defaults-new.sh
@@ -2,6 +2,7 @@
 
 CFG=/etc/board.json
 
+. /lib/functions.sh
 . /usr/share/libubox/jshn.sh
 
 json_select_array() {
@@ -33,8 +34,7 @@ _ucidef_set_interface() {
 	local iface="$2"
 
 	json_select_object "$name"
-	json_add_string ifname "${iface%%.*}"
-	[ "$iface" = "${iface%%.*}" ] || json_add_boolean create_vlan 1
+	json_add_string ifname "$iface"
 	json_select ..
 }
 
@@ -114,28 +114,123 @@ ucidef_add_switch_attr() {
 	json_select ..
 }
 
+_ucidef_add_switch_port() {
+	# inherited: $num $device $need_tag $role $index $prev_role
+	# inherited: $n_cpu $n_ports $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5
+
+	n_ports=$((n_ports + 1))
+
+	json_select_array ports
+		json_add_object
+			json_add_int num "$num"
+			[ -n "$device"   ] && json_add_string  device   "$device"
+			[ -n "$need_tag" ] && json_add_boolean need_tag "$need_tag"
+			[ -n "$role"     ] && json_add_string  role     "$role"
+			[ -n "$index"    ] && json_add_int     index    "$index"
+		json_close_object
+	json_select ..
+
+	# record pointer to cpu entry for lookup in _ucidef_finish_switch_roles()
+	[ -n "$device" ] && {
+		export "cpu$n_cpu=$n_ports"
+		n_cpu=$((n_cpu + 1))
+	}
+
+	# create/append object to role list
+	[ -n "$role" ] && {
+		json_select_array roles
+
+		if [ "$role" != "$prev_role" ]; then
+			json_add_object
+				json_add_string role "$role"
+				json_add_string ports "$num"
+			json_close_object
+
+			prev_role="$role"
+			n_vlan=$((n_vlan + 1))
+		else
+			json_select_object "$n_vlan"
+				json_get_var port ports
+				json_add_string ports "$port $num"
+			json_select ..
+		fi
+
+		json_select ..
+	}
+}
+
+_ucidef_finish_switch_roles() {
+	# inherited: $name $n_cpu $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5
+	local index role roles num device need_tag port ports
+
+	json_select switch
+		json_select "$name"
+			json_get_keys roles roles
+		json_select ..
+	json_select ..
+
+	for index in $roles; do
+		eval "port=\$cpu$(((index - 1) % n_cpu))"
+
+		json_select switch
+			json_select "$name"
+				json_select ports
+					json_select "$port"
+						json_get_vars num device need_tag
+					json_select ..
+				json_select ..
+
+				if [ $n_vlan -gt $n_cpu -o ${need_tag:-0} -eq 1 ]; then
+					num="${num}t"
+					device="${device}.${index}"
+				fi
+
+				json_select roles
+					json_select "$index"
+						json_get_vars role ports
+						json_add_string ports "$ports $num"
+						json_add_string device "$device"
+					json_select ..
+				json_select ..
+			json_select ..
+		json_select ..
+
+		json_select_object network
+			json_select_object "$role"
+				# attach previous interfaces (for multi-switch devices)
+				local prev_device; json_get_var prev_device ifname
+				if ! list_contains prev_device "$device"; then
+					device="${prev_device:+$prev_device }$device"
+				fi
+				json_add_string ifname "$device"
+			json_select ..
+		json_select ..
+	done
+}
+
 ucidef_add_switch_ports() {
 	local name="$1"; shift
-	local port num role dev idx tag
+	local port num role device index need_tag prev_role
+	local cpu0 cpu1 cpu2 cpu3 cpu4 cpu5
+	local n_cpu=0 n_vlan=0 n_ports=0
 
 	json_select_object switch
 	json_select_object "$name"
-	json_select_array ports
 
 	for port in "$@"; do
 		case "$port" in
 			[0-9]*@*)
 				num="${port%%@*}"
-				dev="${port##*@}"
-				tag=0
+				device="${port##*@}"
+				need_tag=0
 				[ "${num%t}" != "$num" ] && {
 					num="${num%t}"
-					tag=1
+					need_tag=1
 				}
 			;;
 			[0-9]*:*:[0-9]*)
 				num="${port%%:*}"
-				idx="${port##*:}"
+				index="${port##*:}"
 				role="${port#[0-9]*:}"; role="${role%:*}"
 			;;
 			[0-9]*:*)
@@ -144,22 +239,17 @@ ucidef_add_switch_ports() {
 			;;
 		esac
 
-		if [ -n "$num" ] && [ -n "$dev$role" ]; then
-			json_add_object
-			json_add_int num "$num"
-			[ -n "$dev" ] && json_add_string device "$dev"
-			[ -n "$tag" ] && json_add_boolean need_tag "$tag"
-			[ -n "$role" ] && json_add_string role "$role"
-			[ -n "$idx" ] && json_add_int index "$idx"
-			json_close_object
+		if [ -n "$num" ] && [ -n "$device$role" ]; then
+			_ucidef_add_switch_port
 		fi
 
-		unset num dev role idx tag
+		unset num device role index need_tag
 	done
 
 	json_select ..
 	json_select ..
-	json_select ..
+
+	_ucidef_finish_switch_roles
 }
 
 ucidef_add_switch_port_attr() {
@@ -198,38 +288,6 @@ ucidef_add_switch_port_attr() {
 	json_select ..
 }
 
-ucidef_add_switch_vlan() {
-	local name="$1"
-	local vlan="$2"
-	local ports="$3"
-	local cpu_port=''
-
-	case "$vlan" in
-	1)	vlan=lan;;
-	2)	vlan=wan;;
-	*)	vlan=vlan$vlan;;
-	esac
-
-	json_select_object switch
-	json_select_object "$name"
-	json_select_object vlans
-
-	json_add_array "$vlan"
-	for p in $ports; do
-		if [ ${p%t} != $p ]; then
-			cpu_port=$p
-		else
-			json_add_int "" $p
-		fi
-	done
-	json_close_array
-
-	json_select ..
-	[ -n "$cpu_port" ] && json_add_int cpu_port "$cpu_port"
-	json_select ..
-	json_select ..
-}
-
 ucidef_set_interface_macaddr() {
 	local network="$1"
 	local macaddr="$2"
-- 
2.34.1