#!/bin/sh
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html

PROG="${PROG:-${0##*/}}"
DHCPCD_ARGS="--background --noipv4ll"

msg() {
    local msg="$@"
    if [ -z "$(echo $msg | sed -e 's/[[:space:]]//g')" ]; then
        return
    fi
    echo "$PROG: $msg"
}

##
# get_netiface_mac - print to STDOUT interface MAC address
#
get_iface_mac() {
    local MTHCA_PREFIX="20:00:55:04:01"
    local FLEXBOOT_MLX4_PREFIX="ff:00:00:00:00:00:02:00:00:02:c9:00:00"
    # FlexBoot ConnectX case, append "prefix", use: "yes" or "no"
    local FLEXBOOT_MLX4="no"
    local IFACE= IF_TYPE= MAC= DRIVER= PGUID= GID=

    if [ $# != 1 ]; then
        echo "Incorrect function invocation." >&2
        echo "Use: get_iface_mac <iface>" >&2
        return
    fi

    IFACE="$1"
    IF_TYPE="$(cat "/sys/class/net/$IFACE/type")"

    if [ "$IF_TYPE" = "1" ] ; then
        # Ethernet
        MAC=`cat /sys/class/net/$IFACE/address`
    elif [ "$IF_TYPE" = "32" ] ; then
        # Infiniband
        DRIVER="$(cat /sys/class/net/$IFACE/device/uevent | grep '^DRIVER=' | cut -d '=' -f 2)"
        if [ "$DRIVER" = "mlx4_core" ] ; then
            # ConnectX
            PGUID="$(cat /sys/class/net/$IFACE/address | cut -d ':' -f 13-)"
            MAC=$PGUID
            if [ "$FLEXBOOT_MLX4" == "yes" ] ; then
                MAC="$FLEXBOOT_MLX4_PREFIX:$PGUID"
            fi
        elif [ "$DRIVER" = "ib_mthca" ] ; then
            # InfiniHost
            GID=`cat /sys/class/net/$IFACE/address | cut -d ':' -f 5-`
            MAC="$MTHCA_PREFIX:$GID"
        fi
    else
        echo "Unsupported interface: $IFACE" >&2
    fi

    if [ -n "$MAC" ]; then
        echo "$MAC"
    fi
}

##
# Startup DHCP service on specified interface
#
ifup() {
    local IFACE=
    local isIB="no"

    # Test invocation syntax
    if [ $# = 0 ]; then
        echo "Incorrect ifup invocation." >&2
        echo "Use: ifup <iface>" >&2
        return
    fi

    IFACE="$1"

    if [ $IFACE != ${IFACE#ib} ] ; then
        isIB="yes"
    fi

    #	Uncomment for debug purposes:
    #    ip a s
    #    grep ^ /sys/class/net/$IFACE/carrier
    #    grep ^ /sys/class/net/$IFACE/operstate

    if ! /sbin/ip link set up dev "$IFACE"; then
        echo "Can't up link on $IFACE device" >&2
        return
    fi

    #	Uncomment for debug purposes:
    #    ip a s
    #    grep ^ /sys/class/net/$IFACE/carrier
    #    grep ^ /sys/class/net/$IFACE/operstate

    if [ "$isIB" = "yes" ]; then
        try=0
        while [ $try -lt 50 ]; do
            CLIENT_ID="$(get_iface_mac $IFACE)"
            if [ -z "$CLIENT_ID" ]; then
                echo "Failed to acquire client-identifier, retrying..." >&2
                sleep 1
                let try=try+1
            else
                echo "client-identifier: $CLIENT_ID" >&2
                DHCPCD_ARGS="--clientid=$CLIENT_ID $DHCPCD_ARGS"
                break
            fi
        done

        #	Uncomment for debug purposes:
        #    ip a s
        #    grep ^ /sys/class/net/$IFACE/carrier
        #    grep ^ /sys/class/net/$IFACE/operstate
        #	/bin/sh

        # temp 'waiting for carrier' dhcpcd workaround:
        # in ib_ipoib case dhcpcd could not start properly if no carrier yet...
        # TODO: fix dhcpcd (quit after timeout when 'waiting for carrier'...)
        try=0
        echo -n "Waiting for carrier..."
        while [ $try -lt 10 ]; do
            if ( grep '^1$' /sys/class/net/$IFACE/carrier > /dev/null 2>&1 ); then
                echo ' Ok'
                break
            else
                echo -n '.'
                sleep 1
                let try=try+1
            fi
        done
    fi


    mkdir -p /var/lib/dhcpcd
    dhcpcd $DHCPCD_ARGS $IFACE
}

nic=0
hba=0

MOD=""
NICSTOWAIT=""
touch /etc/motd
echo "cat /etc/motd" >> /etc/profile

#Load common usb drivers
modprobe ohci-hcd
modprobe uhci-hcd
modprobe ehci-hcd

for d in /proc/sys/net/ipv4/conf/*; do 
   echo 1 > $d/arp_filter
   echo 1 > $d/arp_ignore
done
for i in $(lspci -n | awk '{print $1 "%" $3}')
do
    PCI=$(echo $i | awk -F% '{print $1}')
    VID="0x0000$(echo $i | awk -F% '{print $2}' |awk -F: '{print $1}')"
    DID="0x0000$(echo $i | awk -F% '{print $2}' |awk -F: '{print $2}')"
    if egrep "^[^   ]*[     ]*$VID[     ]*$DID" /lib/modules/`uname -r`/modules.pcimap >/dev/null
    then
        TYPE=$(
            lspci | \
            grep "^$PCI " | \
            awk '{print $2}' | \
            tr '[A-Z]' '[a-z]' | sed 's/\W//g'
        )
        DESC=$(
            lspci | \
            grep "^$PCI " | \
            awk -F: '{print $3}' | \
            sed 's/^ *//'
        )
        MOD=$(
            egrep "^[^  ]*[     ]*$VID[     ]*$DID" /lib/modules/`uname -r`/modules.pcimap | \
            head -1 | \
            awk '{print $1}' | \
            tr -d '"'
        )
        case "$TYPE" in
            ethernet|network)
                echo "Found ($MOD) $DESC"
                GOTNIC=1
                if [ "$MOD" = "gm" ]
                then 
                    echo "alias myri0 $MOD"
                    echo "alias myri0 $MOD" >>/etc/modules.conf
                    echo "alias myri0 $MOD" >>/etc/modprobe.conf
                else
                    modprobe $MOD
                    if [ "mlx4_core" = "$MOD" ]; then
                        modprobe mlx4_en
                    fi
                fi
                ;;
            infiniband)
                echo "Found ($MOD) $DESC"
                GOTNIC=1
                modprobe $MOD
                if [ "mlx4_core" = "$MOD" ]; then
                    modprobe mlx4_ib
                fi
                modprobe ib_ipoib
                # wait a bit...
                sleep 3
                ;;
            scsi|raid)
                echo "Found ($MOD) $DESC"
                GOTHBA=1
                modprobe $MOD & #We background so that messed up SANs don't stop shell
                modprobe sd_mod
                modprobe scsi_mod
                hba=$(($hba + 1))
                ;;
            *)
                continue
                ;;
        esac
    fi
