#!/bin/bash
#
# calvados/asr9k_pkg/boot/scripts/pd-functions
# This script provides PD functions to other scripts.
#
# Copyright (c) 2014-2020 by Cisco Systems, Inc.
# All rights reserved.

IPU_TYPE_AZ="0[789abef]"
IPU_TYPE_BDW_LSQ="1[78]"    # Both LSQ and LSP
IPU_TYPE_BDW_LSP="1[9abcde]"
IPU_TYPE_TH="0[0123456]"
IPU_TYPE_RPBB="2a"
IPU_TYPE_LCBB="1c"
IPU_TYPE_LCSL="1d"
IPU_TYPE_LC99NG="1[cd]" # 9902, 9903 LC
IPU_TYPE_FIRESTAR="1e"
XR_MGMT_IF_MAC_OFFSET=5

myvmtype=`cat /proc/cmdline | sed 's/^.*vmtype=//' | cut -d" " -f1`
if [ "$myvmtype" == "xr-vm" ]; then
    myshowemt="/pkg/sbin/showemt_static"
    myshowipu="/pkg/sbin/showipu_static"
    myshowpcie="/pkg/sbin/dopcie_static"
elif [ "$myvmtype" == "sysadmin-vm" ]; then
    myshowemt="/opt/cisco/calvados/bin/showemt_static"
    myshowipu="/opt/cisco/calvados/bin/showipu_static"
    myshowpcie="/opt/cisco/calvados/bin/dopcie_static"
else
    myshowemt="/sbin/showemt"
    myshowipu="/sbin/showipu"
    myshowpcie="/sbin/dopcie"
fi

KMSG_DIR=/misc/scratch/pcie
KMSG_LOG=${KMSG_DIR}/kmsg.log
A9K_BOOT_LOG=/misc/scratch/pcie/a9k_pd_boot.log

function kmsg_log
{
    local STRING=$@
    local timestamp=$( date +"%b %d %T" )

    # kmsg_log: log to both dmesg and KMSG_LOG
    echo "A9K $STRING" > /dev/kmsg
    mkdir ${KMSG_DIR} > /dev/null 2>&1
    printf "%s %s\n" "$timestamp" "$STRING" >> ${KMSG_LOG}
    grep -q "root=/dev/ram" /proc/cmdline
    if [ $? -ne 0 ]; then
        printf "A9K %s %s\n" "$timestamp" "$STRING" >> ${A9K_BOOT_LOG}
    fi
}

function kmsg_exec
{
    local CMD=$@

    mkdir ${KMSG_DIR} > /dev/null 2>&1

    $CMD 2>&1 | tee -a ${KMSG_LOG}
    local ret=${PIPESTATUS[0]}
    if [[ "$ret" -ne 0 ]]
    then
        # kmsg_exec: log to dmesg on error
        echo "A9K $CMD error=$ret" > /dev/kmsg
        echo "WARNING: $CMD returns $ret" > /dev/ttyS0
        grep -q "root=/dev/ram" /proc/cmdline
        if [ $? -ne 0 ]; then
            printf "A9K %s error=%s\n" "$CMD" "$ret" >> ${A9K_BOOT_LOG}
        fi    
    fi

    # kmsg_exec: log to KMSG_LOG always
    local timestamp=$( date +"%b %d %T" )
    printf "%s %s exit=%d\n" "$timestamp" "$CMD" "$ret" >> ${KMSG_LOG}

    return $ret
}

function update_virt_method {
    local caller=${FUNCNAME[1]}
    local rootdir=$1
    local is_install=$(grep "install=" /proc/cmdline | wc -l)

    is_vxr_sim
    if [[ $? == 1 ]]; then
        VIRT_METHOD=lxc
        export VIRT_METHOD
        readonly VIRT_METHOD
        return
    fi

    if [ ! -z "$is_install" ]; then
        platform_is_virtvm $is_install
        local rc=$?
        if [[ $rc == 1 ]]; then
            VIRT_METHOD=vm
        else
            VIRT_METHOD=lxc
        fi
        export VIRT_METHOD
        readonly VIRT_METHOD
    fi
    kmsg_log "$caller new $VIRT_METHOD in $rootdir"
    echo     "$caller new $VIRT_METHOD in $rootdir" > $rootdir/etc/init.d/$caller.out
    date >> $rootdir/etc/init.d/proc_cmdline.$caller.$VIRT_METHOD
    cat /proc/cmdline >>  $rootdir/etc/init.d/proc_cmdline.$caller.$VIRT_METHOD
    cp /root/cmdline $rootdir/etc/init.d/root_cmdline.$caller.$VIRT_METHOD
}

function update_vmmprofile {

    if [ "$BOARDTYPE" != "RP" ]; then
        return
    fi

    local rootdir=$1
    local vmm_ln=${rootdir}/opt/cisco/calvados/etc/platform_profile/hw/vmm_profile.cfg
    local vmm_fn

    if [[ -L $vmm_ln ]]; then
        vmm_fn=$( stat $vmm_ln | grep File | awk '{print $4}' | sed -e "s;';;g" )
        vmm_fn=${rootdir}/${vmm_fn}
    else
        vmm_fn=$vmm_ln
    fi

    if [[ ! -f $vmm_fn ]]; then
        echo update_vmmprofile cannot locate $vmm_fn
        return
    fi

    if [[ $VIRT_METHOD == "vm" ]]; then
        sed -i -e "s;#CONSOLE_ON_TTY;CONSOLE_ON_TTY;" $vmm_fn
    else
        sed -i -e "s;^CONSOLE_ON_TTY;#CONSOLE_ON_TTY;" $vmm_fn
    fi
}

function update_bootstrap {
    local bootstrap_dest=$1/etc/rc.d/init.d/calvados_bootstrap.cfg
    local bootstrap_src=/var/log/calvados_bootstrap.cfg
    local tmp

    if [[ ! -f $bootstrap_dest ]]; then
        echo update_bootstrap cannot locate $bootstrap_dest
        return
    fi

    A9KSIM=`cat /proc/cmdline | grep __vxr`
    if [[ -z "$A9KSIM" ]]; then
        # Take care of upgrade case from 6.5.1/6.5.2.
        tmp=$(grep -c "^#CTRL_VRF" $bootstrap_src)
        if [[ "$tmp" -eq 1 ]]; then
            sed -i -e "s;^#CTRL_VRF;CTRL_VRF;" -e "s;^#MGMT_VRF;MGMT_VRF;" $bootstrap_src
        fi
    fi

    ls -li  $bootstrap_src $bootstrap_dest >> $1/etc/rc.d/init.d/bootfn.txt
    cp -pf $bootstrap_src $bootstrap_dest
    echo "VIRT_METHOD  ${VIRT_METHOD}" >>  $1/etc/rc.d/init.d/bootfn.txt
    ls -li  $bootstrap_src $bootstrap_dest >> $1/etc/rc.d/init.d/bootfn.txt

    if [[ $VIRT_METHOD == "vm" ]]; then
        sed -i -e "s;VIRT_METHOD=lxc;VIRT_METHOD=vm;" $bootstrap_dest
        sed -i -e "s;HOST_IP_ADDR=0A000210;HOST_IP_ADDR=0A000202;" $bootstrap_dest
        sed -i -e "s;10.0.2.16;10.0.2.2;" $bootstrap_dest
    else
        sed -i -e "s;VIRT_METHOD=vm;VIRT_METHOD=lxc;" $bootstrap_dest
        sed -i -e "s;HOST_IP_ADDR=0A000202;HOST_IP_ADDR=0A000210;" $bootstrap_dest
        sed -i -e "s;10.0.2.2;10.0.2.16;" $bootstrap_dest
    fi
}

function get_host_reboot_count_addr {
    # Obtain host counter address in EMT
    if [ -n "${host_reboot_count}" ]; then
        return;
    fi
    if [[ -f /opt/cisco/calvados/bin/showemt_static ]]; then
         /opt/cisco/calvados/bin/showemt_static addr | grep host_reboot_count > /tmp/emt_addr_offset
    elif [[ -f /pkg/sbin/showemt ]]; then
         /pkg/sbin/showemt addr | grep host_reboot_count > /tmp/emt_addr_offset
    else
        showemt addr | grep host_reboot_count > /tmp/emt_addr_offset
    fi
    if [[ $? != 0 ]]; then
        rm /tmp/emt_addr_offset
        echo "Unable to detect host count address via emt"
        return
    fi
    source /tmp/emt_addr_offset
    rm /tmp/emt_addr_offset
    if [ -n "${host_reboot_count}" ]; then
        return;
    fi
    echo "Unable to gather host count address via emt"
}

