Blame utils/iscsi_offload

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