diff options
Diffstat (limited to 'modules.d/95fcoe')
-rwxr-xr-x | modules.d/95fcoe/cleanup-fcoe.sh | 15 | ||||
-rwxr-xr-x | modules.d/95fcoe/fcoe-edd.sh | 54 | ||||
-rwxr-xr-x | modules.d/95fcoe/fcoe-up.sh | 106 | ||||
-rwxr-xr-x | modules.d/95fcoe/lldpad.sh | 19 | ||||
-rwxr-xr-x | modules.d/95fcoe/module-setup.sh | 122 | ||||
-rwxr-xr-x | modules.d/95fcoe/parse-fcoe.sh | 106 | ||||
-rwxr-xr-x | modules.d/95fcoe/stop-fcoe.sh | 6 |
7 files changed, 428 insertions, 0 deletions
diff --git a/modules.d/95fcoe/cleanup-fcoe.sh b/modules.d/95fcoe/cleanup-fcoe.sh new file mode 100755 index 0000000..210fb94 --- /dev/null +++ b/modules.d/95fcoe/cleanup-fcoe.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +if [ -e /var/run/lldpad.pid ]; then + lldpad -k + # with systemd version 230, this is not necessary anymore + # systemd commit cacf980ed44a28e276a6cc7f8fc41f991e2ab354 + if [ -z "$DRACUT_SYSTEMD" ]; then + # shellcheck disable=SC2174 + mkdir -m 0755 -p /run/initramfs/state/dev/shm + cp /dev/shm/lldpad.state /run/initramfs/state/dev/shm/ > /dev/null 2>&1 + echo "files /dev/shm/lldpad.state" >> /run/initramfs/rwtab + fi +fi diff --git a/modules.d/95fcoe/fcoe-edd.sh b/modules.d/95fcoe/fcoe-edd.sh new file mode 100755 index 0000000..17f8a7c --- /dev/null +++ b/modules.d/95fcoe/fcoe-edd.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +dcb="$1" + +_modprobe_r_edd="0" + +check_edd() { + local cnt=0 + + [ -d /sys/firmware/edd ] && return 0 + + _modprobe_r_edd="1" + modprobe edd || return $? + + while [ $cnt -lt 600 ]; do + [ -d /sys/firmware/edd ] && return 0 + cnt=$((cnt + 1)) + sleep 0.1 + done + return 1 +} + +check_edd || exit 1 + +for disk in /sys/firmware/edd/int13_*; do + [ -d "$disk" ] || continue + if [ -e "${disk}/pci_dev/driver" ]; then + driver=$(readlink "${disk}/pci_dev/driver") + driver=${driver##*/} + fi + # i40e uses dev_port 1 for a virtual fcoe function + if [ "${driver}" = "i40e" ]; then + dev_port=1 + fi + for nic in "${disk}"/pci_dev/net/*; do + [ -d "$nic" ] || continue + if [ -n "${dev_port}" -a -e "${nic}/dev_port" ]; then + if [ "$(cat "${nic}"/dev_port)" -ne "${dev_port}" ]; then + continue + fi + fi + if [ -e "${nic}"/address ]; then + fcoe_interface=${nic##*/} + if ! [ -e "/tmp/.fcoe-$fcoe_interface" ]; then + /sbin/fcoe-up "$fcoe_interface" "$dcb" + : > "/tmp/.fcoe-$fcoe_interface" + fi + fi + done +done + +[ "$_modprobe_r_edd" = "1" ] && modprobe -r edd + +unset _modprobe_r_edd diff --git a/modules.d/95fcoe/fcoe-up.sh b/modules.d/95fcoe/fcoe-up.sh new file mode 100755 index 0000000..0828f03 --- /dev/null +++ b/modules.d/95fcoe/fcoe-up.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# We get called like this: +# fcoe-up <network-device> <dcb|nodcb> <fabric|vn2vn> +# +# Note currently only nodcb is supported, the dcb option is reserved for +# future use. + +PATH=/usr/sbin:/usr/bin:/sbin:/bin +type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh +type ip_to_var > /dev/null 2>&1 || . /lib/net-lib.sh + +# Huh? Missing arguments ?? +[ -z "$1" -o -z "$2" ] && exit 1 + +netif=$1 +dcb=$2 +mode=$3 +vlan="yes" + +read -r iflink < /sys/class/net/"$netif"/iflink +read -r ifindex < /sys/class/net/"$netif"/ifindex +if [ "$iflink" != "$ifindex" ]; then + # Skip VLAN devices + exit 0 +fi + +ip link set dev "$netif" up +linkup "$netif" + +# Some fcoemon implementations expect --syslog=true +syslogopt="--syslog" +if fcoemon -h | grep syslog | grep -q yes; then + syslogopt="$syslogopt=yes" +fi + +netdriver=$(readlink -f /sys/class/net/"$netif"/device/driver) +netdriver=${netdriver##*/} + +write_fcoemon_cfg() { + [ -f /etc/fcoe/cfg-"$netif" ] && return + echo FCOE_ENABLE=\"yes\" > /etc/fcoe/cfg-"$netif" + if [ "$dcb" = "dcb" ]; then + echo DCB_REQUIRED=\"yes\" >> /etc/fcoe/cfg-"$netif" + else + echo DCB_REQUIRED=\"no\" >> /etc/fcoe/cfg-"$netif" + fi + if [ "$vlan" = "yes" ]; then + echo AUTO_VLAN=\"yes\" >> /etc/fcoe/cfg-"$netif" + else + echo AUTO_VLAN=\"no\" >> /etc/fcoe/cfg-"$netif" + fi + if [ "$mode" = "vn2vn" ]; then + echo MODE=\"vn2vn\" >> /etc/fcoe/cfg-"$netif" + else + echo MODE=\"fabric\" >> /etc/fcoe/cfg-"$netif" + fi +} + +if [ "$netdriver" = "bnx2x" ]; then + # If driver is bnx2x, do not use /sys/module/fcoe/parameters/create but fipvlan + modprobe 8021q + udevadm settle --timeout=30 + # Sleep for 13 s to allow dcb negotiation + sleep 13 + fipvlan "$netif" -c -s + need_shutdown + exit +fi +if [ "$dcb" = "dcb" ]; then + # wait for lldpad to be ready + i=0 + while [ $i -lt 60 ]; do + lldptool -p && break + info "Waiting for lldpad to be ready" + sleep 1 + i=$((i + 1)) + done + + while [ $i -lt 60 ]; do + dcbtool sc "$netif" dcb on && break + info "Retrying to turn dcb on" + sleep 1 + i=$((i + 1)) + done + + while [ $i -lt 60 ]; do + dcbtool sc "$netif" pfc e:1 a:1 w:1 && break + info "Retrying to turn dcb on" + sleep 1 + i=$((i + 1)) + done + + while [ $i -lt 60 ]; do + dcbtool sc "$netif" app:fcoe e:1 a:1 w:1 && break + info "Retrying to turn fcoe on" + sleep 1 + i=$((i + 1)) + done + + sleep 1 +fi +write_fcoemon_cfg +fcoemon $syslogopt + +need_shutdown diff --git a/modules.d/95fcoe/lldpad.sh b/modules.d/95fcoe/lldpad.sh new file mode 100755 index 0000000..f992ae2 --- /dev/null +++ b/modules.d/95fcoe/lldpad.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +if ! getargbool 1 rd.fcoe -d -n rd.nofcoe; then + info "rd.fcoe=0: skipping lldpad activation" + return 0 +fi + +# Note lldpad will stay running after switchroot, the system initscripts +# are to kill it and start a new lldpad to take over. Data is transferred +# between the 2 using a shm segment +lldpad -d +# wait for lldpad to be ready +i=0 +while [ $i -lt 60 ]; do + lldptool -p && break + info "Waiting for lldpad to be ready" + sleep 1 + i=$((i + 1)) +done diff --git a/modules.d/95fcoe/module-setup.sh b/modules.d/95fcoe/module-setup.sh new file mode 100755 index 0000000..3de85c2 --- /dev/null +++ b/modules.d/95fcoe/module-setup.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# called by dracut +check() { + is_fcoe() { + block_is_fcoe "$1" || return 1 + } + + [[ $hostonly ]] || [[ $mount_needs ]] && { + for_each_host_dev_and_slaves is_fcoe || return 255 + } + + require_binaries dcbtool fipvlan lldpad ip readlink fcoemon fcoeadm tr || return 1 + return 0 +} + +# called by dracut +depends() { + echo network rootfs-block + return 0 +} + +# called by dracut +installkernel() { + instmods fcoe libfcoe 8021q edd bnx2fc +} + +get_vlan_parent() { + local link=$1 + + [ -d "$link" ] || return + read -r iflink < "$link"/iflink + for if in /sys/class/net/*; do + read -r idx < "$if"/ifindex + if [ "$idx" -eq "$iflink" ]; then + echo "${if##*/}" + fi + done +} + +# called by dracut +cmdline() { + { + for c in /sys/bus/fcoe/devices/ctlr_*; do + [ -L "$c" ] || continue + read -r enabled < "$c"/enabled + read -r mode < "$c"/mode + [ "$enabled" -eq 0 ] && continue + if [ "$mode" = "VN2VN" ]; then + mode="vn2vn" + else + mode="fabric" + fi + d=$( + cd -P "$c" || exit + echo "$PWD" + ) + i=${d%/*} + ifname=${i##*/} + read -r mac < "${i}"/address + s=$(dcbtool gc "${i##*/}" dcb 2> /dev/null | sed -n 's/^DCB State:\t*\(.*\)/\1/p') + if [ -z "$s" ]; then + p=$(get_vlan_parent "${i}") + if [ "$p" ]; then + s=$(dcbtool gc "${p}" dcb 2> /dev/null | sed -n 's/^DCB State:\t*\(.*\)/\1/p') + ifname=${p##*/} + fi + fi + if [ "$s" = "on" ]; then + dcb="dcb" + else + dcb="nodcb" + fi + + # Some Combined Network Adapters(CNAs) implement DCB in firmware. + # Do not run software-based DCB or LLDP on CNAs that implement DCB. + # If the network interface provides hardware DCB/DCBX capabilities, + # DCB_REQUIRED in "/etc/fcoe/cfg-xxx" is expected to set to "no". + # + # Force "nodcb" if there's any DCB_REQUIRED="no"(child or vlan parent). + if grep -q '^[[:blank:]]*DCB_REQUIRED="no"' /etc/fcoe/cfg-"${i##*/}" &> /dev/null; then + dcb="nodcb" + fi + + if [ "$p" ]; then + if grep -q '^[[:blank:]]*DCB_REQUIRED="no"' /etc/fcoe/cfg-"${p}" &> /dev/null; then + dcb="nodcb" + fi + fi + + echo "ifname=${ifname}:${mac}" + echo "fcoe=${ifname}:${dcb}:${mode}" + done + } | sort | uniq +} + +# called by dracut +install() { + inst_multiple ip dcbtool fipvlan lldpad readlink lldptool fcoemon fcoeadm tr + if [[ -e $dracutsysrootdir/etc/hba.conf ]]; then + inst_libdir_file 'libhbalinux.so*' + inst_simple "/etc/hba.conf" + fi + + mkdir -m 0755 -p "$initdir/var/lib/lldpad" + mkdir -m 0755 -p "$initdir/etc/fcoe" + + if [[ $hostonly_cmdline == "yes" ]]; then + local _fcoeconf + _fcoeconf=$(cmdline) + [[ $_fcoeconf ]] && printf "%s\n" "$_fcoeconf" >> "${initdir}/etc/cmdline.d/95fcoe.conf" + fi + inst_multiple "/etc/fcoe/cfg-*" + + inst "$moddir/fcoe-up.sh" "/sbin/fcoe-up" + inst "$moddir/fcoe-edd.sh" "/sbin/fcoe-edd" + inst_hook pre-trigger 03 "$moddir/lldpad.sh" + inst_hook cmdline 99 "$moddir/parse-fcoe.sh" + inst_hook cleanup 90 "$moddir/cleanup-fcoe.sh" + inst_hook shutdown 40 "$moddir/stop-fcoe.sh" + dracut_need_initqueue +} diff --git a/modules.d/95fcoe/parse-fcoe.sh b/modules.d/95fcoe/parse-fcoe.sh new file mode 100755 index 0000000..bde6b62 --- /dev/null +++ b/modules.d/95fcoe/parse-fcoe.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# Supported formats: +# fcoe=<networkdevice>:<dcb|nodcb>:<fabric|vn2vn> +# fcoe=<macaddress>:<dcb|nodcb>:<fabric|vn2vn> +# +# Note currently only nodcb is supported, the dcb option is reserved for +# future use. +# +# Note letters in the macaddress must be lowercase! +# +# Examples: +# fcoe=eth0:nodcb:vn2vn +# fcoe=4a:3f:4c:04:f8:d7:nodcb:fabric + +if [ -z "$fcoe" ] && ! getarg fcoe=; then + # If it's not set we don't continue + return 0 +fi + +if ! getargbool 1 rd.fcoe -d -n rd.nofcoe; then + info "rd.fcoe=0: skipping fcoe" + return 0 +fi + +if ! [ -e /sys/bus/fcoe/ctlr_create ] && ! modprobe -b -a fcoe && ! modprobe -b -a libfcoe; then + die "FCoE requested but kernel/initrd does not support FCoE" +fi + +initqueue --onetime modprobe -b -q bnx2fc + +parse_fcoe_opts() { + local fcoe_interface + local fcoe_dcb + local fcoe_mode + local fcoe_mac + local OLDIFS="$IFS" + local IFS=: + # shellcheck disable=SC2086 + # shellcheck disable=SC2048 + set -- $* + IFS="$OLDIFS" + + case $# in + 2) + fcoe_interface=$1 + fcoe_dcb=$2 + fcoe_mode="fabric" + unset fcoe_mac + ;; + 3) + fcoe_interface=$1 + fcoe_dcb=$2 + fcoe_mode=$3 + unset fcoe_mac + ;; + 7) + fcoe_mac=$(echo "$1:$2:$3:$4:$5:$6" | tr "[:upper:]" "[:lower:]") + fcoe_dcb=$7 + fcoe_mode="fabric" + unset fcoe_interface + ;; + 8) + fcoe_mac=$(echo "$1:$2:$3:$4:$5:$6" | tr "[:upper:]" "[:lower:]") + fcoe_dcb=$7 + fcoe_mode=$8 + unset fcoe_interface + ;; + *) + warn "Invalid arguments for fcoe=$fcoe" + return 1 + ;; + esac + + if [ "$fcoe_dcb" != "nodcb" -a "$fcoe_dcb" != "dcb" ]; then + warn "Invalid FCoE DCB option: $fcoe_dcb" + fi + + if [ "$fcoe_interface" = "edd" ]; then + /sbin/initqueue --settled --unique /sbin/fcoe-edd "$fcoe_dcb" + return 0 + fi + + if [ -z "$fcoe_interface" -a -z "$fcoe_mac" ]; then + warn "fcoe: Neither interface nor MAC specified for fcoe=$fcoe" + return 1 + fi + + { + if [ -n "$fcoe_mac" ]; then + # shellcheck disable=SC2016 + printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/initqueue --onetime --unique --name fcoe-up-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_mac" "$fcoe_dcb" "$fcoe_mode" + # shellcheck disable=SC2016 + printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/initqueue --onetime --timeout --unique --name fcoe-timeout-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_mac" "$fcoe_dcb" "$fcoe_mode" + else + # shellcheck disable=SC2016 + printf 'ACTION=="add", SUBSYSTEM=="net", NAME=="%s", RUN+="/sbin/initqueue --onetime --unique --name fcoe-up-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_interface" "$fcoe_dcb" "$fcoe_mode" + # shellcheck disable=SC2016 + printf 'ACTION=="add", SUBSYSTEM=="net", NAME=="%s", RUN+="/sbin/initqueue --onetime --timeout --unique --name fcoe-timeout-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_interface" "$fcoe_dcb" "$fcoe_mode" + fi + } >> /etc/udev/rules.d/92-fcoe.rules +} + +for fcoe in $fcoe $(getargs fcoe=); do + parse_fcoe_opts "$fcoe" +done diff --git a/modules.d/95fcoe/stop-fcoe.sh b/modules.d/95fcoe/stop-fcoe.sh new file mode 100755 index 0000000..a89cbbc --- /dev/null +++ b/modules.d/95fcoe/stop-fcoe.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +for f in /sys/bus/fcoe/devices/ctlr_*; do + [ -e "$f" ] || continue + echo 0 > "$f"/enabled +done |