#!/bin/bash

#------------------------------------------------------------------------
# August, 2014, Balaji Krishnamoorthy
# Copyright (c) 2014-2017, 2019 by Cisco Systems, Inc.
# All Rights Reserved
#------------------------------------------------------------------------

MYADDR=$(ifconfig eth-vf1.3073 | sed -n -e '/inet addr/s/^.*inet addr:\([1-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*$/\1/p')
   
CONFDADDR=$(ds_test_client -l confd6 | sed -n -e '/ha_role=ACTIVE/s/^.*, *ip=\([1-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*$/\1/p')
 
function usagexit() {
    echo ""
    echo "  USAGE : $0 [OPTIONS] LINK"
    echo ""
    echo "  Parses information from the link R/S/A/L"
    echo "     -A : print all info"
    echo "     -a : get asic inst"
    echo "     -d : get the rack/slot of the node where active driver is running"
    echo "     -e : get asic FAP/FE ID"
    echo "     -f : get physical slot"
    echo "     -h : print this help"
    echo "     -i : get the IP address of the node where active driver is running"
    echo "     -l : get link number"
    echo "     -o : get logical slot"
    echo "     -p : get port number (could be the same or different from link)"
    echo "     -r : get rack"
    echo "     -s : get slot"
    echo "     -u : get asic unit number"
    echo ""
    echo "    LINK is provided as R/S/A/L"
    echo "          R : Rack range LCC:0 to 15, FCC:F0 to F3"
    echo "          S : LC slot range: 0 to 7, FC slot range LCC:FC0 to FC5, FCC:FC0 to FC11"
    echo "          A : SFE Asic range L-FC1:0 to 1, L-FC-M:0 to 3, FFC:0 to 2"
    echo "          L : FIA link number range 0 to 35, SFE link number range 0 to 127."
    echo ""
    exit 1
} >&2

option=
while getopts "rdsfaliophueA" o; do
    if [ "${o}" == "A" \
      -o "${o}" == "a" \
      -o "${o}" == "d" \
      -o "${o}" == "e" \
      -o "${o}" == "f" \
      -o "${o}" == "i" \
      -o "${o}" == "l" \
      -o "${o}" == "o" \
      -o "${o}" == "p" \
      -o "${o}" == "r" \
      -o "${o}" == "s" \
      -o "${o}" == "u" ]; then
    #
    # we do not expect this script to be called with multiple flags. 
    # so it is ok to overwrite option.
    #
        option="${o}"
    else
        usagexit;
    fi
done

location=(`echo $BASH_ARGV | tr '/' ' ' | tr [:lower:] [:upper:]`)
rack=${location[0]}
slot=${location[1]}
asic=${location[2]}
link=${location[3]}

# Validate the Rack/slot
if [[ "$MYADDR" != "$CONFDADDR" ]]; then
    scp -p ${CONFDADDR}:/tmp/show.platform /tmp >& /dev/null
fi
find /tmp -maxdepth 1 -cmin -10 | grep 'show\.platform' >& /dev/null
if [[ $? -ne 0 ]]; then
    show_cmd "show platform | save /tmp/show.platform" > /dev/null
    if [[ "$MYADDR" != "$CONFDADDR" ]]; then
        scp -p ${CONFDADDR}:/tmp/show.platform /tmp >& /dev/null
    fi
fi

grep -q "$rack/$slot" /tmp/show.platform
if [[ $? -ne 0 ]]; then
    echo " Fabric card $rack/$slot not present in show platform" >&2
    exit 65
fi

