#!/bin/sh


# On CORTINA CHASSIS,
# udev rules will create the following:
# eth0, eth6 are HA eobc
# eth2, eth3 are HA epc.

# identify platform
. /etc/init.d/mod_ins/module-load-functions

# Global vars
MGMT_INTF=eth-mgmt
MY_MOD_ID_HEX="$(my_slot_id x)"
MY_MOD_ID="$(my_slot_id)"
MY_SLOT_ID="$(($MY_MOD_ID-1))"
INBAND_MTU=9702
VEOBC_MTU=9702

boot_debug "Got my slot: MY_MOD_ID_HEX=$MY_MOD_ID_HEX MY_MOD_ID=$MY_MOD_ID MY_SLOT_ID=$MY_SLOT_ID"

setup_eobc_sup() {

    # turn off flow control
    /usr/sbin/ethtool -A eth0 rx off tx off
    /usr/sbin/ethtool -A eth6 rx off tx off
    /sbin/ifconfig eth0 down hw ether 00:00:00:00:$MY_MOD_ID_HEX:01 mtu $VEOBC_MTU
    /sbin/ifconfig eth6 down hw ether 00:00:00:00:$MY_MOD_ID_HEX:01 mtu $VEOBC_MTU
}

setup_inband_sup() {

    # turn off flow control
    /usr/sbin/ethtool -A eth2 rx off tx off
    /usr/sbin/ethtool -A eth3 rx off tx off
    # change the mac for eth2
    /sbin/ifconfig eth2 down hw ether 00:00:00:01:$MY_MOD_ID_HEX:01
    /sbin/ifconfig eth3 down hw ether 00:00:00:01:$MY_MOD_ID_HEX:01
    /sbin/ifconfig eth2 mtu $INBAND_MTU
    /sbin/ifconfig eth3 mtu $INBAND_MTU
}

install_psdev_sup() {

    boot_debug "Installing psdev ..."

    local card_idx=$(get_cmdline_card_index)
    local is_vm=0
    if [ -f /vmachine ]; then
        is_vm=1
    fi
    if [ "$card_idx" == 27024 ] || 
       [ "$card_idx" == 27059 ]; then
        insmod -f /lib/modules/klm_psdev.o eobc_dev_names=eth0,eth6 epc_dev_names=eth2,eth3 vmachine=$is_vm flex_filter_support=0
    else
        insmod -f /lib/modules/klm_psdev.o eobc_dev_names=eth0,eth6 epc_dev_names=eth2,eth3 vmachine=$is_vm flex_filter_support=1
    fi

    # configure the interfaces
    /sbin/ifconfig ps-eobc down
    /sbin/ifconfig ps-eobc hw ether 00:00:00:00:$MY_MOD_ID_HEX:01 mtu $VEOBC_MTU
    /sbin/ifconfig ps-eobc up
    /sbin/ifconfig ps-inb down
    /sbin/ifconfig ps-inb hw ether 00:00:00:01:$MY_MOD_ID_HEX:01
    /sbin/ifconfig ps-inb up
    /sbin/ifconfig ps-inb mtu $INBAND_MTU
}

install_veobc() {

    boot_debug "Installing veobc ..."

    insmod -f /lib/modules/klm_veobc.o eobc=ps-eobc inband=ps-inb

    # configure the interfaces
    /sbin/ifconfig veobc down
    /sbin/ifconfig veobc hw ether 00:00:00:00:$MY_MOD_ID_HEX:01 mtu $VEOBC_MTU
    /sbin/ifconfig veobc up
}

sanitize_eth() {

    # Disable all offload optimizations
    # netstack cannot handle it.

    /usr/sbin/ethtool -K $1 gso off 
    /usr/sbin/ethtool -K $1 tso off 
    /usr/sbin/ethtool -K $1 lro off 
    /usr/sbin/ethtool -K $1 gro off 
}


setup_dhcpd_conf() {

    # Copy the appropriate DHCPD conf file
    cp /etc/dhcp/dhcpd.conf.slot${MY_SLOT_ID} /etc/dhcp/dhcpd.conf
}

create_dummy_eobc () {

    # Create dummy interfaces for faking eobc 
    /sbin/ip link add type dummy
    /sbin/ip link add type dummy
    /sbin/ip link add type dummy
}

set_irq_affinity() {                                                                                                                               
    dev_name=$1
    local smp_mask=$2
    /sbin/ifconfig $dev_name up    
    for i in `cat /proc/interrupts | grep $dev_name | awk -F':' '{printf("%d\n", $1)}'`;
    do
        echo $smp_mask > /proc/irq/$i/smp_affinity_list
    done
    /sbin/ifconfig $dev_name down
}

configure_igb_rings() {
    local dev_name=$1
    local ring_size=$2
    /usr/sbin/ethtool -G $1 tx $ring_size
    /usr/sbin/ethtool -G $1 rx $ring_size
}

