From 3f9f6c8f47bc46448ce77617fd6febaddf8008de Mon Sep 17 00:00:00 2001
From: Marius Tomaschewski <mt@suse.de>
Date: Wed, 16 Feb 2022 19:20:27 +0100
Subject: [PATCH 5/6] hcnmgr: maintain hcnid state for later cleanup

When the LPAR has been shut down and the configuration changes then,
there is still previous bonding config (e.g. bond<old HCNID>), that
needs to be cleaned up while in hcn-init.service start (hcnmgr -s).
---
 scripts/hcnmgr | 78 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 60 insertions(+), 18 deletions(-)

diff --git a/scripts/hcnmgr b/scripts/hcnmgr
index c617960..ce34179 100644
--- a/scripts/hcnmgr
+++ b/scripts/hcnmgr
@@ -32,6 +32,7 @@ DT_PATH="/proc/device-tree"
 HCNMGR="hcnmgr"
 HCNCMD=""
 HCNTRACE=""
+STATEDIR="/var/lib/powerpc-utils/hcnmgr"
 LOG_FILE="/var/log/hcnmgr"
 HCN_LOGGING_LEVEL=DEBUG
 HCNID=0
@@ -167,6 +168,28 @@ xdump4() {
 	hexdump -n 4 -ve '/1 "%02x"' "$1"
 }
 
+hcnid_state_create()
+{
+	local hcnid="$1"
+	[ "X$hcnid" != "X" ] && mkdir -p -- "$STATEDIR/$hcnid"
+}
+hcnid_state_remove()
+{
+	local hcnid="$1"
+	[ "X$hcnid" != "X" ] && rm -rf -- "$STATEDIR/$hcnid"
+}
+hcnid_state_list()
+{
+	local revert
+
+	shopt -q nullglob ; revert=$?
+	shopt -s nullglob
+	for dir in "$STATEDIR"/* ; do
+		echo "${dir##*/}"
+	done
+	[ $revert -eq 0 ] || shopt -u nullglob
+}
+
 # function search_dev:
 #	Given DRX_INDEX, Search for device-tree, looking for migratable SR_IOV
 #	backend vnic or ibmveth device to configure hybrid network
@@ -414,6 +437,7 @@ do_config_vdevice_wicked() {
 }
 
 do_config_vdevice() {
+	hcnid_state_create "$HCNID"
 	case $SERVICE in
 		NetworkManager.service)
 			do_config_vdevice_nm
@@ -542,6 +566,7 @@ rmhcn() {
 			rmhcn_wicked
 			;;
 	esac
+	hcnid_state_remove "$HCNID"
 	hcnlog DEBUG "rmhcn: exit"
 	return $E_SUCCESS
 }
@@ -837,12 +862,14 @@ scanhcn_nm() {
 #	is inactive (or during manual 'hcnmgr -s' call).
 #
 scanhcn_wicked() {
-	local hcnids=()
+	local hcnid hcnids=()
 	local -A hcn_devs hcn_primary
 	local file dev
 
 	hcnlog DEBUG "scanhcn: on boot scan for hybrid virtual network starts"
 
+	udevadm settle
+
 	hcnlog DEBUG "search sr_iov device with ibm,hcn-id propterty......"
 	# Look at pci ethernet devices for SR_IOV VFs with ibm,hcn-id propterty
 	# join or Create bond for this hcnid if not exist, add SR-IOVs as primary
@@ -891,22 +918,37 @@ scanhcn_wicked() {
 		fi
 	done
 
-	# TODO: when the LPAR has been shut down and the configuration changes then,
-	#	e.g. from: bond$HCNID_old { eth0, eth1 }
-	#	     into: bond$HCNID_new { eth0, eth2 }
-	#	                            ^^^^
-	#     	there is still a config for bond$HCNID_old that we need to remove
-	#	at LPAR boot _before_ we can setup bond$HCNID_new as the new bond
-	#	is (re)using one slave device of the old bond..
-	#	This requires to know which bond is managed via HCN and we may need
-	#	to mark or remember the hcn managed bonds...
-
-	# (Re)configure all bonds
-	for id in "${hcnids[@]}" ; do
-		local bond="bond$id"
-		local primary="${hcn_primary[$id]}"
-		local devices="${hcn_devs[$id]}"
+	# Cleanup (and shutdown) obsolete bondings or unenslave obsolete slaves
+	# This can happen when the LPAR has been shut down and reconfigured at
+	# next boot (or as attempt to fix via manual rescan when something went
+	# wrong before).
+	for hcnid in $(hcnid_state_list) ; do
+		local bond="bond$hcnid"
+		if suse_wlist_find "$hcnid" "${hcnids[@]}" ; then
+			local devices=(${hcn_devs[$hcnid]})
+			for dev in $(suse_ifcfg_bond_get_slaves "$bond") ; do
+				suse_wlist_find "$dev" "${devices[@]}" && continue
+				suse_ifcfg_bond_del_slave "$bond" "$dev"
+				if systemctl is-active -q wicked.service ; then
+					wicked ifdown "$dev"
+				fi
+			done
+		else
+			suse_ifcfg_bond_delete "$bond"
+			if systemctl is-active -q wicked.service ; then
+				wicked ifdown "$bond"
+			fi
+			hcnid_state_remove "$hcnid"
+		fi
+	done
+
+	# Configure (and set up) actual bonds with current device list
+	for hcnid in "${hcnids[@]}" ; do
+		local bond="bond$hcnid"
+		local primary="${hcn_primary[$hcnid]}"
+		local devices="${hcn_devs[$hcnid]}"
 
+		hcnid_state_create "$hcnid"
 		hcnlog INFO "scanhcn configure HCN $bond with devices '$devices'"
 		if suse_ifcfg_bond_modify "$bond" "$devices" ; then
 			hcnlog INFO "scanhcn configured bond '$bond' config with devices '$devices'"
@@ -921,8 +963,8 @@ scanhcn_wicked() {
 		fi
 
 		if systemctl is-active -q wicked.service ; then
-			hcnlog INFO "scanhcn reloading HCN bonding: $bond"
-			wicked ifreload "$bond"
+			hcnlog INFO "scanhcn starting HCN bonding: $bond"
+			wicked ifup "$bond"
 		else
 			hcnlog INFO "scanhcn omits HCN bondings reload due to inactive network"
 			# at boot, hcn-init.service adjusts the configuration and
-- 
2.34.1

