#!/bin/bash # Parse command line options using getopt options=$(getopt -o f:l:o:t:h:sdg --long first:,last:,only:,time:,hops:,sequential,debug,help -- "$@") eval set -- "$options" source /home/apu/testbed_files/apu-tb-opt/scripts/mesh/node_addresses.sh # Define variables user="root" # Replace "username" with your SSH username # host1="apu00" # Replace "host1.example.com" with the hostname or IP address of the first Linux computer # host2="apu01" # Replace "host2.example.com" with the hostname or IP address of the second Linux computer # mesh0_ip="192.168.10.10" # mesh1_ip="192.168.20.10" interface1="mesh0" # Replace "eth0" with the specific interface you want to use for the measurement interface2="mesh1" # Replace "eth0" with the specific interface you want to use for the measurement measurement_time=10 # Measurement time in seconds sequential_test=false debug=0 start_node=0 stop_node=24 hops=1 server_start_time=4 # in seconds # delay=2 # in seconds skip_first_iperf_meas=6 # Function to display usage information function display_usage { echo "Usage: $0 [--first <[0..84]>] [--last <[0..84]>] [--only <[0..84]>] [--time <[0..84]>] [--hops <[1..4]>] [--sequential] [--help]" } # Function to display help information function display_help { display_usage echo echo "Options:" echo " --first (-f) Set the start node (0)" echo " --last (-l) Set the stop node (24)" echo " --only (-o) Only one node" echo " --time (-t) time per measurement in seconds (10)" echo " --hops (-h) Displays help" echo " --sequential (-s) perform the test on both interfaces sequentially" echo " --debug (-d) debug output" echo " --help (-g) help" } # argument parsing while true; do case "$1" in -f|--first) start_node="$2" shift 2 ;; -l|--last) stop_node="$2" shift 2 ;; -o|--only) start_node="$2" stop_node="$2" shift 2 ;; -t|--time) measurement_time="$2" shift 2 ;; -h|--hops) hops="$2" shift 2 ;; -s|--sequential) sequential_test=true shift ;; -d|--debug) debug=1 shift ;; -h|--help) display_help exit 0 ;; --) shift break ;; *) display_usage exit 1 ;; esac done csv_file="iperf_${hops}_hops.csv" # Remove existing CSV file rm -f "$csv_file" NODE_LIST=$(seq $start_node 1 $stop_node) find_value_for_key() { declare -n list=$1 #nameref for associateve array local search_key=$2 for key in "${!list[@]}"; do if [[ "$key" == "$search_key" ]]; then echo "${list[$key]}" return fi done echo "Unknown" } # Function to convert a node number to its grid coordinates get_coordinates() { local node=$1 echo "$((node / 5)) $((node % 5))" } # Function to calculate the Chebyshev distance between two nodes chebyshev_distance() { local x1=$1 local y1=$2 local x2=$3 local y2=$4 # Calculate absolute values of differences local dx=$((x1 - x2)) local dy=$((y1 - y2)) dx=${dx#-} # Remove negative sign to get absolute value dy=${dy#-} # Remove negative sign to get absolute value # Return the maximum of the two distances echo $((dx > dy ? dx : dy)) } # Function to calculate absolute value abs() { echo ${1#-} } # # Check if exactly one argument is provided and it is in the range 1 to 4 # if [[ $# -ne 1 || $1 -lt 1 || $1 -gt 4 ]]; then # echo "Usage: $0 " # exit 1 # fi iperf_measure() { local csv=$1 local user=$2 local host1=$3 local host2=$4 local start_server=$5 local debug=$6 local eth_host1_ip=$(find_value_for_key "eth0IP" "$host1") local eth_host2_ip=$(find_value_for_key "eth0IP" "$host2") local mesh0_ip=$(find_value_for_key "phy0IP" "$host1") local mesh1_ip=$(find_value_for_key "phy1IP" "$host1") local ping_count=5 local time_out_diff_to_meas_time=15 local time_out=$(( $measurement_time + $time_out_diff_to_meas_time )) local if1_check=0 local if2_check=0 # echo "$time_out" # pinging # average_time1=$(ssh $user@$host1 "ping -c $ping_count $mesh0_ip | awk -F'/' '/^rtt/ { print $5 }' 2>/dev/null &") # average_time2=$(ssh $user@$host1 "ping -c $ping_count $mesh1_ip | awk -F'/' '/^rtt/ { print $5 }' 2>/dev/null &") # pingpid=$! # wait $pingpid # echo "$average_time1 $average_time2" # # Kill iperf3 instances on both nodes # ssh $user@$host1 "pkill iperf3" # ssh $user@$host2 "pkill iperf3" echo "start measuring | server: $host1 | client: $host2 | time: $measurement_time" # echo "$user, $eth_host1_ip, $eth_host2_ip, $mesh0_ip, $mesh1_ip" # SSH connection and iperf3 measurement if [ $debug ]; then echo "Start server" fi if [ $start_server ]; then ssh $user@$host1 "iperf3 -s --bind $mesh0_ip > /dev/null 2>&1 &" # Start iperf3 server in daemon mode on host1 ssh $user@$host1 "iperf3 -s --bind $mesh1_ip > /dev/null 2>&1 &" # Start iperf3 server in daemon mode on host1 fi # Wait for a clean server start if [ $debug ]; then echo "Wait for server" fi sleep $server_start_time # Temporary output files output_file1=$(mktemp) output_file2=$(mktemp) # Start the iperf3 client instances if [ $debug ]; then echo "Start clients" fi if [[ $sequential_test == true ]]; then if [ $debug ]; then echo "sequential test" fi ssh $user@$host2 "iperf3 -c $mesh0_ip -t $measurement_time -O $skip_first_iperf_meas" > $output_file1 2>&1 & # Start iperf3 client on host2, specifying the interface and measurement time, and redirect stderr to stdout pid1=$! wait $pid1 ssh $user@$host2 "iperf3 -c $mesh1_ip -t $measurement_time -O $skip_first_iperf_meas" > $output_file2 2>&1 & # Start iperf3 client on host2, specifying the interface and measurement time, and redirect stderr to stdout pid2=$! wait $pid2 else if [ $debug ]; then echo "parallel test" fi ssh $user@$host2 "iperf3 -c $mesh0_ip -t $measurement_time" > $output_file1 2>&1 & # Start iperf3 client on host2, specifying the interface and measurement time, and redirect stderr to stdout pid1=$! ssh $user@$host2 "iperf3 -c $mesh1_ip -t $measurement_time" > $output_file2 2>&1 & # Start iperf3 client on host2, specifying the interface and measurement time, and redirect stderr to stdout pid2=$! # Wait for the measurement to complete # wait $pid1 # wait $pid2 # wait $measurement_time+1 # Wait for both processes to finish or timeout for ((i=0; i<$time_out; i++)); do # Check if first process is still running if ! kill -0 $pid1 2>/dev/null && [[ $if1_check -eq 0 ]]; then echo "Interface 1 completed before timeout." pid1= # Clear the PID1 to indicate it's done if1_check=1 fi # Check if second process is still running if ! kill -0 $pid2 2>/dev/null && [[ $if2_check -eq 0 ]]; then echo "Interface 2 completed before timeout." pid2= # Clear the PID2 to indicate it's done if2_check=1 fi # Break the loop if both processes are done if [[ -z $pid1 && -z $pid2 ]]; then break fi # Sleep for 1 second before checking again sleep 1 if [[ $i -eq $time_out-1 ]]; then # echo "check" if [[ -n $pid1 ]]; then echo "Timeout interface 1 -> stop!" fi if [[ -n $pid2 ]]; then echo "Timeout interface 2 -> stop!" fi fi done fi if [ $debug ]; then echo "Measurement done" fi # Save the output of the temp files into data structure to inspect local iperf_output1=$(cat $output_file1) local iperf_output2=$(cat $output_file2) if [ $debug ]; then echo "iperf output 1:" echo "$iperf_output1" echo "iperf output 2:" echo "$iperf_output2" fi # Extract throughput information local throughput_info1=$(echo "$iperf_output1" | grep -oP '\d+\.\d+(?=\s+Mbits/sec)') local throughput_info2=$(echo "$iperf_output2" | grep -oP '\d+\.\d+(?=\s+Mbits/sec)') # Extracting min, max, and average throughput local min_throughput1=$(echo "$throughput_info1" | sort -n | head -n 1) local max_throughput1=$(echo "$throughput_info1" | sort -n | tail -n 1) local avg_throughput1=$(echo "$throughput_info1" | awk '{sum += $1} END {print sum / NR}') local min_throughput2=$(echo "$throughput_info2" | sort -n | head -n 1) local max_throughput2=$(echo "$throughput_info2" | sort -n | tail -n 1) local avg_throughput2=$(echo "$throughput_info2" | awk '{sum += $1} END {print sum / NR}') if [ $debug ]; then # Display results echo "Min Throughput 1: $min_throughput1" echo "Max Throughput 1: $max_throughput1" echo "Average Throughput 1: $avg_throughput1 Mbps" echo "Min Throughput 2: $min_throughput2" echo "Max Throughput 2: $max_throughput2" echo "Average Throughput 2: $avg_throughput2 Mbps" fi # Write results to CSV file if [ ! -f "$csv" ]; then echo "Iperf3 Measurement (sequential = $sequential_test)" > $csv_file echo "Server,Client,$interface1 Min TP (Mbps),$interface2 Min TP (Mbps),$interface1 Max TP (Mbps),$interface2 Max TP (Mbps),$interface1 Avg TP (Mbps),$interface2 Avg TP (Mbps)" >> $csv_file fi echo "$host1,$host2,$min_throughput1,$min_throughput2,$max_throughput1,$max_throughput2,$avg_throughput1,$avg_throughput2" >> $csv_file echo "done measuring | server: $host1 | client: $host2 | tp_avg_if1: $avg_throughput1 | tp_avg_if2: $avg_throughput2" # Clean up temporary files rm -f $output_file1 $output_file2 # Kill iperf3 instances on both nodes ssh $user@$host1 "pkill iperf3" ssh $user@$host2 "pkill iperf3" } time_remaining=0 total=0 count=$(wc -w <<< "$NODE_LIST") # echo $(wc -w <<< "$NODE_LIST") # echo ${#NODE_LIST[@]} # calculating remaining time # for server in $NODE_LIST; do # if [[ $server -lt 10 ]];then # current=apu0$server # else # current=apu$server # fi # ((time_remaining+=$server_start_time)) # for client in ${neighbors[$current]}; do # ((time_remaining+=$delay+$measurement_time)) # done # done # for server in $NODE_LIST; do # echo "Remaining time: $((time_remaining / 60))m:$((time_remaining % 60))s" # if [[ $server -lt 10 ]];then # current=apu0$server # else # current=apu$server # fi # start_server=1 # for client in ${neighbors[$current]}; do # # echo "Server: $current | Client: $client | Time: $measurement_time" # # iperf_measure "$csv_file" "root" "$current" "$client" # iperf_measure "$csv_file" "root" "$current" "$client" "1" "$start_server" # last "1" for debug output # ((total+=1)) # sleep $delay # ((time_remaining-=$delay+$measurement_time)) # start_server=0 # done # # kill iperf server instances # ssh $user@$current "pkill iperf3" # done # Iterate over all pairs of nodes # in order to calculate the number of node # pairs to be measured pair_count_total=0 for start in {0..24}; do read x1 y1 <<< $(get_coordinates $start) for end in {0..24}; do if [[ $start -ne $end ]]; then read x2 y2 <<< $(get_coordinates $end) # Calculate Manhattan distance # distance=$(manhattan_distance $x1 $y1 $x2 $y2) distance=$(chebyshev_distance $x1 $y1 $x2 $y2) # If distance matches the given hops, print the pair if [[ $distance -eq $hops ]]; then ((pair_count_total+=1)) fi fi done done echo "Total pair count with chebyshev distance of $hops: $pair_count_total" pair_count_current=0 pair_count_remaining=$pair_count_total # Iterate over all pairs of nodes for start in {0..24}; do read x1 y1 <<< $(get_coordinates $start) if [[ $start -lt 10 ]];then srv_current=apu0$start else srv_current=apu$start fi for end in {0..24}; do if [[ $start -ne $end ]]; then read x2 y2 <<< $(get_coordinates $end) # Calculate Manhattan distance # distance=$(manhattan_distance $x1 $y1 $x2 $y2) distance=$(chebyshev_distance $x1 $y1 $x2 $y2) # If distance matches the given hops, print the pair if [[ $distance -eq $hops ]]; then if [[ $end -lt 10 ]];then clt_current=apu0$end else clt_current=apu$end fi echo "($start, $end)" # echo "start ping" # ping_count=3 # ssh $user@$srv_current "ping -c $ping_count $clt_current | awk -F'/' '/^rtt/ { print $5 }' 2>/dev/null" # pid1=$! # wait $pid1 # echo "ping done" iperf_measure "$csv_file" "root" "$srv_current" "$clt_current" "1" # last "1" for debug output # iperf_measure "$csv_file" "root" "$srv_current" "$clt_current" "1" "1" # last "1" for debug output ((total+=1)) # sleep $delay # ((time_remaining-=$delay+$measurement_time)) # start_server=0 # ssh $user@$srv_current "pkill iperf3" ((pair_count_current+=1)) ((pair_count_remaining=$pair_count_total-$pair_count_current)) echo "Already measured pairs: $pair_count_current" echo "Pairs remaining: $pair_count_remaining" fi fi done done # echo "Total measure steps: $total" # iperf_measure "$csv_file" "root" "apu00" "apu01"