# Validate the card_type/Asic
if [[ $rack =~ ^[0-9] ]]; then

    if [ $rack -ge 16 ]; then
        echo "LCC rack $rack out of range!!" >&2
        exit 73
    fi

    if [[ $slot =~ ^[0-7] ]]; then
        log=$slot
        let asics=5
        let offset=0
    elif [[ "$slot" =~ FC[0-5]$ ]]; then
        log=${slot#FC}
        let asics=4
        let offset=6
    else
        echo "LCC slot $slot out of range!!!" >&2
        exit 86
    fi
elif [[ "$rack" =~ F[0-3] ]]; then
    if [[ "$slot" =~ FC[0-9][0-1]* ]]; then
        log=${slot#FC}
        if [[ $log -ge 12 ]]; then
            echo "FCC slot $slot out of range!!!" >&2
            exit 93
        fi

        let asics=3
        let offset=3
    else
        echo "FCC slot $slot invalid!!!" >&2
        exit 100
    fi
else
    echo "FCC rack $rack out of range!!!" >&2
    exit 104
fi

if [ -z "$asic" ]; then
    echo "Asic instance not present!!!" >&2
    exit 109
fi

if [[ $asic -ge $asics ]]; then
    echo "Asic instance $asic out of range!!!" >&2
    exit 114
fi

if [ -z "$link" ]; then
    echo "Link not present!!!" >&2
    exit 132
fi

if [[ $asics -eq 5 ]]; then
    if [[ $link -ge 36 ]]; then
        echo "FIA link $link out of range!!!" >&2
        exit 138
    fi
else
    if [[ $link -ge 144 ]]; then
        echo "SFE link $link out of range!!!" >&2
        exit 143
    fi
fi

#
# All validations done. Generate the output.
#

if [ "$option" == "r" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Rack                      : "
    echo "$rack"
    [ "$option" == "r" ] && exit 0
fi

if [ "$option" == "s" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Slot                      : "
    echo "$slot"
    [ "$option" == "s" ] && exit 0
fi

if [ "$option" == "a" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Asic Instance on Slot     : "
    echo "$asic"
    [ "$option" == "a" ] && exit 0
fi

if [ "$option" == "l" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Link number               : "
    echo "$link"
    [ "$option" == "l" ] && exit 0
fi

if [ "$option" == "o" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Logical slot              : "
    echo "$log"
    [ "$option" == "o" ] && exit 0
fi

grep panini /proc/cmdline >& /dev/null
if [ $? -eq 0 ]; then
    # NCS6K
    if [[ "$slot" =~ FC ]]; then
        phy=${slot#FC}
        let phy+=8
    else
        phy=$((slot + 16))
    fi
else
    # NCS4K
    if [[ $rack =~ ^[0-9] ]]; then
        # LCC
        if [[ "$slot" =~ FC ]]; then
            if [[ "$log" == 0 ]]; then
                phy=5
            elif [[ "$log" == 1 ]]; then
                phy=6
            elif [[ "$log" == 2 ]]; then
                phy=16
            elif [[ "$log" == 3 ]]; then
                phy=17
            fi
        fi
    else
        # FCC
        if [[ "$slot" =~ FC ]]; then
            phy=${slot#FC}
            let phy+=8
        fi
    fi
fi

if [ "$option" == "f" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Physical slot             : "
    echo "$phy"
    [ "$option" == "f" ] && exit 0
fi

if [ "$option" == "e" -o "$option" == "A" ]; then
    if [[ $rack =~ ^[0-9] ]]; then
        if [[ $slot =~ ^[0-7] ]]; then
            feid=$(( rack * 48 + log * 6 + asic ))
        else
            feid=$(( 768 + rack * 36 + log * offset + asic ))
        fi
    else
        rackoffset=${rack#F}
        feid=$(( 1344 + rackoffset * 36 + log * offset + asic ))
    fi

    [ "$option" == "A" ] && echo -n "FAP/FE ID                 : "
    echo "$feid"
    [ "$option" == "e" ] && exit 0
fi


if [ "$option" == "u" -o "$option" == "A" ]; then
    unit=$(( log * offset + asic ))
    [ "$option" == "A" ] && echo -n "Unit                      : "
    echo "$unit"
    [ "$option" == "u" ] && exit 0
fi

if [ "$option" == "p" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "SFI (port) number         : "
    if [[ "$slot" =~ FC ]]; then
        echo "$link"
    else
        port=$(( link + 256 ))
        echo "$port"
    fi
    [ "$option" == "p" ] && exit 0
fi

if [ "$option" == "i" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "IP Address for driver     : "
    if [[ "$slot" =~ FC ]]; then
        if [[ "$MYADDR" != "$CONFDADDR" ]]; then
            scp -p ${CONFDADDR}:/tmp/sfe.driver.${rack} /tmp >& /dev/null
        fi
        find /tmp -maxdepth 1 -cmin -10 | grep 'sfe\.driver\.${rack}' >& /dev/null
        if [[ $? -ne 0 ]]; then
            show_cmd "show controller sfe driver rack $rack | save /tmp/sfe.driver.${rack}" >& /dev/null
            if [[ "$MYADDR" != "$CONFDADDR" ]]; then
                scp -p ${CONFDADDR}:/tmp/sfe.driver.${rack} /tmp >& /dev/null
            fi
        fi

        ipaddr=$(grep '^Rack: ' /tmp/sfe.driver.${rack} | awk '{print $NF}')
    else
        #
        # the logic of finding the FIA driver location is different for NCS4K and NCS6K
        #
        grep panini /proc/cmdline >& /dev/null
        if [ $? -eq 0 ]; then
            #
            # driver runs on the linecard. Find its XR ip address
            #
            ipaddr=$(findnodeip "$rack/$slot" "IOS-XR-LC")
        else 
            # NCS4K
            thisRS=$(hostname | cut -d':' -f2 | tr '_' '/')
            thisXR=$(findnodeip $thisRS "IOS-XR-RP")
            activeRPRS=$(ssh -q $thisXR /pkg/bin/redcon_show -s | grep "${rack}/RP" | awk '{print $1}')
            ipaddr=$(findnodeip $activeRPRS "IOS-XR-LC")
        fi
    fi
    echo "$ipaddr"
    [ "$option" == "i" ] && exit 0
fi

if [ "$option" == "d" -o "$option" == "A" ]; then
    [ "$option" == "A" ] && echo -n "Driver is running on      : "
    if [[ "$slot" =~ FC ]]; then
        if [[ "$MYADDR" != "$CONFDADDR" ]]; then
            scp -p ${CONFDADDR}:/tmp/sfe.driver.${rack} /tmp >& /dev/null
        fi
        find /tmp -maxdepth 1 -cmin -10 | grep 'sfe\.driver\.${rack}' >& /dev/null
        if [[ $? -ne 0 ]]; then
            show_cmd "show controller sfe driver rack $rack | save /tmp/sfe.driver.${rack}" >& /dev/null
            if [[ "$MYADDR" != "$CONFDADDR" ]]; then
                scp -p ${CONFDADDR}:/tmp/sfe.driver.${rack} /tmp >& /dev/null
            fi
        fi

        touch /tmp/sfe.driver.${rack}

        driver_rack_slot=$(grep '^Rack: ' /tmp/sfe.driver.${rack} | awk '{print $2}' | tr -d ',')
    else
        #
        # the logic of finding the FIA driver location is different for NCS4K and NCS6K
        #
        grep panini /proc/cmdline >& /dev/null
        if [ $? -eq 0 ]; then
            #
            # driver runs on the linecard. Find its XR ip address
            #
            driver_rack_slot="$rack/$slot/CPU0"
        else 
            # NCS4K
            thisRS=$(hostname | cut -d':' -f2 | tr '_' '/')
            thisXR=$(findnodeip $thisRS "IOS-XR-RP")
            driver_rack_slot=$(ssh -q $thisXR /pkg/bin/redcon_show -s | grep "${rack}/LC" | awk '{print $1}')
        fi
    fi
    echo "$driver_rack_slot"
    [ "$option" == "d" ] && exit 0
fi

exit 0



