summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2014-09-12 14:42:01 -0700
committerMike Christie <michaelc@cs.wisc.edu>2014-09-21 19:50:40 -0500
commit76a441ba0dc0071a19daeac456aa898889437efd (patch)
tree78dcd836ae024972973045b75da79ddb3afa2f51 /utils
parent147db3c723c3e605a887bb50887a1b4d114b85a1 (diff)
downloadopen-iscsi-76a441ba0dc0071a19daeac456aa898889437efd.tar.gz
Added new util script to aid in CNA setup
Signed-off-by: Lee Duncan <lduncan@suse.com>
Diffstat (limited to 'utils')
-rwxr-xr-xutils/iscsi_offload378
1 files changed, 378 insertions, 0 deletions
diff --git a/utils/iscsi_offload b/utils/iscsi_offload
new file mode 100755
index 0000000..7cd1dad
--- /dev/null
+++ b/utils/iscsi_offload
@@ -0,0 +1,378 @@
+#!/bin/bash
+#
+# iscsi_offload
+#
+# Configure iSCSI offload engines for use with open-iscsi
+# Usage:
+# iscsi_offload [-d | -f | -i <ipaddr> | -t ] <nic>
+#
+# Copyright (c) 2011 Hannes Reinecke, SUSE Labs
+# This script is licensed under the GPL.
+#
+# The script creates an open-iscsi interface definition
+# in the style <nic>-<module>, where <nic> matches the
+# network interface passed on the commandline.
+# If '-t' (test mode) is passed as an option, the script
+# will not create nor modify any setting but just print
+# the currently active ones.
+#
+# Currently the script works with Broadcom (bnx2i) and
+# Chelsio T3 (cxgbi) iSCSI offload engines.
+# Should work with Chelsio T4, but has not been tested.
+# ServerEngines (be2iscsi) and QLogic (qla4xxx) can only
+# be configured via BIOS, open-iscsi support is still in
+# development.
+#
+
+#
+# Return codes:
+# 0: Success
+# 1: Invalid command line parameter
+# 2: iSCSI offloading not supported
+# 3: Error during module loading
+# 4: Cannot configure interface via iscsiadm, use BIOS setup
+# 5: internal error running iscsiadm
+#
+# Output:
+# <mac> [none|dhcp|ip <ipaddr>|ibft]
+# where
+# <mac>: MAC Address of the iSCSI offload engine
+# none: No IP configuration set for the iSCSI offload engine
+# dhcp: iSCSI offload engine configured for DHCP
+# ip: iSCSI offload engine configured with static IP address <ipaddr>
+# ibft: iSCSI offload engine configured from iBFT values
+#
+
+#
+# Figure out the MAC address of the iSCSI offload engine
+# corresponding to a NIC from a given PCI device.
+# bnx2 is using one PCI device per port for both network and iSCSI offloading
+# cxgb3 is using one PCI device for everything.
+#
+iscsi_macaddress_from_pcidevice()
+{
+ local path=$1
+ local if=$2
+ local h
+ local host
+
+ for h in $path/host* ; do
+ if [ -d "$h" ] ; then
+ host=${h##*/}
+ read netdev < /sys/class/iscsi_host/$host/netdev
+ if [ "$netdev" = "$IFNAME" ] ; then
+ read mac < /sys/class/iscsi_host/$host/hwaddress
+ if [ "$mac" != "00:00:00:00:00:00" ] ; then
+ echo "$mac"
+ fi
+ break;
+ fi
+ fi
+ done
+}
+
+#
+# Figure out the MAC address of the iSCSI offload engine
+# corresponding to a NIC from a given PCI function.
+# It is assumed that the MAC address of the iSCSI offload
+# engine is equal of the MAC address of the NIC plus one.
+# Suitable for be2iscsi and qla4xxx
+#
+iscsi_macaddress_from_pcifn()
+{
+ local path=$1
+ local if=$2
+ local h
+ local host
+ local ifmac
+
+ ifmac=$(ip addr show dev $if | sed -n 's/ *link\/ether \(.*\) brd.*/\1/p')
+ m5=$(( 0x${ifmac##*:} ))
+ m5=$(( $m5 + 1 ))
+ ifmac=$(printf "%s:%02x" ${ifmac%:*} $m5)
+ for host in /sys/class/iscsi_host/host* ; do
+ if [ -L "$host" ] ; then
+ read mac < $host/hwaddress
+ if [ "$mac" = "$ifmac" ] ; then
+ echo "$mac"
+ break;
+ fi
+ fi
+ done
+}
+
+update_iface_setting() {
+ local iface="$1"
+ local name="$2"
+ local value="$3"
+
+ iface_value=$(iscsiadm -m iface -I $iface | sed -n "s/$name = \(.*\)/\1/p")
+ if [ "$iface_value" = "<empty>" ] ; then
+ iface_value=
+ fi
+ if [ "$iface_value" != "$value" ] ; then
+ if ! iscsiadm -m iface -I $iface -o update -n "$name" -v "$value" ; then
+ return 1
+ fi
+ fi
+ return 0
+}
+
+while getopts di:t options ; do
+ case $options in
+ d ) mode=dhcp;;
+ i ) mode=static
+ optaddr=$OPTARG
+ ;;
+ f ) mode=firmware;;
+ t ) dry_run=1;;
+ ?) printf "Usage: %s [-d|-t|-i ipaddr|-f] ifname\n" $0
+ exit 1;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+IFNAME=$1
+ibft_mode="none"
+
+if [ -z "$IFNAME" ] ; then
+ echo "No interface specified"
+ exit 1
+fi
+
+if [ "$dry_run" ] ; then
+ if [ "$mode" = "dhcp" ] ; then
+ echo "'-t' specified, ignoring '-d'"
+ mode=
+ elif [ "$mode" = "static" ] ; then
+ echo "'-t' specified, ignoring '-s'"
+ mode=
+ fi
+fi
+
+if [ ! -L /sys/class/net/$IFNAME ] ; then
+ echo "Interface $IFNAME not found"
+ exit 1
+fi
+
+if [ "$optaddr" ] && ! ip route get $optaddr ; then
+ echo "Invalid IP address $optaddr"
+ exit 1
+fi
+if [ "$dry_run" ] ; then
+ mode=
+fi
+
+
+ifpath=$(cd -P /sys/class/net/$IFNAME; echo $PWD)
+pcipath=$(cd -P $ifpath/device; echo $PWD)
+
+if [ -d $pcipath ] ; then
+ drvlink=$(readlink $pcipath/driver)
+ driver=${drvlink##*/}
+fi
+
+if [ -z "$driver" ] ; then
+ echo "No driver found for interface $IFNAME"
+ exit 1
+fi
+
+case "$driver" in
+ bnx2*)
+ mod=bnx2i
+ ;;
+ cxgb*)
+ mod=cxgb3i
+ ;;
+ be2*)
+ mod=be2iscsi
+ ;;
+ qla*)
+ mod=qla4xxx
+ ;;
+esac
+
+if [ -z "$mod" ] ; then
+ echo "iSCSI offloading not supported on interface $IFNAME"
+ exit 2
+fi
+
+# Check if the required modules are already loaded
+loaded=$(sed -n "/^$mod/p" /proc/modules)
+if [ -z "$loaded" ] ; then
+ modprobe $mod
+fi
+
+loaded=$(sed -n "/^$mod/p" /proc/modules)
+if [ -z "$loaded" ] ; then
+ echo "Loading of $mod.ko failed, please check dmesg"
+ exit 3
+fi
+
+# Get the correct MAC address for the various devices
+if [ "$mod" = "bnx2i" ] ; then
+ mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
+elif [ "$mod" = "cxgb3i" ] ; then
+ mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
+elif [ "$mod" = "be2iscsi" ] ; then
+ mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME)
+elif [ "$mod" = "qla4xxx" ] ; then
+ mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME)
+fi
+
+if [ -z "$mac" ] ; then
+ echo "iSCSI offloading not supported on interface $IFNAME"
+ exit 2
+fi
+
+gen_iface="$mod.$mac"
+ioe_iface="${IFNAME}-${mod}"
+
+# Get existing settings
+if iscsiadm -m iface -I $ioe_iface > /dev/null 2>&1 ; then
+ ioe_mac=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.hwaddress = \(.*\)/\1/p")
+ ioe_mod=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.transport_name = \(.*\)/\1/p")
+ ipaddr=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
+ if [ "$ipaddr" == "<empty>" ] ; then
+ ipaddr=
+ fi
+elif [ "$mod" = "be2iscsi" ] ; then
+ ioe_mac=$mac
+ ioe_mod=$mod
+else
+ # Create new interface
+ iscsiadm -m iface -I $ioe_iface --op=new 2> /dev/null
+ ioe_mac=
+ ioe_mod=
+ ipaddr=
+fi
+
+if [ -z "$dry_run" ] ; then
+ if [ "$ioe_mac" != "$mac" ] ; then
+ if [ -n "$ioe_mac" ] ; then
+ echo "Warning: Updating MAC address on iface $ioe_iface"
+ fi
+ update_iface_setting $ioe_iface iface.hwaddress "$mac"
+ fi
+
+ if [ "$ioe_mod" != "$mod" ] ; then
+ if [ -n "$ioe_mod" ] ; then
+ echo "Warning: Update transport on iface $ioe_iface"
+ fi
+ update_iface_setting $ioe_iface iface.transport_name "$mod"
+ fi
+elif [ -z "$ipaddr" ] ; then
+ ipaddr=$(iscsiadm -m iface -I $gen_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
+ if [ "$ipaddr" = "<empty>" ] ; then
+ ipaddr=
+ fi
+elif [ "$ioe_mod" != "$mod" ] ; then
+ echo "Warning: Transport mismatch on iface $ioe_iface: $ioe_mod should be $mod"
+fi
+
+# Check iBFT setting
+for d in /sys/firmware/* ; do
+ [ -d $d ] || continue
+ [ -d $d/ethernet0 ] || continue
+ iboot_dir=$d
+done
+if [ -n "$iboot_dir" ] && [ -d "$iboot_dir" ] ; then
+ for if in ${iboot_dir}/ethernet* ; do
+ read ibft_mac < $if/mac
+ [ "$ibft_mac" = "$mac" ] || continue
+ ibft_origin=0
+ [ -f ${if}/origin ] && read ibft_origin < $if/origin
+ if [ "$ibft_origin" -eq 1 ] ; then
+ ibft_mode="static"
+ elif [ "$ibft_origin" -eq 3 ] ; then
+ ibft_mode="dhcp"
+ fi
+ [ -f $if/dhcp ] && read ibft_dhcp < $if/dhcp
+ if [ -n "$ibft_dhcp" -a "$ibft_mode" != "dhcp" ] ; then
+ ibft_mode=dhcp
+ fi
+ if [ "$ibft_mode" = "dhcp" ] ; then
+ ibft_ipaddr="0.0.0.0"
+ ibft_gateway=
+ ibft_mask=
+ break
+ fi
+ [ -f $if/ip-addr ] && read ibft_ipaddr < $if/ip-addr
+ [ -f $if/gateway ] && read ibft_gateway < $if/gateway
+ [ -f $if/subnet-mask ] && read ibft_mask < $if/subnet-mask
+ break
+ done
+fi
+
+if [ -z "$optaddr" ] && [ "$ibft_ipaddr" ] ; then
+ optaddr=$ibft_ipaddr
+fi
+
+# Check if the interface needs to be configured
+if [ -z "$mode" ] ; then
+ if [ "$ibft_mode" != "none" ] ; then
+ echo "$mac ibft"
+ mode="ibft"
+ elif [ -z "$ipaddr" ] ; then
+ echo "$mac none"
+ mode="none"
+ elif [ "$ipaddr" = "0.0.0.0" ] ; then
+ echo "$mac dhcp"
+ ipaddr=
+ mode="dhcp"
+ else
+ echo "$mac ip $ipaddr"
+ mode="static"
+ fi
+ [ "$dry_run" ] && exit 0
+elif [ "$mode" = "dhcp" ] ; then
+ if [ "$ipaddr" = "0.0.0.0" ] ; then
+ echo "$mac dhcp"
+ exit 0
+ fi
+ optaddr="0.0.0.0"
+elif [ "$mode" = "static" ] && [ "$ipaddr" = "$optaddr" ] ; then
+ echo "$mac ip $ipaddr"
+ exit 0
+fi
+
+if [ "$mod" = "be2iscsi" ] ; then
+ exit 4
+fi
+
+if ! update_iface_setting $ioe_iface iface.ipaddress "$optaddr" ; then
+ echo "Failed to set IP address: $?"
+ exit 1
+fi
+if ! update_iface_setting $gen_iface iface.ipaddress "$optaddr" ; then
+ echo "Failed to set IP address for generic interface: $?"
+ exit 1
+fi
+
+if ! update_iface_setting $ioe_iface iface.gateway "$ibft_gateway" ; then
+ echo "Failed to set gateway address: $?"
+ exit 1
+fi
+
+if ! update_iface_setting $gen_iface iface.gateway "$ibft_gateway" ; then
+ echo "Failed to set gateway address for generic interface: $?"
+ exit 1
+fi
+
+if ! update_iface_setting $ioe_iface iface.subnet_mask "$ibft_mask" ; then
+ echo "Failed to set subnet mask: $?"
+ exit 1
+fi
+
+if ! update_iface_setting $gen_iface iface.subnet_mask "$ibft_mask" ; then
+ echo "Failed to set subnet mask for generic interface: $?"
+ exit 1
+fi
+
+if [ "$mod" = "qla4xxx" ] ; then
+ iscsiadm -m iface -H $mac -o applyall
+fi
+ip link set dev $IFNAME up
+
+exit 0
+