# We use the host_reboot_count in the emt area for deciding vm or lxc mode.
# The bios maintains host_reboot_count across reload.
# Prior to this change, host_reboot_count was a 32 bit counter.
# Now it is a 24 bit counter. The upper 8 bits of host_reboot_count
# determine either vm or lxc. Zero means vm, non-zero means lxc.
# Adding 16777216 (0x01000000) effectively sets lxc mode.
# Subtracting 16777216 sets vm mode.
# Testing for greater than 16777216 indicates vm vs. lxc
# This simple, yet persistient, model allows us to maintain vm vs. lxc distinction at bake time

function platform_is_emtvm {

    get_host_reboot_count_addr
    if [ -n "${host_reboot_count}" ]; then
        local CURR_CNT=$(pcimemread `printf '%x' $host_reboot_count` 4 | grep -v PCI | awk '{ print $3 ;}' | sed -e 's/^0/0x/')
        local count=`expr $(($CURR_CNT))`
        if [[ $count -gt "16777216" ]]; then
            return 0
        fi
    else
        echo platform_is_emtvm empty -${host_reboot_count}-
    fi
    return 1
}

function platform_set_lxc {
    platform_is_emtvm
    if [[ $? == 0 ]]; then
        # already lxc
        return;
    fi
    if [[ ! -n  $host_reboot_count ]]; then
        echo Cannot determine emt address
        return
    fi
    local CURR_CNT=$(pcimemread `printf '%x' $host_reboot_count` 4 | grep -v PCI | awk '{ print $3 ;}' | sed -e 's/^0/0x/')
    local count=`expr $(($CURR_CNT))`
    count=`expr $(($CURR_CNT)) + 16777216`
    local counthex=`printf '%x' $count`
    pcimemwrite `printf '%x' $host_reboot_count` 4 $counthex > /dev/null 2>&1
}

function platform_set_vm {
    platform_is_emtvm
    if [[ $? == 1 ]]; then
        # already vm
        return;
    fi
    if [[ ! -n  $host_reboot_count ]]; then
        echo Cannot determine emt address
        return
    fi
    local CURR_CNT=$(pcimemread `printf '%x' $host_reboot_count` 4 | grep -v PCI | awk '{ print $3 ;}' | sed -e 's/^0/0x/')
    local count=`expr $(($CURR_CNT))`
    count=`expr $(($CURR_CNT)) - 16777216`
    local counthex=`printf '%x' $count`
    pcimemwrite `printf '%x' $host_reboot_count` 4 $counthex > /dev/null 2>&1
}

function platform_is_virtvm {
    local virtmethod
    local emt_check=$1

    is_vxr_sim
    if [[ $? == 1 ]]; then
        return 0;
    fi

    # first check for virtvm
    virtmethod=$(cat /proc/cmdline | grep virtvm | wc -l)
    if [ "$virtmethod" == "1" ]; then
        # echo platform_is_virtvm from ${FUNCNAME[1]} return 1
        return 1
    fi

    # next, check for virtlxc
    virtmethod=$(cat /proc/cmdline | grep virtlxc | wc -l)
    if [ "$virtmethod" == "1" ]; then
        # echo platform_is_virtvm from ${FUNCNAME[1]} return 0
        return 0
    fi

    # Neither virtvm nor virtlxc set
    # LC must have on or other, default to VM
    if [[ "${BOARDTYPE}" == "LC" ]]; then
        # echo platform_is_virtvm LC ${FUNCNAME[1]} return 0
        return 1
    fi

    # If operting in calvados or xr, default to VM
    if [[ $emt_check == "0" ]]; then
        # echo platform_is_virtvm no emt ${FUNCNAME[1]} return 0
        return 1
    fi

    # RSP hostos case, check emt override
    platform_is_emtvm
    local rc=$?
    # echo platform_is_virtvm exit ${FUNCNAME[1]} return $rc
    return $rc
}

#
# Check if pd_funcions should be skipped
#
function skip_pd_functions {
    local install=$(cat /proc/cmdline | grep install=)
    if [ -n "${install}" ]; then
        return 1
    fi
    local sim=$(cat /proc/cmdline | grep simulator=)
    if [ -n "${sim}" ]; then
        return 1
    fi
    if [[ "${BOARDTYPE}" == "LC" ]]; then
        return 1
    fi
    return 0
}


# read field=value pair from /etc/init.d/calvados_bootstrap.cfg file
# example : cal_bootstrap_field_value VIRT_METHOD
function cal_bootstrap_field_value()
{
    local cal_bs="/etc/init.d/calvados_bootstrap.cfg"

    echo `grep -a $1 $cal_bs | cut -d"=" -f2`
}


# read field=value pair from /dev/xr_bootstrap file
# example : xr_bootstrap_field_value ISSU_ROLE
function xr_bootstrap_field_value()
{
    local bs="/dev/xr_bootstrap"

    echo `grep -a $1 $bs | cut -d"=" -f2`
}

#
# Which TTY should calvados con use
#
function platform_enable_calvados_con
{
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi

    if [ "$virt_method" == "vm" ]; then
        ACTIVE_SERIAL='/dev/hvc0'
    else
        ACTIVE_SERIAL='/dev/pts/0'
    fi

    declare -F platform_log &>/dev/null && platform_log "Calvados console on $ACTIVE_SERIAL"
    echo "Calvados console on $ACTIVE_SERIAL"
}

#
# Which TTY should calvados aux use
#
function platform_enable_calvados_aux
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL=
    declare -F platform_log &>/dev/null && platform_log "Do not start Calvados aux"
    echo "Calvados aux disabled"
}

#
# Which TTY should XR con use
#
function platform_enable_xr_con
{
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi

    if [ "$virt_method" == "vm" ]; then
        ACTIVE_SERIAL_XR_CON="hvc0"
    else
        ACTIVE_SERIAL_XR_CON="pts/0"
    fi

    declare -F platform_log &>/dev/null && platform_log "XR console on $ACTIVE_SERIAL_XR_CON"
    echo "XR console on $ACTIVE_SERIAL_XR_CON"
}

#
# Which TTY should XR aux use
#
function platform_enable_xr_aux
{
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi

    if [ "$virt_method" == "vm" ]; then
        ACTIVE_SERIAL_XR_AUX="hvc1"
    else
        ACTIVE_SERIAL_XR_AUX="pts/1"
    fi

    declare -F platform_log &>/dev/null && platform_log "XR aux on $ACTIVE_SERIAL_XR_AUX"
    echo "XR aux on $ACTIVE_SERIAL_XR_AUX"
}


#
# Should we allow the first serial port to have a tty login?
#
function platform_enable_host_login_on_first_serial
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    if [[ "${BOARDTYPE}" == "RP" ]]; then
        local cmd_host_console=$(cat /proc/cmdline | grep "hostconsole" \
                                 | wc -l)
        if [ "$cmd_host_console" == "1" ]; then
            TTY_FLOWCTRL=
            ACTIVE_SERIAL='/dev/ttyS0' # Console
            declare -F platform_log &>/dev/null && platform_log \
                    "Host console on $ACTIVE_SERIAL"
            echo "Host console on $ACTIVE_SERIAL"
        else
            ACTIVE_SERIAL= # Host console is disabled in production
            echo "XR console. Please wait ..."
        fi
    fi
}

#
# Do we want to enable host access on extra ttys? Good for development but
# is a security risk to leave host access visible.
#
function platform_starts_serial
{
    # On LC ttyS1 is for CBC
    #
    skip_pd_functions
    if [ $? -ne 0 ]; then
        if [[ "${BOARDTYPE}" != "LC" ]]; then
            return;
        fi
    fi
    #
    # We do not want host tty access unless enabled by development mode,
    # so default to no access.on
    #
    # echo "Start serial incoming on $ACTIVE_SERIAL, Clearing .."
    declare -F platform_log &>/dev/null && platform_log "Start serial incoming on $ACTIVE_SERIAL, Clearing .."
    ACTIVE_SERIAL=
    if [[ "${BOARDTYPE}" == "LC" ]]; then
        if [ "$VMTYPE" == "hostos" ]; then
            SPEED="$SPEED -8"
            ACTIVE_SERIAL=/dev/ttyS0
        fi
    fi
    kmsg_log "platform_starts_serial $VMTYPE $ACTIVE_SERIAL"
}

function update_rsp_var_mount
{
    local my_ipaddr=$1
    local rc
    local npass=1
    local maxpass=1

    date >> /tmp/varmount 2>&1
    echo my_ipaddr is ${my_ipaddr}  >> /tmp/varmount

    local my_hostname=$( grep ${my_ipaddr} /etc/hosts | sed -e "s;^.* ;;" )
    if [[ -z ${my_hostname} ]]; then
        echo "my_hostname is null" >> /tmp/varmount
        return
    fi
    echo "my_hostname is $my_hostname" >> /tmp/varmount

    local node
    for node in rsp0_xr rsp1_xr; do
        ping -c 1 ${node} >> /tmp/varmount 2>&1
        rc=$?
        if [[ ${rc} == 0 ]]; then
            ssh -o "BatchMode=yes" ${node} mount /misc/scratchlc/${my_hostname} >> /tmp/varmount 2>&1
        fi
    done
}

