#!/bin/bash
#
# Provide an instantaneous dump of as much of the network stack metrics
# as can be accessed from a command line.
#
# Used for in depth diagnosis of networking issues on-vehicle.

# NOTE: we do *not* wish to do the full strict mode as any of the ethtool
#       commands can fail with a "not supported" operation
#set -euo pipefail

kInterfaces=()

function main {
    print_boundary
    echo "FULL_NETWORK_DUMP"
    fill_interfaces
    dump_processes
    dump_loadavg
    dump_proc_net_dev
    dump_proc_net_tcp
    dump_proc_net_udp
    dump_softirqs
    dump_softnet_stat
    dump_interrupts

    do_per_interface "ethtool_queries"
}

function ethtool_queries {
    local interface=${1}
    dump_detailed_net_stats ${interface}
    dump_nic_features ${interface}
    dump_nic_recv_queues ${interface}
    dump_nic_queue_sizes ${interface}
    dump_nic_processing_weights ${interface}
    dump_nic_coalescing ${interface}
    dump_nic_ntuples ${interface}
}

function fill_interfaces {
    for iface in $(ifconfig | cut --delimiter ' ' --fields 1 | tr ':' '\n'| awk NF);  do
        if [[ "${iface}" != "lo" && ! "${iface}" =~ "docker" ]]; then
            kInterfaces+=("${iface}")
        fi
    done
}

function print_boundary {
    echo
    echo "******************************************"
    echo
}

function echo_and_do {
    print_boundary
    echo Output of "\"$*\"":
    $*
}

function do_per_interface {
    local method=${1}
    for iface in ${kInterfaces[@]}; do
        ${method} ${iface}
    done
}

function dump_processes {
    echo_and_do ps aux
}

function dump_loadavg {
    echo_and_do cat /proc/loadavg
}

function dump_proc_net_dev {
    echo_and_do cat /proc/net/dev
}

function dump_proc_net_tcp {
    echo_and_do cat /proc/net/tcp
}

function dump_proc_net_udp {
    echo_and_do cat /proc/net/udp
}

function dump_softirqs {
    echo_and_do cat /proc/softirqs
}

function dump_softnet_stat {
    echo_and_do cat /proc/net/softnet_stat
}

function dump_interrupts {
    echo_and_do cat /proc/interrupts
}

function dump_detailed_net_stats {
    local interface=${1}
    echo_and_do ethtool --statistics ${interface}
}

function dump_nic_features {
    local interface=${1}
    echo_and_do ethtool --show-features ${interface}
}

function dump_nic_recv_queues {
    local interface=${1}
    echo_and_do ethtool --show-channels ${interface}
}

function dump_nic_queue_sizes {
    local interface=${1}
    echo_and_do ethtool --show-ring ${interface}
}

function dump_nic_processing_weights {
    local interface=${1}
    echo_and_do ethtool --show-rxfh-indir ${interface}
}

function dump_nic_coalescing {
    local interface=${1}
    echo_and_do ethtool --show-coalesce ${interface}
}

function dump_nic_ntuples {
    local interface=${1}
    echo_and_do ethtool --show-ntuple ${interface} rx-flow-hash tcp4
    echo_and_do ethtool --show-ntuple ${interface} rx-flow-hash udp4
}

main
