File s390-tools-sles15sp3-hsci-Add-new-tool-to-control-HiperSockets-Converged-.patch of Package s390-tools.19916

From ef090dda8333a778cb2d9e7f65ca8021e2ae9e67 Mon Sep 17 00:00:00 2001
From: Karsten Graul <kgraul@linux.ibm.com>
Date: Tue, 10 Nov 2020 12:07:03 +0100
Subject: [PATCH] hsci: Add new tool to control HiperSockets Converged
 Interfaces
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

hsci is used to control and show HSCI (HiperSockets Converged Interfaces)
settings. A HiperSockets interface and an external network interface are
converged to an HSCI interface.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
---
 Makefile      |   2 +-
 README.md     |   3 +
 hsci/Makefile |  16 ++
 hsci/hsci     | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hsci/hsci.8   | 100 ++++++++++++
 5 files changed, 561 insertions(+), 1 deletion(-)
 create mode 100644 hsci/Makefile
 create mode 100755 hsci/hsci
 create mode 100644 hsci/hsci.8

diff --git a/Makefile b/Makefile
index cc277b8e..cfbbd950 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
 	   vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
 	   ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
 	   systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
-	   genprotimg lsstp
+	   genprotimg lsstp hsci
 
 SUB_DIRS = $(LIB_DIRS) $(TOOL_DIRS)
 
diff --git a/README.md b/README.md
index aa2188a5..581353fd 100644
--- a/README.md
+++ b/README.md
@@ -249,6 +249,9 @@ Package contents
    Management Foundation - Web Edition, and is used to manage keys in an
    enterprise.
 
+ * hsci:
+   Manage HiperSockets Converged Interfaces (HSCI).
+
 For more information refer to the following publications:
 
   * "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