#
# The step-by-step flow of np log file preservation across bake is:
# Below description refers to np log files, pcie log files also follow a similar flow
# a) At bake time: function save_sys_files xr_misc_scratch np - saves np files from XR:/misc/scratch/np
# b) At bake time: function restore_sys_files admin_var_log np - saves np files to Admin:/var/log/np.tar
# c) In Calvados(PI): temporarily mount bind Calvados:/var/log within XR rootfs - via mount_pd_fs.sh/fs_required.txt
# d) In Calvados: In update_xr_files (below):  Move np.tar from Calvados:/var/log/ to XR:/xr/
# e) In Calvados(PI): umount temporary binding - via mount_pd_fs.sh/fs_required.txt
# f) In XR: In update_misc_scratch_xr (below): untar /xr/np.tar to /misc/scratch/np
# g) In XR: In update_misc_scratch_xr (below): Remove /xr/np.tar
#

XR_TAR_FILE_DIR=/xr
XR_MISC_SCRATCH_TAR_LIST="np.tar pcie.tar"
XR_EUSB_TAR_LIST="migration.tar"

function update_xr_files {
    for tar_fn in $XR_MISC_SCRATCH_TAR_LIST $XR_EUSB_TAR_LIST; do
        if [[ -f /var/log/$tar_fn ]]; then
            mkdir -p ${XR_TAR_FILE_DIR}
            mv /var/log/$tar_fn ${XR_TAR_FILE_DIR}/
        fi
    done
}

function update_misc_scratch_xr
{
    local curdir=`pwd`
    cd /misc/scratch/

    for tar_fn in $XR_MISC_SCRATCH_TAR_LIST; do
        if [[ -f ${XR_TAR_FILE_DIR}/$tar_fn ]]; then
            echo update_misc_scratch_xr process $tar_fn >> /tmp/varmount
            tar xvf ${XR_TAR_FILE_DIR}/$tar_fn >> /tmp/varmount
            if [[ $? != 0 ]]; then
                echo untar ${XR_TAR_FILE_DIR}/$tar_fn files did not work  >> /tmp/varmount 2>&1
            fi
        fi
    done
    
    cd $curdir
}

function update_eusb_xr
{
    local curdir=`pwd`

    cd /eusbb/
    for tar_fn in $XR_EUSB_TAR_LIST; do
        if [[ -f ${XR_TAR_FILE_DIR}/$tar_fn ]]; then
            echo update_misc_scratch_xr process $tar_fn >> /tmp/varmount
            tar xvf ${XR_TAR_FILE_DIR}/$tar_fn >> /tmp/varmount
            if [[ $? != 0 ]]; then
                echo untar ${XR_TAR_FILE_DIR}/$tar_fn files did not work  >> /tmp/varmount 2>&1
            fi
        fi
    done
    
    rm -r ${XR_TAR_FILE_DIR} >> /tmp/varmount
    cd $curdir
}

function rename_nic
{
    if [ ! -L /sys/class/net/$1 ]; then
        echo Warning cannot rename network interface $1
        kmsg_log "Warning cannot rename network interface $1"
        return 1
    fi
    kmsg_exec "ip link set dev $1 name $2"
}

function config_nic
{
    if [[ $2 != "0" ]]; then
        kmsg_exec "/usr/sbin/ethtool -G $1 rx $2"
    fi
    kmsg_exec "ifconfig $1 mtu 9700"
    sleep 1
    kmsg_exec "ifconfig $1 up"
}

function add_multicast_entries 
{
    local hw_ct

    if [[ -z ${HW_CARDTYPE} ]]; then
        kmsg_log "add_multicast_entries $1: HW_CARDTYPE not set"
        return
    fi
    let "hw_ct = ${HW_CARDTYPE} & 0x3f"

    hw_ct=$( printf "%02x" ${hw_ct} )

    case "$hw_ct" in
    ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed cards
       kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:54 dev eth-punt"
       kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:42 dev eth-bfd"
       kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:30 dev eth-srpm"
       kmsg_exec "/sbin/ip maddr add 01:80:c2:00:00:0e dev eth-flexe"
       ;;
    2[78]|${IPU_TYPE_RPBB})  # RSP5/RP3/RPBB
       kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:54 dev eth-punt"
       kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:77 dev eth-tpa"
       ;;
    *)  # Everything else
     ;;
     esac
}

function set_bfd_affinity
{
    local irq
    local affinity=1
    local lastcpu=$( grep processor /proc/cpuinfo | tail -1 | awk '{print $3}' )
    local irqs=$( grep bfd /proc/interrupts | awk '{print $1}' | tr -d ':' )    

    
    # Find out affinity value (include all cores except core 0)
    for ((i=0;i<$lastcpu;i++)) 
    do
        let affinity=$affinity*2+1
    done
    let affinity=$affinity-1
    
    # Convert affinity to hex
    printf -v affinity "%x" $affinity

    # Update bfd irq affinities
    for irq in ${irqs}                                                          
    do                                                                          
        echo $affinity  > /proc/irq/${irq}/smp_affinity                       
        kmsg_log "Setting up smp_affinity to: $affinity for irq: $irq"
    done  

}

# Avoid any dependency on specific ethX ordering.
# Instead of depending on specific ethX to VNIC mapping,
# lookup ethX based upon VNIC order assigned in QEMU command line.
# Rename the ethX to the desired new ifname

