diff --git a/scripts/net/roce/get_bw.sh b/scripts/net/roce/get_bw.sh index 1931a34ca2ebe7611d2350a44e234f5b3a6a12e5..f0c65f080826ea2054b14cc64b605910f678247b 100644 --- a/scripts/net/roce/get_bw.sh +++ b/scripts/net/roce/get_bw.sh @@ -1,12 +1,15 @@ #!/bin/bash bw_stats_field=("mac_tx_total_oct_num" "mac_rx_total_oct_num") -declare -A start_stats -declare -A end_stats +declare -Ag start_stats +declare -Ag end_stats +declare -g t1 +declare -g t2 init_start_stats(){ local device=$1 stats=$(ethtool -S "$device") + t1=$(date +%s%3N) for((i=0; i<${#bw_stats_field[@]};i++)); do start_stats[${bw_stats_field[i]}]=$(echo "$stats"|grep "${bw_stats_field[i]}"| awk '{print $2}') @@ -16,6 +19,7 @@ init_start_stats(){ bw_end_stats(){ local device=$1 stats=$(ethtool -S "$device") + t2=$(date +%s%3N) for((i=0;i<${#bw_stats_field[@]};i++)); do end_stats[${bw_stats_field[i]}]=$(echo "$stats"|grep "${bw_stats_field[i]}"| awk '{print $2}') @@ -39,29 +43,27 @@ get_bw_fmt(){ fmt_factor=$((1024*1024)) fi - bw_fmt=$(printf "%.2f" $(echo "scale=2;($cur_period_bytes-$pre_period_bytes)/$fmt_factor/$time_diff" | bc)) + bw=$(echo "scale=2;($cur_period_bytes-$pre_period_bytes)/$fmt_factor/$time_diff" | bc) + + if [ ! "$m" ];then + bw_fmt=$(printf "%6.2f Gb/s" "${bw}") + else + bw_fmt=$(printf "%8.2f Mib/s" "${bw}") + fi echo "$bw_fmt" } print_stats(){ device=$1 - time_interval=$2 + time_interval="$(printf "%.3f" "$(echo "scale=3;$2/1000" | bc)")" echo "$device roce" - if [ ! "$m" ];then - tx_print_fmt='tx_bw: %6.2f Gb/s\n' - rx_print_fmt='rx_bw: %6.2f Gb/s\n' - else - tx_print_fmt='tx_bw: %8.2f MiB/s\n' - rx_print_fmt='rx_bw: %8.2f MiB/s\n' - fi - for((i=0;i<${#bw_stats_field[@]};i++)); do bw_res=$(get_bw_fmt "${start_stats[${bw_stats_field[i]}]}" "${end_stats[${bw_stats_field[i]}]}" "$time_interval") if [ $i -eq 0 ];then - printf "$tx_print_fmt" ${bw_res} + printf "tx_bw: %s\n" "${bw_res}" else - printf "$rx_print_fmt" ${bw_res} + printf "rx_bw: %s\n" "${bw_res}" fi done } @@ -70,12 +72,10 @@ get_stats_info(){ device=$1 time_limit=$2 init_start_stats "$device" - t1=$(date +%s) while true;do sleep "$time_limit" bw_end_stats "$device" - t2=$(date +%s) duration=$((t2-t1)) print_stats "$device" "$duration" t1=$t2 diff --git a/scripts/net/roce/get_devinfo.sh b/scripts/net/roce/get_devinfo.sh new file mode 100755 index 0000000000000000000000000000000000000000..d26372df05943d75bbc449bea2ce1edd38170ca4 --- /dev/null +++ b/scripts/net/roce/get_devinfo.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +INPUT_NAME=$1 +# the column for data +data_col=2 +tempfile='' + +#The top 1K is not used for roce +BASE_OFFSET=$((16#400)) +#The offset between various PFs in the roce general configuration +PF_OFFSET=$((16#48)) + +check_whether_hns3() { + netdev=$1 + ethtool -i "$netdev" |grep hns3 &> /dev/null + return $? +} + +get_bdf() { + name=$1 + # support BDF + BDF=$(lspci -s "$name" -nD 2>/dev/null | awk '{print $1}' 2>/dev/null) + if ethname=$(ls /sys/bus/pci/devices/"$BDF"/net/ 2>/dev/null); then + echo "$BDF" + check_whether_hns3 "$ethname" + return $? + fi + + ethname="$name" + # support rdma dev name + if rdma_ret=$(rdma link show "$name/1" 2>/dev/null); then + ethname=$(echo "$rdma_ret"|awk '{print $NF}') + fi + + # support net devname + # get BDF from net devname + BDF=$(ethtool -i "$ethname" |grep "bus-info" | awk '{print $2}') + echo "$BDF" + check_whether_hns3 "$ethname" + return $? +} + +get_pf_num() { + echo "$1" |awk -F . '{printf $NF}' +} + +# The current implementation logic performance is not good, +# it has to read an 8K file repeatedly. However, this tool +# has no performance requirements, so it can be implemented +# with the current simple solution. +get_data() { + offset=$1 + bdf=$2 + #read the ncl + while read -r line; do + #get offset and data + offset_hex=$(echo "$line" | cut -d '|' -f 1) + data=$(echo "$line" | cut -d '|' -f $data_col) + # get the data + if [[ "${offset_hex// /}" == "$offset" ]]; then + echo "$data" + return 0 + fi + done < "$tempfile" +} + +get_cap_flag() { + CAPFLAG_OFFSET=$((16#150)) + EXTCAP_OFFSET=$((16#16c)) + bdf=$1 + + pf_num=$(get_pf_num "$bdf") + pf_offset=$((PF_OFFSET * pf_num)) + + offset=$((BASE_OFFSET + CAPFLAG_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" $offset) + base_cap=$(get_data "$offset" "$bdf") + base_cap=$((base_cap >> 20)) + + offset=$((EXTCAP_OFFSET + BASE_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" "$offset") + ext_cap=$(get_data "$offset" "$bdf") + ext_cap=$((ext_cap >> 16)) + ext_cap=$((ext_cap << 12)) + + cap=$(printf "0x%x" $((ext_cap | base_cap))) + echo "$bdf capflags: $cap" +} + +get_default_congest_type() { + DEF_CONG_OFFSET=$((16#174)) + bdf=$1 + + pf_num=$(get_pf_num "$bdf") + pf_offset=$((PF_OFFSET * pf_num)) + + offset=$((BASE_OFFSET + DEF_CONG_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" "$offset") + def_cong=$(get_data "$offset" "$bdf") + def_cong=$((def_cong >> 26)) + + echo "$bdf defalut congest: $def_cong" +} + +get_eq_info() { + MAX_CEQ_OFFSET=$((16#170)) + MAX_AEQ_OFFSET=$((16#174)) + bdf=$1 + + pf_num=$(get_pf_num "$bdf") + pf_offset=$((PF_OFFSET * pf_num)) + + offset=$((BASE_OFFSET + MAX_CEQ_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" "$offset") + max_ceq_info=$(get_data "$offset" "$bdf") + max_ceq=$((max_ceq_info >> 22)) + max_ceq_depth=$((max_ceq_info & 0x3fffff)) + max_ceq_depth=$(printf "max_ceq_depth: 0x%x" "$max_ceq_depth") + + offset=$((BASE_OFFSET + MAX_AEQ_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" "$offset") + max_aeq_info=$(get_data "$offset" "$bdf") + max_aeq_depth=$((max_aeq_info & 0x3fffff)) + max_aeq_depth=$(printf "max_aeq_depth: 0x%x" "$max_aeq_depth") + + echo "$bdf max_ceq: $max_ceq; $max_ceq_depth; $max_aeq_depth" +} + +get_qp_hopnum() { + QP_HOPNUM_OFFSET=$((16#168)) + bdf=$1 + + pf_num=$(get_pf_num "$bdf") + pf_offset=$((PF_OFFSET * pf_num)) + + offset=$((BASE_OFFSET + QP_HOPNUM_OFFSET)) + offset=$((pf_offset + offset)) + offset=$(printf "0x%04x" "$offset") + qp_hopnum=$(get_data "$offset" "$bdf") + sq_hopnum=$((qp_hopnum >> 24)) + sq_hopnum=$((sq_hopnum & 0x3)) + sge_hopnum=$((qp_hopnum >> 22)) + sge_hopnum=$((sge_hopnum & 0x3)) + rq_hopnum=$((qp_hopnum >> 20)) + rq_hopnum=$((rq_hopnum & 0x3)) + + echo "$bdf sq_hopnum: $sq_hopnum; sge_hopnum: $sge_hopnum; rq_hopnum: $rq_hopnum" +} + +help_info=" +Usage: $0 [OPTIONS] + +Get device info from nclconfig, Only support hns. + +Options: + -h, --help show this info + -v, --version version info + dev, device name, support netdev name, rdmadev name and BDF +" + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "$help_info" + exit 0 + ;; + -v|--version) + echo "Version 1.0" + exit 0 + ;; + *) + if ! DEV=$(get_bdf "$INPUT_NAME"); then + echo "$help_info" + exit 1 + fi + tempfile=$(mktemp) + # Save NCL in a tempfile to avoid accessing the IMP multiple times + cat /sys/kernel/debug/hns3/"$DEV"/ncl_config > "$tempfile" + get_cap_flag "$DEV" + get_default_congest_type "$DEV" + get_qp_hopnum "$DEV" + get_eq_info "$DEV" + rm "$tempfile" + ;; + esac + shift +done diff --git a/scripts/net/roce/get_hw_stats.sh b/scripts/net/roce/get_hw_stats.sh new file mode 100755 index 0000000000000000000000000000000000000000..46ad0d21297df56371f1b998ee301e2d1eacf740 --- /dev/null +++ b/scripts/net/roce/get_hw_stats.sh @@ -0,0 +1,226 @@ +#!/bin/bash +rdma_tx_stats=("tx_pkt" "tx_err_pkt" "tx_cnp_pkt" "tx_rc_pkt" "tx_ud_pkt" "tx_xrc_pkt") +rdma_rx_stats=("rx_pkt" "rx_err_pkt" "rx_cnp_pkt" "rx_rc_pkt" "rx_ud_pkt" "rx_xrc_pkt") +rdma_cq_stats=("cq_cqe" "cq_poe" "cq_notify") +rdma_trp_stats=("get_mpt_err_pkt" "get_irrl_err_pkt") +ETH_STATS=false +eth_tx_stats=("mac_tx_total_pkt" "mac_tx_good_pkt" "mac_tx_bad_pkt" "mac_tx_err_all_pkt") +eth_rx_stats=("mac_rx_total_pkt" "mac_rx_good_pkt" "mac_rx_bad_pkt" "mac_rx_fcs_err_pkt") + +declare -A start_stat +declare -A end_stat + +invalid_netdev() { + local netdev=$1 + echo "$netdev" + ethtool -i "$netdev" |grep hns3 &> /dev/null + return $? +} + +get_dev_name() { + name=$1 + ethname="" + # support rdma dev name + if rdma_ret=$(rdma link show "$name/1" 2>/dev/null); then + ethname=$(echo "$rdma_ret"|awk '{print $NF}') + invalid_netdev "$ethname" + return $? + fi + # support BDF + BDF=$(lspci -s "$name" -nD 2>/dev/null | awk '{print $1}' 2>/dev/null) + if ethname=$(ls /sys/bus/pci/devices/"$BDF"/net/ 2>/dev/null); then + invalid_netdev "$ethname" + return $? + fi + # support net devname + invalid_netdev "$name" + return $? +} + +get_rdma_name() { + ethname=$1 + rdma_name=$(ls /sys/class/net/"$ethname"/device/infiniband/ 2>/dev/null) + echo "$rdma_name" +} + +print_rdma_stats() { + for ((i=0; i<${#rdma_rx_stats[@]}; i++)); do + rx_ret=$(( ${end_stat[${rdma_rx_stats[i]}]} - ${start_stat[${rdma_rx_stats[i]}]} )) + tx_ret=$(( ${end_stat[${rdma_tx_stats[i]}]} - ${start_stat[${rdma_tx_stats[i]}]} )) + if [ $rx_ret -ne 0 ] || [ $tx_ret -ne 0 ];then + echo "${rdma_rx_stats[i]}: $rx_ret, ${rdma_tx_stats[i]}: $tx_ret" + fi + done + + cq_str="" + for ((i=0; i<${#rdma_cq_stats[@]}; i++)); do + ret=$(( ${end_stat[${rdma_cq_stats[i]}]} - ${start_stat[${rdma_cq_stats[i]}]} )) + if [ $ret -ne 0 ];then + cq_str="${rdma_cq_stats[i]}: $ret;"" ""${cq_str}" + fi + done + if [ -n "${cq_str}" ]; then + echo "${cq_str}" + fi + + trp_str="" + for ((i=0; i<${#rdma_trp_stats[@]}; i++)); do + ret=$(( ${end_stat[${rdma_trp_stats[i]}]} - ${start_stat[${rdma_trp_stats[i]}]} )) + if [ $ret -ne 0 ];then + cq_str="${rdma_trp_stats[i]}: $ret;"" ""${trp_str}" + fi + done + if [ -n "${trp_str}" ]; then + echo "${trp_str}" + fi +} + +fresh_rdma_start_stats() { + for ((i=0; i<${#rdma_rx_stats[@]}; i++)); do + start_stat[${rdma_tx_stats[i]}]=${end_stat[${rdma_tx_stats[i]}]} + start_stat[${rdma_rx_stats[i]}]=${end_stat[${rdma_rx_stats[i]}]} + done + + for ((i=0; i<${#rdma_cq_stats[@]}; i++)); do + start_stat[${rdma_cq_stats[i]}]=${end_stat[${rdma_cq_stats[i]}]} + done + + for ((i=0; i<${#rdma_trp_stats[@]}; i++)); do + start_stat[${rdma_cq_stats[i]}]=${end_stat[${rdma_cq_stats[i]}]} + done +} + +init_rdma_stats() { + local device=$1 + stats=$(rdma stat show link "$device" -p) + for ((i=0; i<${#rdma_rx_stats[@]}; i++)); do + start_stat[${rdma_rx_stats[i]}]=$(echo "$stats"|grep "${rdma_rx_stats[i]}"| awk '{print $2}') + start_stat[${rdma_tx_stats[i]}]=$(echo "$stats"|grep "${rdma_tx_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#rdma_cq_stats[@]}; i++)); do + start_stat[${rdma_cq_stats[i]}]=$(echo "$stats"|grep "${rdma_cq_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#rdma_trp_stats[@]}; i++)); do + start_stat[${rdma_trp_stats[i]}]=$(echo "$stats"|grep "${rdma_trp_stats[i]}"| awk '{print $2}') + done +} + +fresh_rdma_end_stats() { + stats=$1 + for ((i=0; i<${#rdma_rx_stats[@]}; i++)); do + end_stat[${rdma_rx_stats[i]}]=$(echo "$stats"|grep "${rdma_rx_stats[i]}"| awk '{print $2}') + end_stat[${rdma_tx_stats[i]}]=$(echo "$stats"|grep "${rdma_tx_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#rdma_cq_stats[@]}; i++)); do + end_stat[${rdma_cq_stats[i]}]=$(echo "$stats"|grep "${rdma_cq_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#rdma_trp_stats[@]}; i++)); do + end_stat[${rdma_trp_stats[i]}]=$(echo "$stats"|grep "${rdma_trp_stats[i]}"| awk '{print $2}') + done +} + +init_eth_stats() { + local device=$1 + stats=$(ethtool -S "$device") + for ((i=0; i<${#eth_rx_stats[@]}; i++)); do + start_stat[${eth_rx_stats[i]}]=$(echo "$stats"|grep "${eth_rx_stats[i]}"| awk '{print $2}') + start_stat[${eth_tx_stats[i]}]=$(echo "$stats"|grep "${eth_tx_stats[i]}"| awk '{print $2}') + done +} + +fresh_eth_end_stats() { + local stats=$1 + for ((i=0; i<${#eth_rx_stats[@]}; i++)); do + end_stat[${eth_rx_stats[i]}]=$(echo "$stats"|grep "${eth_rx_stats[i]}"| awk '{print $2}') + end_stat[${eth_tx_stats[i]}]=$(echo "$stats"|grep "${eth_tx_stats[i]}"| awk '{print $2}') + done +} + +fresh_eth_start_stats() { + for ((i=0; i<${#eth_rx_stats[@]}; i++)); do + start_stat[${eth_tx_stats[i]}]=${end_stat[${eth_tx_stats[i]}]} + start_stat[${eth_rx_stats[i]}]=${end_stat[${eth_rx_stats[i]}]} + done +} + +print_eth_stats() { + for ((i=0; i<${#eth_rx_stats[@]}; i++)); do + rx_ret=$(( ${end_stat[${eth_rx_stats[i]}]} - ${start_stat[${eth_rx_stats[i]}]} )) + tx_ret=$(( ${end_stat[${eth_tx_stats[i]}]} - ${start_stat[${eth_tx_stats[i]}]} )) + if [ $rx_ret -ne 0 ] || [ $tx_ret -ne 0 ];then + echo "${eth_rx_stats[i]}: $rx_ret, ${eth_tx_stats[i]}: $tx_ret" + fi + done +} + +get_stats() { + local device="" + local eth_dev="" + + if [ $# -gt 1 ]; then + eth_dev=$2 + init_eth_stats "$eth_dev" + fi + device=$1 + init_rdma_stats "${device}" + while true; do + sleep 1 + stats=$(rdma stat show link "$device" -p) + if [ -n "${eth_dev}" ]; then + eth_stats=$(ethtool -S "${eth_dev}") + fresh_eth_end_stats "${eth_stats}" + print_eth_stats + fresh_eth_start_stats + fi + fresh_rdma_end_stats "${stats}" + print_rdma_stats + fresh_rdma_start_stats + echo "************************************************" + done +} + +help_info=" +Usage: $0 [Options] dev + +Get RDMA related HW stats per second. Only support hns. + +This script outputs RDMA packet statistics by default. + +Args: + dev, device name, support netdev name, rdmadev name and BDF +Options: + -h, --help show this info + -v, --version version info + -a, --all add Mac stat +" + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "$help_info" + exit 0 + ;; + -v|--version) + echo "Version 1.0" + exit 0 + ;; + -a|--all) + ETH_STATS=true + ;; + *) + INPUT_NAME=$1 + if ! ETHDEV=$(get_dev_name "$INPUT_NAME"); then + echo "$help_info" + exit 1 + fi + RDMADEV=$(get_rdma_name "$ETHDEV") + + if ${ETH_STATS}; then + get_stats "$RDMADEV" "$ETHDEV" + else + get_stats "$RDMADEV" + fi + ;; + esac + shift +done diff --git a/scripts/net/roce/get_ncl.sh b/scripts/net/roce/get_ncl.sh new file mode 100644 index 0000000000000000000000000000000000000000..c34b29467be4975f115e51fb900b7e8da9d8c16b --- /dev/null +++ b/scripts/net/roce/get_ncl.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +# The debugfs of the driver can be used to dump the binary data of the NCL file +# used by the current network port (16K binary data). The first 1k (0-0x3FF) +# is the NCL header, indicating the NCL configuration information of the current +# board.The data is used to decompress ncl_config during imp initialization. + +# The data dumped by using the debugfs file is a single NCL_CONFIG file after +# decompression. The actual size of a single valid NCL is 8K. Therefore, we can directly +# view 8K data between 0x400 and 0x2400. + +# the column for data +DATA_COL=2 + +# The top 1K and last 7K is not used for nic/roce +BASE_OFFSET="0x0400" +HIGH_OFFSET="0x2400" + +check_whether_hns3() { + netdev=$1 + ethtool -i "$netdev" |grep hns3 &> /dev/null + return $? +} + +get_bdf() { + name=$1 + # support BDF + BDF=$(lspci -s "$name" -nD 2>/dev/null | awk '{print $1}' 2>/dev/null) + if ethname=$(ls /sys/bus/pci/devices/"$BDF"/net/ 2>/dev/null); then + echo "$BDF" + check_whether_hns3 "$ethname" + return $? + fi + + ethname="$name" + # support rdma dev name + if [ -e /sys/class/infiniband/"$name" ]; then + ethname=$(ls /sys/class/infiniband/"$name"/device/net/ 2>/dev/null) + fi + + # support net devname + # get BDF from net devname + BDF=$(ethtool -i "$ethname" |grep "bus-info" | awk '{print $2}') + echo "$BDF" + check_whether_hns3 "$ethname" + return $? +} + +big_endian_2_little_endian() { + # Output the characters corresponding to each byte in little-endian order + data=$1 + byte1=$((data & 0xff)) + byte2=$((data >> 8 & 0xff)) + byte3=$((data >> 16 & 0xff)) + byte4=$((data >> 24 & 0xff)) + echo -ne "$(printf '\\x%02x\\x%02x\\x%02x\\x%02x' $byte1 $byte2 $byte3 $byte4)" +} + +generate_ncl() { + tempfile=$(mktemp) + rawfile=/sys/kernel/debug/hns3/"$BDF"/ncl_config + # Save NCL in a tempfile, Only 8K data that is useful in the middle is retained + BASE_OFFSET_LINE=$(grep -nr "${BASE_OFFSET} |" "$rawfile" | awk '{print $1}' | cut -d ':' -f 1) + HIGH_OFFSET_LINE=$(grep -nr "${HIGH_OFFSET} |" "$rawfile" | awk '{print $1}' | cut -d ':' -f 1) + awk -v base="$BASE_OFFSET_LINE" -v high="$HIGH_OFFSET_LINE" 'NR>=base && NR "$tempfile" + #read tempfile + while read -r line; do + data=$(echo "$line" | cut -d '|' -f $DATA_COL) + big_endian_2_little_endian "${data// /}" + done < "$tempfile" + + rm "$tempfile" +} + +help_info=" +Usage: $0 [OPTIONS] + +Get ncl_config, Only support hns. +please use ncl_config_opt.xlsm to parse ncl_config +Use the NCL0 tab to read a single NCL + +Options: + -h, --help show this info + -v, --version version info + -d, --device device name, support netdev name, rdmadev name and BDF +" + +VERSION="1.0" +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "$help_info" + exit 0 + ;; + -v|--version) + echo "Version $VERSION" + exit 0 + ;; + -d|--device) + dev=$2 + shift + ;; + *) + echo "Error: Invalid option: $1" + echo "$help_info" + exit 0 + ;; + esac + shift +done + +if [ ! "$dev" ]; then + echo "Error: device name is not set" + echo "$help_info" + exit 0 +fi + +if ! BDF=$(get_bdf "$dev"); then + echo "$help_info" + exit 0 +fi + +generate_ncl diff --git a/scripts/net/roce/get_pause.sh b/scripts/net/roce/get_pause.sh new file mode 100644 index 0000000000000000000000000000000000000000..56ff788cbb8b621bbb6bc33a5f3698626c3ebdd3 --- /dev/null +++ b/scripts/net/roce/get_pause.sh @@ -0,0 +1,148 @@ +#!/bin/bash +INPUT_NAME=$1 + +tx_pause_stats=("tx_mac_pause" "tx_pause_xoff_time") +rx_pause_stats=("rx_mac_pause" "rx_pause_xoff_time") +declare -a rx_pfc_stats +declare -a tx_pfc_stats +declare -A start_stats +declare -A end_stats + +init_pfc_array() { + tx_pfc_stats+=("tx_pfc_pkt") + rx_pfc_stats+=("rx_pfc_pkt") + for((i=0; i<8; i++)); do + rx_pfc_stats+=("rx_pfc_pri${i}_pkt") + rx_pfc_stats+=("rx_pfc_pri${i}_xoff_time") + tx_pfc_stats+=("tx_pfc_pri${i}_pkt") + tx_pfc_stats+=("tx_pfc_pri${i}_xoff_time") + done +} + +invalid_netdev() { + netdev=$1 + echo "$netdev" + ethtool -i "$netdev" |grep hns3 &> /dev/null + return $? +} + +get_dev_name() { + name=$1 + ethname="" + # support rdma dev name + if rdma_ret=$(rdma link show "$name/1" 2>/dev/null); then + ethname=$(echo "$rdma_ret"|awk '{print $NF}') + invalid_netdev "$ethname" + return $? + fi + # support BDF + BDF=$(lspci -s "$name" -nD 2>/dev/null | awk '{print $1}' 2>/dev/null) + if ethname=$(ls /sys/bus/pci/devices/"$BDF"/net/ 2>/dev/null); then + invalid_netdev "$ethname" + return $? + fi + # support net devname + invalid_netdev "$name" + return $? +} + +init_start_stats() { + local device=$1 + + stats=$(ethtool -S "$device") + for ((i=0; i<${#tx_pause_stats[@]}; i++)); do + start_stats[${tx_pause_stats[i]}]=$(echo "$stats"|grep "${tx_pause_stats[i]}"| awk '{print $2}') + start_stats[${rx_pause_stats[i]}]=$(echo "$stats"|grep "${rx_pause_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#tx_pfc_stats[@]}; i++)); do + start_stats[${tx_pfc_stats[i]}]=$(echo "$stats"|grep "${tx_pfc_stats[i]}"| awk '{print $2}') + start_stats[${rx_pfc_stats[i]}]=$(echo "$stats"|grep "${rx_pfc_stats[i]}"| awk '{print $2}') + done +} + +fresh_end_stats() { + local device=$1 + + stats=$(ethtool -S "$device") + for ((i=0; i<${#tx_pause_stats[@]}; i++)); do + end_stats[${tx_pause_stats[i]}]=$(echo "$stats"|grep "${tx_pause_stats[i]}"| awk '{print $2}') + end_stats[${rx_pause_stats[i]}]=$(echo "$stats"|grep "${rx_pause_stats[i]}"| awk '{print $2}') + done + for ((i=0; i<${#tx_pfc_stats[@]}; i++)); do + end_stats[${tx_pfc_stats[i]}]=$(echo "$stats"|grep "${tx_pfc_stats[i]}"| awk '{print $2}') + end_stats[${rx_pfc_stats[i]}]=$(echo "$stats"|grep "${rx_pfc_stats[i]}"| awk '{print $2}') + done +} + +fresh_start_stats() { + for ((i=0; i<${#tx_pause_stats[@]}; i++)); do + start_stats[${tx_pause_stats[i]}]=${end_stats[${tx_pause_stats[i]}]} + start_stats[${rx_pause_stats[i]}]=${end_stats[${rx_pause_stats[i]}]} + done + for ((i=0; i<${#tx_pfc_stats[@]}; i++)); do + start_stats[${tx_pfc_stats[i]}]=${end_stats[${tx_pfc_stats[i]}]} + start_stats[${rx_pfc_stats[i]}]=${end_stats[${rx_pfc_stats[i]}]} + done +} + +print_stats() { + for ((i=0; i<${#tx_pause_stats[@]}; i++)); do + rx_ret=$(( ${end_stats[${rx_pause_stats[i]}]} - ${start_stats[${rx_pause_stats[i]}]} )) + tx_ret=$(( ${end_stats[${tx_pause_stats[i]}]} - ${start_stats[${tx_pause_stats[i]}]} )) + if [ $rx_ret -ne 0 ] || [ $tx_ret -ne 0 ];then + echo "${rx_pause_stats[i]}: $rx_ret, ${tx_pause_stats[i]}: $tx_ret" + fi + done + for ((i=0; i<${#tx_pfc_stats[@]}; i++)); do + rx_ret=$(( ${end_stats[${rx_pfc_stats[i]}]} - ${start_stats[${rx_pfc_stats[i]}]} )) + tx_ret=$(( ${end_stats[${tx_pfc_stats[i]}]} - ${start_stats[${tx_pfc_stats[i]}]} )) + if [ $rx_ret -ne 0 ] || [ $tx_ret -ne 0 ];then + echo "${rx_pfc_stats[i]}: $rx_ret, ${tx_pfc_stats[i]}: $tx_ret" + fi + done + echo "**************************************************" +} + +get_period_pause_info() { + device=$1 + init_pfc_array + init_start_stats "$device" + while true; do + sleep 1 + fresh_end_stats "$device" + print_stats + fresh_start_stats + done +} + +help_info=" +Usage: $0 [OPTIONS] + +Get pause frame stats per second. Only support hns. + +Options: + -h, --help show this info + -v, --version version info + dev, device name, support netdev name, rdmadev name and BDF +" + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "$help_info" + exit 0 + ;; + -v|--version) + echo "Version 1.0" + exit 0 + ;; + *) + if ! DEV=$(get_dev_name "$INPUT_NAME"); then + echo "$help_info" + exit 1 + fi + get_period_pause_info "$DEV" + ;; + esac + shift +done