diff --git a/hsci/Makefile b/hsci/Makefile
new file mode 100644
index 00000000..6f7474c5
--- /dev/null
+++ b/hsci/Makefile
@@ -0,0 +1,16 @@
+include ../common.mak
+
+all:
+
+install: hsci
+	$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
+	< hsci >$(DESTDIR)$(BINDIR)/hsci; \
+	chown $(OWNER).$(GROUP) $(DESTDIR)$(BINDIR)/hsci; \
+	chmod 755 $(DESTDIR)$(BINDIR)/hsci; \
+	$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
+	$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 hsci.8 \
+		$(DESTDIR)$(MANDIR)/man8
+
+clean:
+
+.PHONY: all install clean
diff --git a/hsci/hsci b/hsci/hsci
new file mode 100755
index 00000000..9a56aa0d
--- /dev/null
+++ b/hsci/hsci
@@ -0,0 +1,441 @@
+#!/bin/bash
+#
+# hsci - Tool to manage HiperSockets Converged Interfaces (HSCI)
+#
+# Copyright IBM Corp. 2020
+#
+# s390-tools is free software; you can redistribute it and/or modify
+# it under the terms of the MIT license. See LICENSE for details.
+#
+
+hsdev=""
+ndev=""
+hsci=""
+hsdev_mac=""
+hsif_pnetid=""
+netif_pnetid=""
+hsci_pnetid=""
+
+function usage {
+cat <<-EOD
+Usage: hsci COMMAND [OPTION]
+
+This tool is designed to control and show HSCI (HiperSockets Converged
+Interfaces) settings. A HiperSockets interface and an external network
+
+COMMANDS
+        add HIPERSOCKETS_DEV NET_DEV    Adds an HSCI interface
+        del HSCI_NAME                   Deletes an HSCI interface
+        show                            Lists the configured HSCI interfaces
+
+OPTIONS:
+        -v, --version                   Prints the version number of the hsci tool and exits
+        -h, --help                      Displays the help information for the command
+EOD
+}
+
+function prereqs_check {
+	if ! [ -x "$(command -v ip)" ]; then
+		echo "Error: No iproute2 installed on this system" >&2
+		return 1
+	fi
+}
+
+function check_pnetids {
+	# get PNETID of the HS
+	local hsif_pnetids=""
+	local netif_pnetids=""
+
+	if [ -e /sys/class/net/$hsdev/device/util_string ]; then
+		hsif_pnetids="$(cat /sys/class/net/$hsdev/device/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
+	else
+		if [ -e /sys/class/net/$hsdev/device/chpid ]; then
+			chpid="$(cat /sys/class/net/$hsdev/device/chpid | tr [:upper:] [:lower:])"
+			hsif_pnetids="$(cat /sys/devices/css0/chp0.$chpid/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
+		fi
+	fi
+	if [ "$hsif_pnetids" != "" ]; then
+		port_hsif="$(cat /sys/class/net/$hsdev/dev_port)"
+		(( idx=16*$port_hsif+1 ))
+		(( end=$idx+15 ))
+		hsif_pnetid="$(echo "$hsif_pnetids" | cut -c $idx-$end | tr -d ' ')"
+	fi
+
+	# get PNETID of the NET_DEV
+	if [ -e /sys/class/net/$ndev/device/util_string ]; then
+		netif_pnetids="$(cat /sys/class/net/$ndev/device/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
+	else
+		if [ -e /sys/class/net/$ndev/device/chpid ]; then
+			chpid="$(cat /sys/class/net/$ndev/device/chpid | tr [:upper:] [:lower:])"
+			netif_pnetids="$(cat /sys/devices/css0/chp0.$chpid/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
+		fi
+	fi
+	if [ "$netif_pnetids" != "" ]; then
+		port_netif="$(cat /sys/class/net/$ndev/dev_port)"
+		(( idx=16*$port_netif+1 ))
+		(( end=$idx+15 ))
+		netif_pnetid="$(echo "$netif_pnetids" | cut -c $idx-$end | tr -d ' ')"
+	fi
+
+	#Check PNETIDs
+	if [ "$hsif_pnetid" != "" ] && [ "$netif_pnetid" != "" ] && [ "$netif_pnetid" != "$hsif_pnetid" ]; then
+		echo "Error: $hsdev and $ndev have different PNETIDs! They are $hsif_pnetid and $netif_pnetid respectively" >&2
+		return 1
+	fi
+
+	if [ "$hsif_pnetid" != "" ] && [ "$netif_pnetid" != "" ] && [ "$netif_pnetid" == "$hsif_pnetid" ]; then
+		hsci_pnetid=$hsif_pnetid
+	fi
+}
+
+function verify_precon {
+	echo "Verifying net dev $ndev and HiperSockets dev $hsdev"
+
+	if [ ! -e /sys/class/net/$hsdev ]; then
+		echo "Error: $hsdev does not exist" >&2
+		return 1
+	fi
+	if [ "$(cat /sys/class/net/$hsdev/device/card_type)" != "HiperSockets" ]; then
+		echo "Error: $hsdev is not a HiperSockets device" >&2
+		return 1
+	fi
+	if [ "$(cat /sys/class/net/$hsdev/device/layer2)" != "1" ]; then
+		echo "Error: $hsdev is not in layer 2 mode" >&2
+		return 1
+	fi
+	if [ ! -e /sys/class/net/$hsdev/device/vnicc/bridge_invisible ]; then
+		echo "Error: Missing vnic-characteristics support" >&2
+		return 1
+	fi
+	if [ "$(cat /sys/class/net/$hsdev/device/vnicc/bridge_invisible)" == "n/a" ]; then
+		echo "Error: $hsdev does not support vnicc" >&2
+		return 1
+	fi
+	if [ $(ip link show $hsdev | grep UP | wc -l) -eq 0 ]; then
+		echo "Error: $hsdev is not in state UP" >&2
+		return 1
+	fi
+	if [ $(bridge -d link show dev $hsdev self | grep learning_sync | wc -l) -eq 0 ]; then
+		echo "Error: $hsdev does not support attribute learning_sync" >&2
+		return 1
+	fi
+	if [ $(ip link show $hsdev | grep master | wc -l) -ne 0 ]; then
+		echo "Error: $hsdev is already a bridge port" >&2
+		return 1
+	fi
+
+	#Pre-verify net_dev
+	if [ ! -e /sys/class/net/$ndev ]; then
+		echo "Error: $ndev does not exist" >&2
+		return 1
+	fi
+	if [ "$(cat /sys/class/net/$ndev/device/card_type)" == "HiperSockets" ]; then
+		echo "Error: $ndev is also a HiperSockets device" >&2
+		return 1
+	fi
+	if [ $(ip link show $ndev | grep UP | wc -l) -eq 0 ]; then
+		echo "Error: $ndev is not in state UP" >&2
+		return 1
+	fi
+	if [ $(ip link show $ndev | grep master | wc -l) -ne 0 ]; then
+		echo "Error: $ndev is already a bridge port" >&2
+		return 1
+	fi
+
+	#Check PNETIDs
+	check_pnetids
+	if [ $? -ne 0 ]; then
+		return $?
+	fi
+
+	return 0
+}
+
+function clean_up {
+	bridge link set dev $hsdev learning_sync off self >/dev/null 2>&1
+	echo 0 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible >/dev/null 2>&1
+	bridge fdb del $hsdev_mac dev $ndev >/dev/null 2>&1
+	ip link del $hsci >/dev/null 2>&1
+}
+
+##############################################################################
+##	add a new HSCI interface
+##############################################################################
+function add_hsci {
+
+	if [ $# != 2 ]; then
+		echo "hsci: Invalid parameters" >&2
+		echo "Use 'hsci --help' for more information" >&2
+		return 1
+	fi
+	hsdev=$1
+	ndev=$2
+
+	#### Verify preconditions
+	verify_precon
+	if [ $? -ne 0 ]; then
+		return $?
+	fi
+
+	hsci_postfix="$(readlink /sys/class/net/$hsdev/device/cdev0 | tail -c5)"
+	hsci=hsci$hsci_postfix
+
+	echo "Adding $hsci with a HiperSockets dev $hsdev and an external dev $ndev"
+
+	#### Create bridge
+	ip link add name $hsci type bridge stp_state 0 >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Could not create a bridge" >&2
+		return 1
+	fi
+
+	#### Prepare hsdev
+	# Set VNICC of hsdev to invisible
+	#(mandatory for co-existence with HS-OSA bridges!)
+	echo 1 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible
+
+	#### Create bridge ports
+	ip link set dev $ndev master $hsci >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Could not set master for $ndev" >&2
+		clean_up
+		return 1
+	fi
+	ip link set dev $hsdev master $hsci >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Could not set master for $hsdev" >&2
+		clean_up
+		return 1
+	fi
+
+	# no forwarding between ndev and hsdev -> isolated on
+	# ndev is default for outgoing unknown targets -> flood on
+	# no need to learn external LAN targets into fdb -> learning off
+	bridge link set dev $ndev isolated on learning off flood on mcast_flood on >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to set bridge attributes on $ndev" >&2
+		clean_up
+		return 1
+	fi
+
+	# no forwarding between ndev and hsdev -> isolated on
+	# fdb will be populated by dev-to-bridge-notification, no need to learn
+	#	-> learning off
+	# only send to hsdev, if listed in fdb -> flood off
+	# don't send MC/BC on hsdev -> mcast_flood off
+	bridge link set dev $hsdev isolated on learning off flood off mcast_flood off >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to set bridge attributes on $hsdev" >&2
+		clean_up
+		return 1
+	fi
+
+	# NOTE: Although not required, BCs will be sent out on hsdev.
+	# NOTE: We need to receive BCs on hsdev, as z/OS HSCI does ARP requests on HS.
+
+	hsdev_mac="$(cat /sys/class/net/$hsdev/address)"
+	echo "Set $hsdev MAC $hsdev_mac on $ndev and $hsci"
+
+	# set HS MAC on OSA as secondary MAC
+	bridge fdb add $hsdev_mac dev $ndev >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to set HS MAC on OSA as secondary MAC" >&2
+		clean_up
+		return 1
+	fi
+
+	# set HS MAC (common MAC) on HSCI as primary MAC
+	ip link set address $hsdev_mac dev $hsci >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to set HiperSockets MAC (common MAC) on HSCI as primary MAC" >&2
+		clean_up
+		return 1
+	fi
+
+	# use hsdev MTU
+	if [ -e /sys/class/net/$hsdev/mtu ]; then
+		hs_mtu="$(cat /sys/class/net/$hsdev/mtu)"
+		ip link set dev $hsci mtu $hs_mtu >/dev/null 2>&1
+		if [ $? -ne 0 ]; then
+			echo "Error: Failed to set MTU for $hsci " >&2
+			clean_up
+			return 1
+		fi
+	fi
+	ip link set dev $hsci up >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to set $hsci up" >&2
+		clean_up
+		return 1
+	fi
+
+	# Turn on device for bridge notification
+	bridge link set dev $hsdev learning_sync on self >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to turn on device for bridge notification" >&2
+		clean_up
+		return 1
+	fi
+	echo "Successfully added HSCI interface $hsci"
+	return 0
+}
+
+##############################################################################
+##	Delete HSCI
+##############################################################################
+
+function del_hsci {
+	if [ $# != 1 ]; then
+		echo "hsci: invalid parameters" >&2
+		echo "Use 'hsci --help' for more information" >&2
+		return 1
+	fi
+	hsci=$1
+	if [ $(ip link show dev $hsci | wc -l) -eq 0 ]; then
+		echo "Error: $hsci does not exit" >&2
+		return 1
+	fi
+	if [ $(ip link show | grep "master $hsci" | wc -l) -eq 0 ]; then
+		echo "Error: $hsci is not an active HSCI interface" >&2
+		return 1
+	fi
+
+	bports="$(ip link show | grep "master $hsci" | awk '{print $2}')"
+	for bport in $bports; do
+		if [ $(bridge -d link show dev $bport | grep "learning_sync on" | wc -l) -ne 0 ]; then
+			hsdev=${bport%:}
+		else
+			ndev=${bport%:}
+		fi
+	done
+	if [ "$hsdev" == "" ]; then
+		echo "Error: $hsci has no active HiperSockets port" >&2
+		return 1
+	fi
+	echo "Deleting HSCI interface $hsci with the HiperSockets $hsdev and the external $ndev"
+
+	bridge link set dev $hsdev learning_sync off self >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to turn off learning_sync on $hsdev" >&2
+		return 1
+	fi
+	echo 0 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible
+
+	hsdev_mac="$(cat /sys/class/net/$hsdev/address)"
+	echo "Deleting $hsev MAC $hsdev_mac on $ndev"
+	bridge fdb del $hsdev_mac dev $ndev >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to delete $hsev MAC $hsdev_mac on $ndev" >&2
+		return 1
+	fi
+
+	ip link del $hsci >/dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		echo "Error: Failed to delete $hsci" >&2
+		return 1
+	fi
+	echo "Successfully deleted device $hsci"
+
+	return 0
+}
+
+##############################################################################
+##	Show HSCI
+##############################################################################
+
+function list_active {
+	hsdev=$1
+	local ext=""
+
+	hsci="$(ip link show dev $hsdev | awk '{for(x=1;x<NF;x++) if($x~/master/) print $(x+1)}')"
+	ext="$(ip link show | grep "master $hsci" | grep --invert-match $hsdev | awk '{print $2}')"
+	# remove trailing ':'
+	ndev="${ext%:}"
+
+	check_pnetids
+
+	printf '%-8s  %-16s  %-15s  %-15s\n' "$hsci" "$hsci_pnetid" "$hsdev" "$ndev"
+
+	return 0
+}
+
+function print_header {
+	if [ $header -eq 0 ]; then
+		echo "HSCI      PNET_ID           HiperSockets     External       "
+		echo "------------------------------------------------------------"
+	fi
+}
+
+function list_one {
+	local hsnetdev=$1
+
+	if [ $(bridge -d link show dev $hsnetdev | grep	 "learning_sync on" | wc -l) -ne 0 ]; then
+		print_header
+		list_active $hsnetdev
+	fi
+
+	return 0
+}
+
+function show_hsci {
+	if [ $# != 0 ]; then
+		echo "hsci: invalid parameters" >&2
+		echo "Use 'hsci --help' for more information" >&2
+		return 1
+	fi
+	header=0
+
+	for hs_net_dev in $(ls -1 /sys/class/net/); do
+		list_one $hs_net_dev
+	done
+
+	return 0
+}
+
+#==============================================================================
+
+function print_version()
+{
+	echo "hsci utility: version %S390_TOOLS_VERSION%"
+	echo "Copyright IBM Corp. 2020"
+}
+
+##############################################################################
+##### Main
+##############################################################################
+prereqs_check
+
+args="$(getopt -u -o hv -l help,version -- $*)"
+[ $? -ne 0 ] && exit 2
+set -- $args
+while true; do
+	case $1 in
+		-v | --version)
+			print_version
+			exit 0
+			;;
+		-h | --help)
+			usage
+			exit 0
+			;;
+		--)
+			;;
+		add)	shift
+			add_hsci "$@"
+			exit $?
+			;;
+		del)	shift
+			del_hsci "$@"
+			exit $?
+			;;
+		show)	shift
+			show_hsci "$@"
+			exit $?
+			;;
+		*)	echo "hsci: Please specify a valid command or option" >&2
+			echo "Use 'hsci --help' for more information" >&2
+			exit 1
+	esac
+	shift
+done
+
diff --git a/hsci/hsci.8 b/hsci/hsci.8
new file mode 100644
index 00000000..fc170532
--- /dev/null
+++ b/hsci/hsci.8
@@ -0,0 +1,100 @@
+.\" Copyright IBM Corp. 2020
+
+.TH HSCI 8 "November 2020" "s390-tools" "Linux Programmer's Manual"
+
+
+.SH NAME
+.B hsci
+\- control and show HSCI settings.
+
+
+.SH SYNOPSIS
+.B hsci add
+.I HSDEV
+.I NETDEV
+.br
+.B hsci del
+.I HSCINAME
+.br
+.B hsci show
+.br
+.B hsci [\-hv]
+
+.SH DESCRIPTION
+.BI hsci
+is used to control and show HSCI (HiperSockets Converged Interfaces) settings. A HiperSockets interface and an external network interface are converged into an HSCI interface.
+
+.SH COMMANDS
+.TP
+.B add \fIHSDEV\fR \fINETDEV\fR
+.RS .4i
+.PP
+Adds an HSCI interface
+.PP
+.I HSDEV
+is the interface name of the HiperSockets device to be converged into the HSCI interface.
+.PP
+.I NETDEV
+is the interface name of the external network device to be converged into the HSCI interface.
+.RE
+
+.TP
+.B del \fIHSCINAME\fR
+.RS .4i
+.PP
+Deletes an HSCI interface
+.PP
+.I HSCINAME
+is the name of the HSCI interface for the HiperSockets device and the external network device.
+.RE
+
+.TP
+.B show
+.RS .4i
+.PP
+Lists the configured HSCI interfaces.
+.RE
+
+.SH OPTIONS
+.TP
+.BR \-v ", " \-\-version
+Prints the version number of hsci and exits.
+.TP
+.BR \-h ", " \-\-help
+Displays the help information for the command.
+
+.SH EXIT CODES
+.TP
+.BR "0"
+The hsci command ran successfully.
+
+.TP
+.BR "1"
+An error occurred.
+
+.SH EXAMPLE
+.BR "hsci show"
+.TP
+.RB
+Lists the configured HSCI interfaces:
+.RS 1.2i
+
+HSCI      PNET_ID  HiperSockets  External
+.br
+-----------------------------------------
+.br
+hsci8410  NET1     enc8410       encb040
+
+.RE
+
+.SH SEE ALSO
+.nf
+ip(8), bridge(8)
+.fi
+
+.SH AUTHOR
+.nf
+Written by Alexandra Winter <wintera@linux.ibm.com>
+           Wenjia Zhang <wenjia@linux.ibm.com>
+.fi
+
-- 
2.17.1

openSUSE Build Service is sponsored by