function rename_nic_v2
{
      local devid=$1
      local inst=$2
      local tifname=$3
          
      local ethname=$(lspci -nn | grep $devid | awk '{print $1}' | head -n $inst | tail -1)
      local sifname=$(ls -l /sys/class/net/*/device | awk '{print $9, $11}' | grep $ethname  | cut -d"/" -f5)

      ifconfig $sifname down
      rename_nic $sifname $tifname
}

function configure_from_xr_bootstrap_vm
{
    source /etc/rc.d/init.d/spirit_pd.sh
    local issu_role=`xr_bootstrap_field_value ISSU_ROLE`
    local issu_id=`xr_bootstrap_field_value ISSU_ID`
    local mlan_mtu=9200
    local hw_ct=$( get_hw_cardtype )

    kmsg_log "configure_from_xr_bootstrap_vm $issu_role $issu_id"
    
    rm /etc/udev/rules.d/70-persistent-net.rules
    rm /lib/udev/rules.d/75-persistent-net-generator.rules
    rmmod igb
    sleep 1

    declare -F platform_log &>/dev/null && \
    platform_log "configure from XR bootstrap ISSU role $issu_role id $issu_id"

    pd_modprobe_vf_driver

    case "$hw_ct" in
    26) # RSP4-Lite
        echo "RSP4 Lite XR VM"
        ifconfig eth2 down
        rename_nic  eth2 eth-punt
        rename_nic  eth1 eth-vf1
        ;;

    2[78]) # RP3/RSP5
        rename_nic_v2 37cd 3 eth-punt
        rename_nic_v2 37cd 1 eth-vf1
        ;;

    ${IPU_TYPE_RPBB})
        echo "RPBB XR VM"
        rename_nic_v2  15a8 3 eth-punt
        rename_nic_v2  15a8 1 eth-vf1
        ;;

    *)
        ifconfig eth1 down
        rename_nic  eth1 eth-punt
        rename_nic  eth0 eth-vf1
        ;;
    esac

    config_nic  eth-punt 1024
    config_nic  eth-vf1  1024

    if [[ "${BOARDTYPE}" == "LC" ]]; then
        rename_nic  eth2  eth-bfd
        config_nic  eth-bfd 1024
        rename_nic  eth3  eth-srpm
        config_nic  eth-srpm 1024
        set_bfd_affinity
        case "$hw_ct" in
        ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed LC
            rename_nic  eth4  eth-flexe
            config_nic  eth-flexe 1024
            ;;
        esac
    else
        case "$hw_ct" in
        26) # RSP4-Lite
            echo "RSP4 Lite XR VM"
            rename_nic  eth3  eth-tpa
            ;;
        ${IPU_TYPE_RPBB})
            echo "RPBB XR VM"
            rename_nic_v2 15a8 2 eth-tpa
            ;;
        2[78]) # RP3/RSP5
            rename_nic_v2 37cd 2 eth-tpa
            ;;

        *)
            rename_nic  eth2  eth-tpa
            ;;
        esac
        config_nic  eth-tpa 0

        pd_modprobe_igb
        sleep 1
        rename_nic  eth0   eth-mgmt1
    fi

    add_multicast_entries
}

function set_vlan_ingress_egress_map() {
    local dev=$1
    for i in {0..7}
    do
         vconfig set_egress_map $dev $i $i  > /dev/null 2>&1
         vconfig set_ingress_map $dev $i $i  > /dev/null 2>&1
    done
}

function log_ifconfig 
{
    printf "%s\n" "$(date): /sbin/ifconfig -a:" > $1   
    /sbin/ifconfig -a >> $1 2>&1
    local eths=($(ifconfig -a | grep "Link\ " | cut -d' ' -f1))
    for eth in "${eths[@]}";
    do
        printf "\n%s\n" "$(date): /usr/sbin/ethtool ${eth}:" >> $1
        /usr/sbin/ethtool ${eth} >> $1 2>&1
    done
    printf "\n%s\n" "$(date): find /sys -name *eth*:" >> $1
    find /sys -name *eth* >> $1 2>&1
}

# Parse RSP mac_address from showemt, add offset and assign
# mac address to mgmt interface
function get_xr_mgmt_intf_mac
{
     local mac_offset=$1
     local rsp_base_mac=$($myshowemt mac_base)
    
     local mac1=$( echo $rsp_base_mac | cut -d ":" -f1)
     local mac2=$( echo $rsp_base_mac | cut -d ":" -f2)
     local mac3=$( echo $rsp_base_mac | cut -d ":" -f3)

     local mac_byte1=${mac1:0:2}
     local mac_byte2=${mac1:2:2}
     local mac_byte3=${mac2:0:2}
     local mac_byte4=${mac2:2:2}
     local mac_byte5=${mac3:0:2}
     local mac_byte6=${mac3:2:2}

     local LO3=${mac_byte4}${mac_byte5}${mac_byte6}
     printf -v new_LO3 "%x\n" $((0x$LO3 + 0x$mac_offset))
     local new_mac_addr=${mac_byte1}${mac_byte2}${mac_byte3}${new_LO3}
     
     echo $new_mac_addr
}

function platform_xr_ifconfig
{

    source /etc/rc.d/init.d/spirit_pd.sh
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`
    local hw_ct=$( get_hw_cardtype )

    declare -F platform_log &>/dev/null && platform_log "virt_method= $virt_method"

    if [[ "${virt_method}" == "vm" ]]; then
        configure_from_xr_bootstrap_vm
    fi

    kmsg_log "platform_xr_ifconfig start"
    /usr/bin/tr -d '\0' < /dev/xr_bootstrap > /tmp/xr_bootstrap
    source /tmp/xr_bootstrap

    kmsg_exec "/usr/sbin/ethtool -K eth-vf1 gro off"
    kmsg_exec "/sbin/vconfig add eth-vf1 ${CALVADOS_CTRL_ETH_VLAN}"
    kmsg_exec "/sbin/ifconfig ${ADMIN_CTRL_ETH} ${GUEST_IP_ADDR} netmask 255.0.0.0 up"
    kmsg_exec "/sbin/ifconfig ${ADMIN_CTRL_ETH} hw ether ${GUEST_MAC_ADDR} up"
    kmsg_exec "/sbin/ifconfig ${ADMIN_CTRL_ETH} mtu 9700 up"
    kmsg_exec "/usr/sbin/ethtool -K ${ADMIN_CTRL_ETH} gro off"

    INSTANCE_BASE=32
    INSTANCE=$(($INSTANCE_BASE + $(($ISSU_ID * 8))))

    # MAC format is V:K:G:R:S:I 
    MAC_BYTE4=$(printf "%02x" ${PD_SLOT_NUM})
    MAC_BYTE5=$(printf "%02x" ${INSTANCE})
    kmsg_exec "/sbin/vconfig add eth-vf1 ${GUEST_CTRL_ETH_VLAN}"
    kmsg_exec "/sbin/ifconfig ${GUEST_CTRL_ETH} 172.0.${PD_SLOT_NUM}.${INSTANCE} netmask 255.0.0.0 up"
    kmsg_exec "/sbin/ifconfig ${GUEST_CTRL_ETH} hw ether 56:4b:47:00:${MAC_BYTE4}:${MAC_BYTE5} up"
    kmsg_exec "/sbin/ifconfig ${GUEST_CTRL_ETH} mtu 9700 up"
    kmsg_exec "/usr/sbin/ethtool -K ${GUEST_CTRL_ETH} gro off"

    set_vlan_ingress_egress_map ${ADMIN_CTRL_ETH}
    set_vlan_ingress_egress_map ${GUEST_CTRL_ETH}

    # For front panel management ports
    if [[ "${BOARDTYPE}" == "RP" ]]; then
        kmsg_exec "/usr/sbin/ethtool -K eth-mgmt1 gro off"
        kmsg_exec "/sbin/ifconfig eth-mgmt1 mtu 9200 up"
    fi

    is_rp_rsp4lite
    rc=$?
    if [[ $rc == 1 ]];then
        local mgmt_mac_addr=$(get_xr_mgmt_intf_mac $XR_MGMT_IF_MAC_OFFSET)
        kmsg_exec "/sbin/ifconfig eth-mgmt1 down"
        kmsg_exec "/sbin/ifconfig eth-mgmt1 hw ether $mgmt_mac_addr"
        kmsg_exec "/sbin/ifconfig eth-mgmt1 up"
    fi

    kmsg_exec "/usr/sbin/ethtool -K eth-punt gro off"
    kmsg_exec "/sbin/vconfig add eth-punt ${GUEST_PUNT_ETH_VLAN}"
    kmsg_exec "/sbin/ifconfig ${GUEST_PUNT_ETH} hw ether 56:4b:47:50:4E:54 up"
    kmsg_exec "/usr/sbin/ethtool -K ${GUEST_PUNT_ETH} gro off"

    is_rp_rpbb
    rc=$?
    if [[ $rc == 1 ]];then
        kmsg_exec "/sbin/vconfig add eth-punt 1287"
        kmsg_exec "/sbin/ifconfig eth-punt.1287 hw ether 56:4b:47:50:${MAC_BYTE4}:55 up"
        kmsg_exec "/usr/sbin/ethtool -K eth-punt.1287 gro off"
    fi

    is_rp_starlord
    rc=$?
    if [[ $rc == 1 ]];then
        kmsg_exec "/sbin/ifconfig ${GUEST_PUNT_ETH} down"
        kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:54 dev ${GUEST_PUNT_ETH}"
        kmsg_log "starlord RP maddr add "
     fi
 
     is_lc_starlord
     rc=$?
     if [[ $rc == 1 ]];then
         kmsg_exec "/sbin/ifconfig ${GUEST_PUNT_ETH} down"
         kmsg_exec "/sbin/ifconfig ${GUEST_PUNT_ETH} hw ether 56:4b:47:50:4E:53 up"
         kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:53 dev ${GUEST_PUNT_ETH}"
         kmsg_log "starlord LC maddr add "
     fi

    # Join multicast group on the vxr sim, otherwise packets don't get punted
    # to the RP/LC CPU through eth-punt.1282 interface.
    is_vxr_sim
    if [[ $? != 0 ]]; then
        # SPP destination MAC address
        kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:54 dev ${GUEST_PUNT_ETH}"
        # Add BFD destination MAC address only on the RP
        if [[ "${BOARDTYPE}" == "RP" ]]; then
            kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:42 dev ${GUEST_PUNT_ETH}"
        fi
    fi

    kmsg_exec "/sbin/ifconfig ${GUEST_PUNT_ETH} mtu 9700 up"

    if [[ "${BOARDTYPE}" == "LC" ]]; then
        kmsg_exec "/usr/sbin/ethtool -K eth-bfd gro off"
        kmsg_exec "/sbin/vconfig add eth-bfd ${GUEST_PUNT_ETH_VLAN}"
        kmsg_exec "/sbin/ifconfig ${GUEST_BFD_ETH} hw ether 56:4b:47:50:4E:42 up"
        kmsg_exec "/usr/sbin/ethtool -K ${GUEST_BFD_ETH} gro off"

        kmsg_exec "/usr/sbin/ethtool -K eth-srpm gro off"
        kmsg_exec "/sbin/vconfig add eth-srpm 1283"
        kmsg_exec "/sbin/ifconfig eth-srpm.1283 hw ether 56:4b:47:50:4E:52 up"
        kmsg_exec "/usr/sbin/ethtool -K eth-srpm.1283 gro off"

        # Join multicast group on the vxr sim, otherwise packets don't get
        # punted to the LC CPU through eth-bfd.1282 interface.
        is_vxr_sim
        if [[ $? != 0 ]]; then
            kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:42 dev ${GUEST_BFD_ETH}"
            kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:30 dev eth-srpm.1283"
        fi

        kmsg_exec "/sbin/ifconfig ${GUEST_BFD_ETH} mtu 9700 up"
        kmsg_exec "/sbin/ifconfig eth-srpm.1283 mtu 9700 up"

        case "$hw_ct" in
        ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed LC
            kmsg_exec "/usr/sbin/ethtool -K eth-flexe gro off"
            kmsg_exec "/sbin/vconfig add eth-flexe ${GUEST_PUNT_ETH_VLAN}"
            kmsg_exec "/sbin/ifconfig eth-flexe.1282 hw ether 56:4b:47:50:4E:64 up"
            kmsg_exec "/usr/sbin/ethtool -K eth-flexe.1282 gro off"

            # Join multicast group on the vxr sim, otherwise packets don't get
            # punted to the LC CPU through eth-flexe.1282 interface.
            is_vxr_sim
            if [[ $? != 0 ]]; then
                kmsg_exec "/sbin/ip maddr add 01:80:c2:00:00:0e dev eth-flexe.1282"
            fi

            kmsg_exec "/sbin/ifconfig eth-flexe.1282 mtu 9700 up"
            ;;
        esac
    else
        kmsg_exec "/usr/sbin/ethtool -K eth-tpa gro off"
        kmsg_exec "/sbin/vconfig add eth-tpa ${GUEST_PUNT_ETH_VLAN}"
        kmsg_exec "/sbin/ifconfig eth-tpa.1282 hw ether 56:4b:47:50:4E:77 up"
        kmsg_exec "/sbin/ifconfig eth-tpa.1282 mtu 9700 up"
        kmsg_exec "/usr/sbin/ethtool -K eth-tpa.1282 gro off"
    fi
    is_lc_starlord
    rc=$?
    if [[ $rc == 1 ]];then
        kmsg_exec "/sbin/ip maddr add 01:56:47:50:4e:42 dev ${GUEST_BFD_ETH}"
        kmsg_log "starlord LC BFD maddr add "
    fi
   
    # snapshot xr state to /misc/scratch/pcie
    log_ifconfig "/misc/scratch/pcie/xr_ifconfig.log"

    kmsg_log "platform_xr_ifconfig finish"

    # snapshot XR state to Calvados if needed, debug only
    # note: pcie_rpc_svr must be also started in backup_logs() if snapshot needed
    # snapshot_state
}

function is_development_platform()
{
    grep -q "__development=true" /proc/cmdline
    if [ $? -eq 0 ]; then
        true
        return
    fi

    false
}

function on_dev()
{
    if [ "${DEVELOPMENT}" == "" ]; then
        #
        # Only log the first time we decide on the simulation setting to avoid
        # noise and repeated looking up of the information we need.
        # 
        is_development_platform
        if [[ $? == 0 ]]; then
            readonly DEVELOPMENT=1
        else
            readonly DEVELOPMENT=0
        fi
    fi

    return $DEVELOPMENT
}

#
# Disable all 8717 links
#
function pci_disable_8717_down
{
    local dev=$(lspci -nn | grep 8717 | grep -v "00.0" | awk '{print $1}')
    for d in $dev; do
        setpci -s $d CAP_EXP+10.l=10:10
    done
}

#
# Check IPU MB ID from info rom
# Matching below table
#
#/* IPU MB ID */
#define IPU_MB_ID_PYRO_SAC          1
#define IPU_MB_ID_PYRO_SM15         2
#define IPU_MB_ID_OCTANE            3
#define IPU_MB_ID_SURESHOT          4
#define IPU_MB_ID_SKYHAMMER         5
#define IPU_MB_ID_PWRGLIDE          6      /* 48x10GE                    */
#define IPU_MB_ID_AZTECA            7      /* 32x100GE LAN               */
#define IPU_MB_ID_AZTECA_2SKB5F     8      /* 16x100GE LAN 5-Fab 2xSBK   */
#define IPU_MB_ID_SW_SIM            9      /* Reserved for SW SIM        */
#define IPU_MB_ID_AZTECA_1SKB5F     10     /* 16x100GE LAN 5-Fab 1xSKB   */
#define IPU_MB_ID_AZTECA_TTV        11     /* 30x100GE Thermal Test card */
#define IPU_MB_ID_STARLORD_LC       12     /* Starlord LC                */
#define IPU_MB_ID_AZTECA_2SKB5F_ALS 13     /* 16x100GE LAN 5-Fab 2xSKB alias */
#define IPU_MB_ID_AZTECA_2SKB7F     14     /* 16x100GE LAN 7-Fab 2xSKB   */
#define IPU_MB_ID_AZTECA_16P        15     /* 16x100GE w/ 8x(2 ports per)LSQs */
#define IPU_MB_ID_LC_TEST_CARD_2    16     /* Test card line card 2      */
#define IPU_MB_ID_AZTECA_PLUS       23     /* 32x100GE w/ LSP            */
#define IPU_MB_ID_QUESTRA           24     /* 2T Combo                   */
#define IPU_MB_ID_DURLAST           25     /* 10x400GE LAN               */
#define IPU_MB_ID_JABULANI          26     /* 2.4T Combo                 */
#define IPU_MB_ID_QUESTRA_8_100     27     /* 8x100                      */
#define IPU_MB_ID_BBLC              28     /* Blackbolt LC               */

#define IPU_MB_ID_RSP4              0x20   /* RSP4                    */
#define IPU_MB_ID_RP2               0x21   /* RP2                     */
#define IPU_MB_ID_RSP_SHK_WV_2XBAR  0x22   /* RSP Shockwave 2x SM15   */
#define IPU_MB_ID_RSP_SHK_WV_1XBAR  0x23   /* RSP Shockwave 1x SM15   */
#define IPU_MB_ID_RSP4_PROD_A0      0x24   /* RSP4 Production -A0     */
#define IPU_MB_ID_RP2_PROD_A0       0x25   /* RP2 Produciton -A0      */
#define IPU_MB_ID_RSP4_LITE         0x26   /* RSP4 LITE               */
#define IPU_MB_ID_RSP5              0x27   /* RSP5                    */
#define IPU_MB_ID_RP3               0x28   /* RP3                     */
#define IPU_MB_ID_STARLORD_RP       0x29   /* Starlord RP             */
#define IPU_MB_ID_BBRP              0x2a   /* Blackbolt RP            */

#define IPU_MB_ID_FC2               0x30   /* FC2                     */
#define IPU_MB_ID_FC2_SS            0x31   /* Starscream specific FC2 */
#define IPU_MB_ID_FC2_SHK_WV        0x32   /* Shockwave FC2           */
#define IPU_MB_ID_FC2_TRCH_WD       0x33   /* Torchwood FC2           */
#define IPU_MB_ID_FC2_B2B           0x34   /* 2x SM15 proof of concept */
#define IPU_MB_ID_FC3               0x35   /* 2x SKB MT               */
#define IPU_MB_ID_FC3_B2B           0x36   /* 4x SKB Back to back     */
#define IPU_MB_ID_FC3_SHK_WV        0x37   /* Shockwave FC3           */

#define IPU_MB_ID_FAMILY_MSK        0x30
#define IPU_MB_ID_FAMILY_LC         0
#define IPU_MB_ID_FAMILY_RP         0x20
#define IPU_MB_ID_FAMILY_FC         0x30

function check_ipu_magic
{
    local base=$1
    INFO_ROM_CT_OFF=0xc0

    # confirm ipu info rom block id 2240d (35d << 6)
    local block_id=$( pcimemread $base 0x4 | grep -v PCI |  awk '{ print $3 ; }' )
    if [[ -z $block_id ]]; then
        echo Unable to determine block_id for address $base
        return 1
    fi
    block_id=0x${block_id}
    let "block_id = $block_id & 0x3fc0"
    if [[ "$block_id" != "2240" ]]; then
        return 1
    fi

    # confirm permissable MBI_ID value from above table
    local hw_cardtype_addr=$(($base + $INFO_ROM_CT_OFF))
    local hw_cardtype=$( pcimemread `printf "%x" $hw_cardtype_addr` 0x4 | \
                         grep -v PCI | awk '{ print $3 ; }' | sed -e 's/...../0x/' )
    if [[ $hw_cardtype -ge 0x20 && $hw_cardtype -lt 0x30 ]]; then
        return 0
    fi
    if [[ $hw_cardtype -ge 0x1 && $hw_cardtype -lt 0x20 ]]; then
        return 0
    fi
    return 1   # FC's
}

#
# Safest way to get IPU base
#
function get_ipu_base_safe
{
    local devices=$(lspci -nn | grep ":87a0]" | awk '{print $1}' | grep ":00.0")
    for dev in $devices; do
        local mem=$(echo `lspci -s ${dev} -v | grep "size=" | grep -v "size=1[MK]" |  awk '{print $3}'`)
        if [[ ! -z ${mem} ]]; then
            check_ipu_magic 0x${mem}
            if [ $? -eq  0 ]; then
                echo 0x${mem}
                return
            fi
        fi
    done
}

function get_ipu_bdf_safe
{
    local devices=$(lspci -nn | grep ":87a0" | awk '{print $1}')
    for dev in $devices; do
        local mem=$(echo `lspci -s ${dev} -v | grep Memory | grep -v "size=1M" | awk '{print $3}'`)
        if [[ ! -z ${mem} ]]; then
            check_ipu_magic 0x${mem}
            if [ $? -eq  0 ]; then
                echo ${dev}
                return
            fi
        fi
    done
}

function display_ipu_devices
{
    local devices=$(lspci -nn | grep ":87a0" | awk '{print $1}' | grep ":00.0" | paste - - - - - - )
    kmsg_log "Warning: IPU device not found: $devices"
}

function set_ipu_base
{
    if [[ ! -z ${IPU_BASE} ]]; then
        # IPU_BASE already set
        return 0
    fi

    # first try
    IPU_BASE=$(get_ipu_base_safe)
    if [[ ! -z ${IPU_BASE} ]]; then
        kmsg_log "IPU_BASE: ${IPU_BASE}"
        return 0
    fi

    sleep 1

    # second try
    IPU_BASE=$(get_ipu_base_safe)
    if [[ ! -z ${IPU_BASE} ]]; then
        kmsg_log "IPU_BASE: ${IPU_BASE} - second try"
        return 0
    fi

    # IPU_BASE set failure
    display_ipu_devices
    return 1
}

function set_ipu_bdf
{
    if [[ ! -z ${IPU_BDF} ]]; then
        # IPU_BDF already set
        return 0
    fi

    # first try
    IPU_BDF=$(get_ipu_bdf_safe)
    if [[ ! -z ${IPU_BDF} ]]; then
        kmsg_log "IPU_BDF: ${IPU_BDF}"
        return 0
    fi

    # second try
    IPU_BDF=$(get_ipu_bdf_safe)
    if [[ ! -z ${IPU_BDF} ]]; then
        kmsg_log "IPU_BDF: ${IPU_BDF} - second try"
        return 0
    fi

    # IPU_BDF set failure
    display_ipu_devices
    return 1
}

#
# Mask malformed TLP and surprise link down errors
#
function pd_mask_uncorrectable_err
{
    local dev=$(lspci -nn | grep 8717 | grep -v "00.0" | awk '{print $1}')
    for d in $dev; do
        setpci -s $d ECAP_AER+8.l=40020:40020
    done

    local rootb=$(lspci -nn | grep 8749 | grep -v "00.0" | awk '{print $1}' |\
            cut -d ":" -f1 | head -1)
    setpci -s $rootb":03.0" ECAP_AER+8.l=20:20
    setpci -s $rootb":05.0" ECAP_AER+8.l=20:20
}

function setup_host_access_lxc()
{
    # for release use on_dev to bypass host access

    # On RP V1 and V2 are not active at same time, so one address 10.11.12.14
    # is enough for host access. On LC V1 and V2 can be active at same time
    # so second address (10.11.12.13) is needed for V2 instance

    local issu_id=`xr_bootstrap_field_value ISSU_ID`
    if [ $issu_id -eq 1 ] && [[ "${BOARDTYPE}" == "LC" ]]; then
        kmsg_exec "ifconfig eth-vf0 10.11.12.13/24 up"
    else
        kmsg_exec "ifconfig eth-vf0 10.11.12.14/24 up"
    fi
    kmsg_exec "route add default gateway 10.11.12.2 eth-vf0"
    kmsg_exec "route add 10.0.2.16 eth-vf0"
}


function configure_from_xr_bootstrap_lxc
{
    source /etc/rc.d/init.d/spirit_pd.sh
    local issu_role=`xr_bootstrap_field_value ISSU_ROLE`
    local issu_id=`xr_bootstrap_field_value ISSU_ID`
    local hw_ct=$( get_hw_cardtype )

    kmsg_log "configure_from_xr_bootstrap_lxc $issu_role $issu_id"

    declare -F platform_log &>/dev/null && \
    platform_log "configure from XR bootstrap ISSU role $issu_role id $issu_id"

    # configuration must match with lxc_set_sdr_intf_hook
    if [ $issu_id -eq 1 ] && [[ "${BOARDTYPE}" == "LC" ]]; then
        kmsg_exec "ifconfig eth-vnic4 down"
        rename_nic  eth-vnic4  eth-vf1
        config_nic  eth-vf1 0
        rename_nic  eth-vnic6  eth-punt
        config_nic  eth-punt 0
        rename_nic  eth-vnic8  eth-bfd
        config_nic  eth-bfd 0
        rename_nic  eth-vnic10  eth-srpm
        config_nic  eth-srpm 0
        case "$hw_ct" in
        ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed LC
            rename_nic  eth-vnic12  eth-flexe
            config_nic  eth-flexe 0
            ;;
        esac
    else    
        kmsg_exec "ifconfig eth-vnic2 down"
        rename_nic  eth-vnic2  eth-vf1
        config_nic  eth-vf1 0
        rename_nic  eth-vnic5  eth-punt
        config_nic  eth-punt 0
        if [[ "${BOARDTYPE}" == "LC" ]]; then
            rename_nic  eth-vnic7  eth-bfd
            config_nic eth-bfd 0
            rename_nic  eth-vnic9  eth-srpm
            config_nic  eth-srpm 0
            case "$hw_ct" in
            ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed LC
                rename_nic  eth-vnic11  eth-flexe
                config_nic  eth-flexe 0
                ;;
            esac
        else
            rename_nic  eth-vnic7  eth-tpa
            config_nic eth-tpa 0
        fi
    fi
}

# Invoked when host set the vmm cfg as XR bootstrap
# modify the bootstrap if needed
# configure XR based on bootstrap parameters
function platform_patch_xr_bootstrap
{
    local xr_bootstrap=$1
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    declare -F platform_log &>/dev/null && platform_log "XR bootstrap $xr_bootstrap"
    declare -F platform_log &>/dev/null && platform_log "virt_method= $virt_method"

    if [[ "${virt_method}" == "lxc" ]]; then
        configure_from_xr_bootstrap_lxc
        setup_host_access_lxc
    fi
}

#
# Get the offset for any block $1: String/block name $2: Instance number
#
function get_ipu_block_offset {
    if [[ -z ${IPU_BASE} ]]; then
        return
    fi
    local req=$1
    local inst=$2
    echo $($myshowipu -p ${IPU_BASE} | grep $req | cut -d ":" -f1 | sed -n ${inst}p)
}

#
# Set the MUX settings for XR console
#
function platform_get_mux_tty_settings
{
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    skip_pd_functions
    if [ $? -ne 0 ] || [ "$virt_method" == "vm" ]; then
        return;
    fi
    
    MUX_TTY=/dev/ttyS0
    MUX_TTY_SPEED=115200
    MUX_TTY_TYPE=1
    MUX_TTY_FLOWCTRL=""
    MUX_TTY_SOCAT_OPTION="raw,echo=0,opost=1"
}

#
# Set the MUX settings for calvados console
#
function platform_get_mux_calvados_tty_settings
{
    local virt_method=`cal_bootstrap_field_value VIRT_METHOD`

    skip_pd_functions
    if [ $? -ne 0 ] || [ "$virt_method" == "vm" ]; then
        return;
    fi

    MUX_TTY=/dev/ttyS1
    MUX_TTY_SPEED=115200
    MUX_TTY_TYPE=2
    MUX_TTY_FLOWCTRL=""
    MUX_TTY_SOCAT_OPTION="raw,echo=0,opost=1"
}


function pcimemsetbit {
    local offset=$1
    local setbit=$2
    
    local val=$( pcimemread $offset 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^/0x/' )
    let "val = $val | $setbit"
    val=0x$( printf "%08x" $val )
    pcimemwrite $offset 4 $val &> /dev/null
    local new_val=$( pcimemread $offset 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^/0x/' )
    if [ $val != $new_val ]; then
        echo set failure offset $offset wrote $val read back $new_val
    fi
}

function pcimemclrbit {
    local offset=$1
    local setbit=$2
    
    local val=$( pcimemread $offset 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^/0x/' )
    let "setbit = ~ $setbit"
    let "val = $val & $setbit"
    val=0x$( printf "%08x" $val )
    pcimemwrite $offset 4 $val &> /dev/null
    local new_val=$( pcimemread $offset 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^/0x/' )
    if [ $val != $new_val ]; then
        echo clr failure offset $offset wrote $val read back $new_val
    fi
}

function oir_reset {
    local OIR_RESET_SUPPORT=$(get_card_specific_value OIR_RESET_SUPPORT)
    OIR_RESET_SUPPORT=$(printf "%d" $OIR_RESET_SUPPORT)

    if [ $OIR_RESET_SUPPORT -eq 0 ]; then
      echo Skipping OIR Reset > /dev/ttyS0
      return
    fi

    echo Issuing OIR Reset > /dev/ttyS0
    # OIR reset supported by card. Programming it (if we find an IPU_BASE).
    INFO_ROM_X86_CTRL_OFF=0xE0
    SLOT_INFO_OFF=0xC8

    if [[ -z ${IPU_BASE} ]]; then
        kmsg_log "Warning: No IPU base - skipping oir reset"
        return
    fi

    SLOT_INFO_ADDR=$(( $IPU_BASE + $SLOT_INFO_OFF )) 
    SLOT_ID=$( pcimemread `printf "%x" $SLOT_INFO_ADDR` 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^0/0x0/' )
    SLOT_ID=$( printf "0x%x" $(( $SLOT_ID & 0x1F )))

    if (($SLOT_ID == 0x1f)); then
        kmsg_log "Warning: Running on bench - skipping oir reset"
        return
    fi

    X86_CTRL_ADDR=$(( $IPU_BASE + $INFO_ROM_X86_CTRL_OFF ))
    X86_CTRL_OFF=$( pcimemread `printf "%x" $X86_CTRL_ADDR` 0x4 | grep -v PCI | awk '{ print $3 ; }' | sed -e 's/^0/0x0/' )
    
    X86_CTRL_CKEY_OFF=$(( $IPU_BASE + $X86_CTRL_OFF + 0x20 ))
    X86_CTRL_CKEY_OFF=$( printf "%x" $X86_CTRL_CKEY_OFF )

    X86_CTRL_CTRL_OFF=$(( $IPU_BASE + $X86_CTRL_OFF + 0x24 ))
    X86_CTRL_CTRL_OFF=$( printf "%x" $X86_CTRL_CTRL_OFF )

    pcimemsetbit $X86_CTRL_CKEY_OFF 0x10000
    pcimemsetbit $X86_CTRL_CTRL_OFF 0x10000
    pcimemclrbit $X86_CTRL_CKEY_OFF 0x10000
}

# Patch host_auth* files to stop console output for noise control
function patch_host_auth {
    local rootdir=$1
    local hauth_xr="${rootdir}/etc/init/host_auth.conf"
    local hauth_calv="${rootdir}/etc/init/host_auth_calvados.conf"
    if [ -f ${hauth_xr} ]; then
        sed -i -e "s;console output;;" ${hauth_xr}
    fi
    if [ -f ${hauth_calv} ]; then
        sed -i -e "s;console output;;" ${hauth_calv}
    fi
}

function show_bars
{
    local vid=$1
    local did=$2
    local virt_method=$4
    local name=$5
    local count=0

    local bdf_list=$( lspci -d $vid:$did | awk '{ print $1 }' )
    for bdf in $bdf_list; do
        local bars=$(   lspci -s $bdf -v      | \
                        grep "Memory at"      | \
                        awk '{ print $3 $6 }' | \
                        sed -e "s;size=;;"    | \
                        paste -d" " - - - )

        local cmd=$(    lspci -s $bdf -x      | \
                        grep 00: | awk '{print $7 $6}' )

        if [ "${BOARDTYPE}" == "LC" ]; then
            if [ "$VM_TYPE" == "hostos" ]; then
                echo "$vid:$did $bdf ${bars} ${cmd}"
            fi
        fi
        kmsg_log "$vid:$did $bdf ${bars} ${cmd}"
        let "count = $count + 1"
    done
    if [[ $count != 0 ]]; then
        if [ "$VM_TYPE" == "hostos" ]; then
            echo Discovered ${name} ${vid}:${did} x${count}
            echo Discovered ${name} ${vid}:${did} x${count} >> /dev/ttyS0
            echo ${name} ${vid}:${did} x${count} >> /root/dev_inv.txt
        fi
    fi
    return $count
}

function pcie_proxy_enable
{
    local vid=$1
    local did=$2
    local VM_TYPE=$3
    local VIRT_METHOD=$4
    local NAME=$5

    case "$did" in
    234*)   # Skip msix virtual devices
        ;;
    5678)   # Skip dma virtual device
        ;;
    *)      # Everything else
        show_bars $vid $did $VM_TYPE $VIRT_METHOD $NAME
        ;;
    esac
    if [ "$VM_TYPE" == "hostos" ] || [ "$VIRT_METHOD" == "vm" ]; then
        echo "$vid $did" > /sys/bus/pci/drivers/pci_proxy/new_id
    fi
}

function a9k_show_card
{
  local tempval

  tempval=$(grep MemTotal /proc/meminfo | awk '{print $2}')
  echo MEM ${tempval} kB >> /root/dev_inv.txt
  echo Discovered MEM ${tempval} kB >> /dev/ttyS0

  tempval=$(showemt | grep card_pid  | awk '{print $3}')
  echo PID ${tempval} >> /root/dev_inv.txt
  echo Discovered PID ${tempval} >> /dev/ttyS0

  tempval=$(showemt | grep card_serial  | awk '{print $3}')
  echo SNO ${tempval} >> /root/dev_inv.txt
  echo Discovered SNO ${tempval} >> /dev/ttyS0

  tempval=$(showemt | grep chassis_pid  | awk '{print $3}')
  echo CPD ${tempval} >> /root/dev_inv.txt
  echo Discovered CPD ${tempval} >> /dev/ttyS0

  tempval=$(showemt | grep chassis_serial  | awk '{print $3}')
  echo CSN ${tempval} >> /root/dev_inv.txt
  echo Discovered CSN ${tempval} >> /dev/ttyS0
}

function a9k_pcie_proxy_enable
{
  local VM_TYPE=$1
  local VIRT_METHOD=$2

  # Marvell
  pcie_proxy_enable "11ab" "8000" $VM_TYPE $VIRT_METHOD "ESD"
  pcie_proxy_enable "11ab" "c81f" $VM_TYPE $VIRT_METHOD "ESD"
  pcie_proxy_enable "11ab" "c81e" $VM_TYPE $VIRT_METHOD "ESD"
  pcie_proxy_enable "11ab" "c81d" $VM_TYPE $VIRT_METHOD "ESD"
  pcie_proxy_enable "11ab" "c800" $VM_TYPE $VIRT_METHOD "ESD"

  # Lewis
  pcie_proxy_enable "11ab" "be10" $VM_TYPE $VIRT_METHOD "ESD"

  # IPU
  pcie_proxy_enable "10b5" "87a0" $VM_TYPE $VIRT_METHOD "IPU"
  pcie_proxy_enable "10b5" "87b1" $VM_TYPE $VIRT_METHOD "IPU"
  pcie_proxy_enable "1137" "87a0" $VM_TYPE $VIRT_METHOD "IPU"
  pcie_proxy_enable "1137" "87a1" $VM_TYPE $VIRT_METHOD "SEC"
  pcie_proxy_enable "1137" "87a2" $VM_TYPE $VIRT_METHOD "TIM"
  pcie_proxy_enable "1137" "87a3" $VM_TYPE $VIRT_METHOD "SST"
  pcie_proxy_enable "1137" "87a4" $VM_TYPE $VIRT_METHOD "HPN"

  # Fabric devices
  pcie_proxy_enable "1137" "00ca" $VM_TYPE $VIRT_METHOD "FAB"
  pcie_proxy_enable "1137" "0082" $VM_TYPE $VIRT_METHOD "FAB"
  pcie_proxy_enable "1137" "003b" $VM_TYPE $VIRT_METHOD "FAB"
  pcie_proxy_enable "1137" "00fb" $VM_TYPE $VIRT_METHOD "FAB"
  pcie_proxy_enable "1137" "0141" $VM_TYPE $VIRT_METHOD "FAB"

  # Skybolt
  pcie_proxy_enable "1137" "018e" $VM_TYPE $VIRT_METHOD "FAB"

  # MSIX Virtual device
  pcie_proxy_enable "1137" "2345" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "2346" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "2347" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "2348" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "2349" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "234a" $VM_TYPE $VIRT_METHOD "MSI"
  pcie_proxy_enable "1137" "234b" $VM_TYPE $VIRT_METHOD "MSI"

  # DMA virtual device
  pcie_proxy_enable "1137" "5678" $VM_TYPE $VIRT_METHOD "DMA"

  # ETNA
  pcie_proxy_enable "1137" "0120" $VM_TYPE $VIRT_METHOD "LBK"

  # FRENZY
  pcie_proxy_enable "1137" "016b" $VM_TYPE $VIRT_METHOD "LBK"

  # NP5C
  pcie_proxy_enable "11ab" "05c1" $VM_TYPE $VIRT_METHOD "NPU"

  # Sureshot FPGA's  need for each MPA fpga type
  pcie_proxy_enable "1137" "0094" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0095" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0096" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0097" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "009b" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0100" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0167" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "016a" $VM_TYPE $VIRT_METHOD "MPA"
  pcie_proxy_enable "1137" "0262" $VM_TYPE $VIRT_METHOD "MPA"

  # lightspeed SIM
  pcie_proxy_enable "1137" "005d" $VM_TYPE $VIRT_METHOD "LSQ"

  # lightspeed LSQ
  pcie_proxy_enable "1137" "018d" $VM_TYPE $VIRT_METHOD "LSQ"

  # lightspeed LSP
  pcie_proxy_enable "1137" "a002" $VM_TYPE $VIRT_METHOD "LSP"
}

function reset_eobc_switch
{
  local hw_ct
  local downstream_did

  if [[ -z ${HW_CARDTYPE} ]]; then
      kmsg_log "reset_eobc_switch $1: HW_CARDTYPE not set"
      return
  fi
  let "hw_ct = ${HW_CARDTYPE} & 0x3f"

  hw_ct=$( printf "%02x" ${hw_ct} )

  case "$hw_ct" in
  ${IPU_TYPE_AZ}|${IPU_TYPE_BDW_LSQ}|${IPU_TYPE_BDW_LSP}) # Lightspeed LC
      case "$hw_ct" in
      ${IPU_TYPE_AZ})
        downstream_did=19ab
        # This change needs to be reverted after BIOS fix is issued. 
        # Set EXTCAP (0x42) bit 8 to 0
        setpci -d :${downstream_did} CAP_EXP.l=0:1000000
        sleep .25
        # Clear bit 3 at SLOTSTS (0x5A) after setting EXTCAP. Write 1 to clear
        setpci -d :${downstream_did} CAP_EXP+18.l=80000:80000
        ;;
      esac

      /opt/cisco/calvados/bin/es_reset_ng -i eth-pf1 -j eth-pf2 -l
      kmsg_log "es_reset_ng returned with rc $?"
      ifconfig eth-pf1 up
      ifconfig eth-pf2 up
      ;; 
  26) # RSP4-Lite
      /opt/cisco/calvados/bin/es_reset_ng -i eth0 -j eth3 -r
      kmsg_log "RSP4-Lite es_reset_ng returned with rc $?"
      ifconfig eth0 up
      ifconfig eth1 up
      ifconfig eth2 up
      ifconfig eth3 up
      ;;
  ${IPU_TYPE_RPBB}) # RPBB
      /opt/cisco/calvados/bin/es_reset_ng -i eth5 -j eth3 -a
      ;;
  27) # RSP5
      /opt/cisco/calvados/bin/es_reset_ng -i eth5 -j eth7 -a
      ;;
  28) # RP3
      /opt/cisco/calvados/bin/es_reset_ng -i eth5 -j eth7 -a
      /opt/cisco/calvados/bin/es_reset_ng -b
      ;;
  29) # Starlord RP
     /opt/cisco/calvados/bin/es_reset_ng -i eth-0 -j eth-1 -s
     kmsg_log "starlord RP es_reset_ng rc $?"
     ifconfig eth-0 up
     ifconfig eth-1 up
     ;;
  0c) # Starlord LC
     kmsg_log "no eobc switch on starlord LC..return"
     ;;
  0[6]) # Powerglide LC
     /opt/cisco/calvados/bin/es_reset_ng -i eth-pf1 -j eth-pf4
     kmsg_log "es_reset_ng for Powerglide returned with rc $?"
     ifconfig eth-pf1 up
     ifconfig eth-pf3 up
     ifconfig eth-pf4 up
     ;;
  *)  # Everything else
     es_reset
     kmsg_log "es_reset returned with rc $?"
     ;;
  esac
}

