From 9971b901d393edd80eb78b270596f4cb4dd405bc Mon Sep 17 00:00:00 2001 From: Chengchang Tang Date: Mon, 23 Jun 2025 12:00:50 +0800 Subject: [PATCH 1/3] hikptool: Add get_devinfo to parse the ncl_config for hns roce This tool will get the ncl from the hns3 debugfs, then parse the variabes that have a greater impact on RoCE and print them out. Example: $ ./get_devinfo.sh eth0 0000:35:00.0 capflags: 0x70977f 0000:35:00.0 defalut congest: 0 0000:35:00.0 sq_hopnum: 2; sge_hopnum: 2; rq_hopnum: 2 See help for more details. Signed-off-by: Chengchang Tang --- scripts/net/roce/get_devinfo.sh | 192 ++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100755 scripts/net/roce/get_devinfo.sh diff --git a/scripts/net/roce/get_devinfo.sh b/scripts/net/roce/get_devinfo.sh new file mode 100755 index 0000000..d26372d --- /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 -- Gitee From aef4cef4879342c715ac09b06fb722c36dd71de8 Mon Sep 17 00:00:00 2001 From: Chengchang Tang Date: Mon, 23 Jun 2025 12:02:46 +0800 Subject: [PATCH 2/3] hikptool: add get_hw_stats to get the real-tiem packet rate This script support getting the packet statitstics for hns RoCEE per second. This output is not exactly equal to the actual packet rate because its time interval is relatively rough. Example: $ ./get_hw_stats.sh eth1 -a ************************************************ rx_pkt: 11931020, tx_pkt: 11931027 rx_rc_pkt: 11931005, tx_rc_pkt: 11931030 cq_cqe: 367100; ************************************************ See help for more details. Signed-off-by: Chengchang Tang --- scripts/net/roce/get_hw_stats.sh | 226 +++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100755 scripts/net/roce/get_hw_stats.sh diff --git a/scripts/net/roce/get_hw_stats.sh b/scripts/net/roce/get_hw_stats.sh new file mode 100755 index 0000000..46ad0d2 --- /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 -- Gitee From bc2406a5833063c540e824310f737d77d378374a Mon Sep 17 00:00:00 2001 From: Junxian Huang Date: Thu, 10 Jul 2025 11:01:55 +0800 Subject: [PATCH 3/3] hikptool: Add two roce scripts Add two roce scripts. 1. get_ncl.sh dumps ncl_config in a format that can be parsed by NCL0 tab in ncl_config_opt.xlsm. Usage: sh get_ncl.sh -d hns_0 > hns_0_ncl 2. get_pause.sh shows the number of pause/pfc sent or received by a given device per second. Usage: sh get_pause.sh eth0 Signed-off-by: Junxian Huang --- scripts/net/roce/get_bw.sh | 32 ++++---- scripts/net/roce/get_ncl.sh | 123 ++++++++++++++++++++++++++++ scripts/net/roce/get_pause.sh | 148 ++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 16 deletions(-) create mode 100644 scripts/net/roce/get_ncl.sh create mode 100644 scripts/net/roce/get_pause.sh diff --git a/scripts/net/roce/get_bw.sh b/scripts/net/roce/get_bw.sh index 1931a34..f0c65f0 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_ncl.sh b/scripts/net/roce/get_ncl.sh new file mode 100644 index 0000000..c34b294 --- /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 0000000..56ff788 --- /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 -- Gitee