done
NEEDVETH=0;
for dir in /proc/device-tree/vdevice/l-lan*; do
    if [ -d $dir ]; then NEEDVETH=1; fi
done
if [ $NEEDVETH =  1 ]; then
	modprobe ibmveth
fi
NEEDEHEA=0;
for dir in /proc/device-tree/lhea*; do
    if [ -d $dir ]; then NEEDEHEA=1; fi
done
if [ $NEEDEHEA = 1 ]; then
		    modprobe ehea
fi

NICSTOWAIT=`/sbin/ifconfig -a 2>/dev/null|grep HWaddr|grep -E '^eth|^ib'|sed -e 's/ .*//'`

if [ -z "${NICSTOWAIT// /}" ]; then
    msg "No any NIC found. Maybe you missing to add some kernel modules? Exiting."
    exit -1
fi

for nic in $NICSTOWAIT; do
    ifup $nic
done

let extrat=0
until [ $extrat == 20 -o -z "$NICSTOWAIT" ]; do
   sleep 1
   extrat=$(($extrat+1))
   for nic in $NICSTOWAIT; do 
      if [ ! -f /tmp/ignorenic.$nic ] && ifconfig $nic 2>/dev/null|grep "inet addr"; then
         NICSTOWAIT=`echo $NICSTOWAIT|sed -e s/$nic//`
         if [ $extrat -gt 45 ]; then
            echo "Warning: $nic took more than 45 seconds to receive DHCP reply, spanning-tree may not be configured well, examine switch configuration" >> /etc/motd
            echo "Warning: $nic took more than 45 seconds to receive DHCP reply, spanning-tree may not be configured well, examine switch configuration"
         fi
      elif [ $extrat == 10 ]; then
           # do not work in all cases
           #if ethtool $nic | grep "Link detected: no"; then
            if ( ! grep up /sys/class/net/$nic/operstate >/dev/null 2>&1 ); then
               echo "$nic did not have any link when bringing up network"
               echo "$nic did not have any link when bringing up network" >> /etc/motd
               NICSTOWAIT=`echo $NICSTOWAIT|sed -e s/$nic//`
            fi
      fi
   done
done
if [ ! -z "$NICSTOWAIT" ]; then
   echo "Warning: the following network devices appeared to be connected to networks, but received no DHCP response: $NICSTOWAIT" >> /etc/motd
   echo "Warning: the following network devices appeared to be connected to networks, but received no DHCP response: $NICSTOWAIT"
fi