function a9k_devices_enable
{
  local VM_TYPE=$1
  local VIRT_METHOD=$2

  # Enable PCIE RPC server
  initctl start pcie_rpc_svr
  
  # Start MSIX daemon on Host only with LXCs
  if [[ $VIRT_METHOD == "lxc" ]]; then
      msixd -v 0x1137 -d 0x2345
  fi

  is_vxr_sim
  if [[ $? != 1 ]]; then
      reset_eobc_switch
  fi

  reset_lgt_pcie $VM_TYPE $VIRT_METHOD
  update_host_counters

  # On oir immediately reset card
  oir_reset
  
  # Enable PCIE linkmon server post lgt reset
 is_vxr_sim
 if [[ $? != 1 ]]; then
     initctl start linkmonhost 
     initctl start hcd_client 
 fi    
}

function a9k_show_nics
{
    if [[ -f /tmp/nics ]]; then
        cat /tmp/nics >> /dev/ttyS0
    fi
}

function a9k_show_media
{
    local size
    local install=$(cat /proc/cmdline | grep install=)

    for i in sda sdb sdc sdd; do
        if [[ -b /dev/$i ]]; then
            size=$( fdisk -l /dev/$i    | \
                grep Disk | head -1     | \
                awk '{print $3 $4}'     | \
                sed -e "s;,;;" )
            if [ -n "${install}" ]; then
                step_log_console "Discovered $i: $size"
            else
                echo     "Discovered DSK $i: $size" >> /dev/ttyS0
                echo     "DSK $i: $size" >> /root/dev_inv.txt
                kmsg_log "Discovered DSK $i: $size"
            fi
        fi
    done
}