sup_pre_init() {
    local card_idx=$(get_cmdline_card_index)
    
    # Setup interrupt affinity
    # Separate out the EPC traffic from EOBC/Mgmt
    set_irq_affinity eth0 "2-3"
    set_irq_affinity eth6 "2-3"

    set_irq_affinity eth2 "0-1"
    set_irq_affinity eth3 "0-1"

    # Setting mgmt affinity
    set_irq_affinity eth-mgmt 1

    # Set the eth-ptp affinity on the Precisa SyncE RP
    if [ "$card_idx" == 27024 ] || 
       [ "$card_idx" == 27059 ]; then
        set_irq_affinity eth-ptp 1
    fi

    setup_eobc_sup

    setup_inband_sup
    if [ "$card_idx" == 27024 ] || 
       [ "$card_idx" == 27059 ]; then
        /usr/sbin/ethtool -X eth-mgmt weight 1 1

        # Disable xps queues to reduce probability of out-of-sequence 
        # packets caused by context switches between CPU cores
        for xps_cpus in /sys/class/net/eth{0,2,3,6}/queues/tx-*/xps_cpus; do
           echo 0 > $xps_cpus
        done

        # Disable LLDP on i40e
        # - by default, the i40e driver enables LLDP. But the SC EOBC switch
        #   cannot handle those LLDP packets.  We don't use LLDP in our system
        #   anyway.
        for f in /sys/kernel/debug/i40e/*/command; do
            echo "lldp stop" > $f
        done
    else
        # Make all packets to go to Rx Ring 0 by default.  Flex Filter in the igb
        # would filter out VLAN priority 7 packets to Rx Ring 1
        /usr/sbin/ethtool -X eth0 weight 1 0
        /usr/sbin/ethtool -X eth1 weight 1 0
        /usr/sbin/ethtool -X eth2 weight 1 0
        /usr/sbin/ethtool -X eth3 weight 1 0
        /usr/sbin/ethtool -X eth4 weight 1 0
        /usr/sbin/ethtool -X eth5 weight 1 0
        /usr/sbin/ethtool -X eth6 weight 1 0
        /usr/sbin/ethtool -X eth7 weight 1 0
    fi
}

sup_main() {

    local mgmt_intf=eth-mgmt
    local card_idx=$(get_cmdline_card_index)
    
    if [ "$card_idx" != 27065 ]; then
        install_psdev_sup
    else
        # turn off flow control
        /usr/sbin/ethtool -A eth0 rx off tx off
        /usr/sbin/ethtool -A eth1 rx off tx off autoneg off
        #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
        #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
        ifconfig eth0 down
        ip link set eth0 name ps-eobc
        ifconfig eth1 down
        ip link set eth1 name ps-inb

        # configure the interfaces
        /sbin/ifconfig ps-eobc down
        /sbin/ifconfig ps-eobc hw ether 00:00:00:00:$MY_MOD_ID_HEX:01 mtu $VEOBC_MTU
        /sbin/ifconfig ps-eobc up
        /sbin/ifconfig ps-inb down
        /sbin/ifconfig ps-inb hw ether 00:00:00:01:$MY_MOD_ID_HEX:01
        /sbin/ifconfig ps-inb up
        /sbin/ifconfig ps-inb mtu $INBAND_MTU
    fi
    sanitize_eth $mgmt_intf

    # sanitize eth-ptp on the Precisa SyncE RP
    if [ "$card_idx" == 27024 ] || 
       [ "$card_idx" == 27059 ]; then
        sanitize_eth eth-ptp
    fi

    # set the eobc and epc descriptors to 4K.
    configure_igb_rings eth2 4096
    configure_igb_rings eth3 4096
    configure_igb_rings eth0 4096
    configure_igb_rings eth6 4096

    setup_dhcpd_conf

    if [ "$card_idx" == 27065 ]; then
        pnic_list="ps-eobc\nps-inb\n"
    else
        pnic_list="eth6\neth0\neth3\neth2\n"
    fi

    if [[ ! -z ${pnic_list} ]]; then
             printf ${pnic_list} > /etc/init.d/pd_pnic_list.txt
    fi
}

setup_lc_eobc() {

    # turn off flow control
    /usr/sbin/ethtool -A eth0 rx off tx off

    #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
    #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
    /sbin/ifconfig eth0 down hw ether 00:00:00:00:$MY_MOD_ID_HEX:02 mtu $VEOBC_MTU
    /sbin/ifconfig eth0 up
}

wait_for_netdev_up() {

    local netdev=$1
    local retries=6
    local dev_state

    for i in `seq 1 $retries`;
    do
        dev_state=$(cat /sys/class/net/$netdev/operstate)
        if [ "$dev_state" == "up" ]; then
            break
        fi
        sleep 1
    done
    if [ "$dev_state" == "down" ]; then
        echo "$netdev is down."
    else
        echo "$netdev is up."
    fi
}

setup_lc_inband() {
    local card_idx=$(get_cmdline_card_index)

    if [ "$card_idx" -ne 27000 ] && 
       [ "$card_idx" -ne 27023 ] &&
       [ "$card_idx" -ne 27034 ] &&
       [ "$card_idx" -ne 27035 ] &&
       [ "$card_idx" -ne 27044 ] &&
       [ "$card_idx" -ne 27050 ] &&
       [ "$card_idx" -ne 27046 ] &&
       [ "$card_idx" -ne 27061 ] &&
       [ "$card_idx" -ne 27062 ] &&
       [ "$card_idx" -ne 27063 ] &&
       [ "$card_idx" -ne 27060 ] &&
       [ "$card_idx" -ne 27064 ] &&
       [ "$card_idx" -ne 27066 ] &&
       [ "$card_idx" -ne 27067 ] &&
       [ "$card_idx" -ne 27068 ] &&
       [ "$card_idx" -ne 27055 ]; then

        # turn off flow control
        /usr/sbin/ethtool -A eth1 rx off tx off autoneg off
        /usr/sbin/ethtool -A eth2 rx off tx off autoneg off
        /usr/sbin/ethtool -A eth3 rx off tx off autoneg off
        sanitize_eth eth1
        sanitize_eth eth2
        sanitize_eth eth3

        /sbin/ifconfig eth1 mtu $INBAND_MTU up
        /sbin/ifconfig eth2 mtu $INBAND_MTU up
        /sbin/ifconfig eth3 mtu $INBAND_MTU up

        /sbin/modprobe bonding mode=balance-xor xmit-hash-policy=layer3+4

        #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
        #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
        /sbin/ifconfig bond0 down hw ether 00:00:00:01:$MY_MOD_ID_HEX:02
        /sbin/ifconfig bond0 mtu $INBAND_MTU
        /sbin/ifconfig bond0 up

        wait_for_netdev_up eth1
        wait_for_netdev_up eth2
        wait_for_netdev_up eth3

        # Wait for slaves to be up before adding them to the bond interface
        ifenslave bond0 eth1 eth2 eth3

    else

        # turn off flow control
        /usr/sbin/ethtool -A eth1 rx off tx off autoneg off

        #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
        #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
        /sbin/ifconfig eth1 down hw ether 00:00:00:01:$MY_MOD_ID_HEX:02
        /sbin/ifconfig eth1 mtu $INBAND_MTU
        /sbin/ifconfig eth1 up
    fi
}


lc_main() {
    setup_lc_eobc
    setup_lc_inband

    pnic_list="ps-eobc\nps-inb\n"
    if [[ ! -z ${pnic_list} ]]; then
        printf ${pnic_list} > /etc/init.d/pd_pnic_list.txt
    fi

}

setup_fc_eobc() {

    echo "Setting up FC eobc:"

    #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
    #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
    /sbin/ifconfig eobc down hw ether 00:00:00:00:$MY_MOD_ID_HEX:3

    /sbin/ifconfig eobc mtu $VEOBC_MTU up
    /sbin/ifconfig lo netmask 255.255.0.0

}

setup_hw_eobc() {

    echo "Setting up hw eobc:"

    #MAC ADDRESS: 00:00:00:<eobc:0, epc:1>:<slot-id+1>:<card-type>
    #card-type: SUP = 1, LC = 2, FC = 3, SC = 4
    /sbin/ifconfig $1 down hw ether 00:00:00:00:$MY_MOD_ID_HEX:3

    # setup the rxq size to 4096
    echo 0 0 4096 > /sys/devices/platform/neta/gbe/rxq_size
    # setup the txq size
    echo 0 0 0 1024 > /sys/devices/platform/neta/gbe/txq_size

    # turn off flow control
    /usr/sbin/ethtool -A $1 rx off tx off

    /sbin/ifconfig $1 mtu $VEOBC_MTU up
    /sbin/ifconfig lo netmask 255.255.0.0

}

fc_main() {

    # Rename eth0 and eth1 to what klm_eobc_psdev expects
    echo "Renaming eth0 and eth1 ..." 
    /sbin/ifconfig eth0 down
    /sbin/ifconfig eth1 down

    /sbin/ip link set eth0 name hw-eobc1
    /sbin/ip link set eth1 name hw-eobc0

    echo "Installing klm_eobc_psdev ..."
    /sbin/insmod -f /lib/modules/klm_eobc_psdev.o

    setup_hw_eobc hw-eobc0
    setup_hw_eobc hw-eobc1
    setup_fc_eobc
}

BOARDTYPE=$(get_cctrl_board_type)

main() {

    boot_debug "Configuring network ..."

    if [ "$BOARDTYPE" == "LC" ]; then
        lc_main
    elif [ "$BOARDTYPE" == "FC" ]; then
        fc_main
    elif [ "$BOARDTYPE" == "RP" ]; then
        sup_main
    fi

	echo "Executing nwbridge_pd.sh"
    . /etc/init.d/nwbridge_pd.sh
}

case $1 in
    pre_init)
        if [ "$BOARDTYPE" == "RP" ]; then
            sup_pre_init
        fi
        ;;
    *)
        main
        ;;
esac