#App hosting Cgroup settings
function pd_tpa_cgroup_settings
{
    APP_CGROUP_MEM_NUMA_NODES=0
    APP_CGROUP_CPUSET_CPUS=1
    APP_CGROUP_CPU_SHARES=512
    APP_CGROUP_MEM_LIMIT_IN_BYTES=1G
}

function modify_init_console_para_xr()
{
    local XROOT=$1
    local devc_con=`ls -l ${XROOT}/pkg/init.d/devc_conaux_con.init | awk '{print $11}'`
    local devc_aux=`ls -l ${XROOT}/pkg/init.d/devc_conaux_aux.init | awk '{print $11}'`

    ACTIVE_SERIAL_XR_CON="pts/0"
    ACTIVE_SERIAL_XR_AUX="pts/1"

    #
    # Allow platform to override ACTIVE_SERIAL_XR_CON/AUX
    #
    platform_enable_xr_con
    sed -i "s;pts/0;$ACTIVE_SERIAL_XR_CON;g" ${XROOT}/${devc_con}

    platform_enable_xr_aux
    sed -i "s;hvc1;$ACTIVE_SERIAL_XR_AUX;g" ${XROOT}/${devc_aux}
}

# Function called by pxe_install.sh script to allow PD to patch hostos boot
# partition.
function pd_pxe_install_patch_hostos_boot
{
    local LOCAL_PARTMNT=$1
    local LOCAL_LVG_NAME=$2
    local LOCAL_LV_ID=$3

    /etc/init.d/calvados_patch_lxc_iso.sh ${LOCAL_PARTMNT} ${LOCAL_LVG_NAME} \
        ${LOCAL_LV_ID} "hostos"

}

# Function called by pxe_install.sh script to allow PD to patch SysAdmin VM
# boot partition.
function pd_pxe_install_patch_sysadmin_vm_boot
{
    local LOCAL_PARTMNT=$1
    local LOCAL_LVG_NAME=$2
    local LOCAL_LV_ID=$3

    /etc/init.d/calvados_patch_lxc_iso.sh ${LOCAL_PARTMNT} ${LOCAL_LVG_NAME} \
        ${LOCAL_LV_ID} "sysadmin-vm"
}

function replace_calv_boot_strap_cfg () {

    local disk_size_float=$(fdisk -l /dev/sda | grep "Disk /dev/sda" | awk '{printf $3}')
    local disk_size=${disk_size_float%.*}
    local hw_ct=$( get_hw_cardtype )

    if [[ "${disk_size}" -gt "100" ]]; then
        kmsg_log "Replacing Bootstrap File"
        case "$hw_ct" in
        ${IPU_TYPE_RPBB}|${IPU_TYPE_LC99NG})  # RPBB/LCBB/LCSL
            cp -pf /etc/rc.d/init.d/calvados_bootstrap_bb.cfg \
                   /etc/rc.d/init.d/calvados_bootstrap.cfg
            ;;
        *) # All other IPU types 
            cp -pf /etc/rc.d/init.d/calvados_bootstrap_ng.cfg \
                   /etc/rc.d/init.d/calvados_bootstrap.cfg
            ;;
        esac
        cp -pf /etc/rc.d/init.d/calvados_bootstrap.cfg /var/log
    else
        kmsg_log "Retaining Bootstrap File"
        cp -pf /etc/rc.d/init.d/calvados_bootstrap.cfg /var/log
        return
    fi
    source /etc/rc.d/init.d/calvados_bootstrap.cfg
}

