diff --git a/scripts/sosp24-experiments/vm_tx_flows_exp.sh b/scripts/sosp24-experiments/vm_tx_flows_exp.sh new file mode 100755 index 000000000..24a17e2b3 --- /dev/null +++ b/scripts/sosp24-experiments/vm_tx_flows_exp.sh @@ -0,0 +1,177 @@ +#!/bin/bash +cd .. +echo "Running flow experiment... this may take a few minutes" + +# Add dry run flag +DRY_RUN=0 + +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --dry) + DRY_RUN=1 + shift # past argument + ;; + *) + shift # past unknown argument + ;; + esac +done + +GUEST_INTF="enp0s1np0" +GUEST_IP="192.168.101.11" +GUEST_NIC_BUS="0x0" +GUEST_HOME="/home/schai" +# for some reason, public domain name doesn't work +HOST_IP="192.17.101.97" +HOST_UNAME="lbalara" +HOST_HOME="/home/lbalara" +CLIENT_HOME="/home/siyuanc3" +CLIENT_INTF="ens1006np0" +CLIENT_IP="192.168.101.3" +CLIENT_SSH_UNAME="siyuanc3" +CLIENT_SSH_HOST="nexus03.csl.illinois.edu" # Public IP or hostname for SSH "genie12.cs.cornell.edu" +CLIENT_SSH_PASSWORD="saksham" +CLIENT_USE_PASS_AUTH=0 # 1 to use password, 0 to use identity file +CLIENT_SSH_IDENTITY_FILE="/home/schai/.ssh/id_rsa" + +function detect_virt_tech() { + local virsh_out=$(ssh -i "$CLIENT_SSH_IDENTITY_FILE" "${HOST_UNAME}@${HOST_IP}" 'bash -l -c "virsh list --all"') + local running_vms=$(echo "$virsh_out" | grep running | awk '{print $2}') + + if [ -z "$running_vms" ]; then + echo "ERROR: No VMs are currently running" >&2 + return 1 + fi + + echo "Found running VMs: $running_vms" >&2 + + local detected_tech="" + if [[ "$running_vms" == *"nested"* ]]; then + detected_tech="nested" + elif [[ "$running_vms" == *"shadow"* ]]; then + detected_tech="shadow" + elif [[ "$running_vms" == *"off"* ]]; then + detected_tech="off" + else + echo "ERROR: Could not detect virtualization technology from VM name: $running_vms" >&2 + echo "Expected VM name to contain 'nested', 'shadow', or 'off'" >&2 + return 1 + fi + + echo "$detected_tech" + return 0 +} + +parse_iommu_mode() { + local cmdline="${1:-$( iova.log" + + cd - + sudo chmod +666 -R ../utils/reports/$exp_name + + done + done +done + diff --git a/scripts/vm-tx-collect-tput-stats.py b/scripts/vm-tx-collect-tput-stats.py new file mode 100644 index 000000000..d6b25ff19 --- /dev/null +++ b/scripts/vm-tx-collect-tput-stats.py @@ -0,0 +1,184 @@ +import sys +import numpy as np +import statistics +import subprocess + +# TODO: Leshna, Combine both vm and baremetal stat collector with file names as parameters. + +EXP_NAME = sys.argv[1] +NUM_RUNS = int(sys.argv[2]) +COLLECT_MLC_TPUT = int(sys.argv[3]) + +FILE_NAME = "../utils/reports/" + EXP_NAME +command = 'mkdir -p ' + FILE_NAME +result = subprocess.run(command, shell=True, capture_output=True, text=True) + +net_tputs = [] +retx_rates = [] +sent_packets = [] +mem_bws = [] +cpu_utils = [] +mlc_tputs = [] + +pcie_wr_tput = [] +iotlb_first_lookup = [] +iotlb_all_lookup = [] +iotlb_miss = [] +iommu_mem_access = [] +iotlb_inv = [] +pwt_occupancy = [] + +# iotlb_hits = [] +# ctx_lookup = [] +# ctx_hits = [] +# ctxt_misses = [] +# cache_lookup = [] +# cache_hit_256T = [] +# cache_hit_512G = [] +# cache_hit_1G = [] +# cache_hit_2M = [] +# cache_fills = [] + +for i in range(NUM_RUNS): + with open(FILE_NAME + '-RUN-' + str(i) + '/iperf.bw.rpt') as f1: + for line in f1: + tput = float(line.split()[-1]) + if (tput > 0): + net_tputs.append(tput) + break + + with open(FILE_NAME + '-RUN-' + str(i) + '/retx.rpt') as f1: + for line in f1: + line_str = line.split() + if (line_str[0] == 'Retx_percent:'): # always come last so we can break + retx_pct = float(line_str[-1]) + if (retx_pct >= 0): + retx_rates.append(retx_pct) + break + elif (line_str[0] == "Recv:"): + sent = float(line_str[-1]) + sent_packets.append(sent) + + with open(FILE_NAME + '-RUN-' + str(i) + '/host-membw.rpt') as f1: + try: + for line in f1: + line_str = line.split() + if (line_str[0] != 'Node0_total_bw:'): + continue + else: + membw = float(line_str[-1]) + if (membw >= 0): + mem_bws.append(membw) + break + except Exception as e: + mem_bws.append(0) + + with open(FILE_NAME + '-RUN-' + str(i) + '/cpu_util.rpt') as f1: + for line in f1: + line_str = line.split() + if (line_str[0] != 'avg_cpu_util:'): + continue + else: + cpu_util = float(line_str[-1]) + if (cpu_util >= 0): + cpu_utils.append(cpu_util) + break + try: + with open(FILE_NAME + '-RUN-' + str(i) + '/host-pcie.rpt') as f1: + for line in f1: + line_str = line.split() + if (line_str[0] == 'PCIe_wr_tput:'): + pcie_tput = float(line_str[-1]) + if (pcie_tput >= 0): + pcie_wr_tput.append(pcie_tput) + elif (line_str[0] == 'IOTLB_first_lookup_avg:'): + iotlb_first_lookup_ = float(line_str[-1]) + iotlb_first_lookup.append(iotlb_first_lookup_) + elif (line_str[0] == 'IOTLB_all_lookup_avg:'): + iotlb_all_lookup_ = float(line_str[-1]) + iotlb_all_lookup.append(iotlb_all_lookup_) + elif (line_str[0] == 'IOTLB_miss_avg:'): + iotlb_miss_ = float(line_str[-1]) + iotlb_miss.append(iotlb_miss_) + elif (line_str[0] == 'IOMMU_mem_access:'): + iommu_mem_access_ = float(line_str[-1]) + iommu_mem_access.append(iommu_mem_access_) + elif (line_str[0] == 'IOTLB_inv_avg:'): + iotlb_inv_ = float(line_str[-1]) + iotlb_inv.append(iotlb_inv_) + elif (line_str[0] == 'PWT_occupancy_avg:'): + pwt_occupancy_ = float(line_str[-1]) + pwt_occupancy.append(pwt_occupancy_) + except Exception as e: + pcie_wr_tput.append(0) + iotlb_first_lookup.append(0) + iotlb_all_lookup.append(0) + iotlb_miss.append(0) + iommu_mem_access.append(0) + iotlb_inv.append(0) + pwt_occupancy.append(0) + + if (COLLECT_MLC_TPUT > 0 and False): + with open(FILE_NAME + '-MLCRUN-' + str(i) + '/mlc.log') as f1: + for line in f1: + if line.startswith(' 00000'): + tput = float(line.split()[-1]) + if (tput >= 0): + mlc_tputs.append(tput) + break + + +def mean_or_zero(arr): return statistics.mean(arr) if arr else 0 +def stdev_or_zero(arr): return statistics.stdev(arr) if len(arr) > 1 else 0 + + +cpu_utils_mean = mean_or_zero(cpu_utils); cpu_utils_stddev = stdev_or_zero(cpu_utils) +net_tput_mean = mean_or_zero(net_tputs); net_tput_stddev = stdev_or_zero(net_tputs) +retx_rate_mean = mean_or_zero(retx_rates); retx_rate_stddev = stdev_or_zero(retx_rates) +sent_packets_mean = mean_or_zero(sent_packets); sent_packets_stddev = stdev_or_zero(sent_packets) +mem_bw_mean = mean_or_zero(mem_bws); mem_bw_stddev = stdev_or_zero(mem_bws) +pcie_wr_tput_mean = mean_or_zero(pcie_wr_tput); pcie_wr_tput_stddev = stdev_or_zero(pcie_wr_tput) + +iotlb_first_lookup_mean = mean_or_zero(iotlb_first_lookup); iotlb_first_lookup_stddev = stdev_or_zero(iotlb_first_lookup) +iotlb_all_lookup_mean = mean_or_zero(iotlb_all_lookup); iotlb_all_lookup_stddev = stdev_or_zero(iotlb_all_lookup) +iotlb_miss_mean = mean_or_zero(iotlb_miss); iotlb_miss_stddev = stdev_or_zero(iotlb_miss) +iommu_mem_access_mean = mean_or_zero(iommu_mem_access); iommu_mem_access_stddev = stdev_or_zero(iommu_mem_access) +iotlb_inv_mean = mean_or_zero(iotlb_inv); iotlb_inv_stddev = stdev_or_zero(iotlb_inv) +pwt_occupancy_mean = mean_or_zero(pwt_occupancy); pwt_occupancy_stddev = stdev_or_zero(pwt_occupancy) + +mlc_tput_mean = 0 +mlc_tput_stddev = 0 + +if (COLLECT_MLC_TPUT > 0): + mlc_tput_mean = statistics.mean(mlc_tputs) + if NUM_RUNS > 1: + mlc_tput_stddev = statistics.stdev(mlc_tputs) + else: + mlc_tput_stddev = 0 + +output_list = [ + ("cpu_utils_mean", cpu_utils_mean), ("cpu_utils_stddev", cpu_utils_stddev), + ("net_tput_mean", net_tput_mean), ("net_tput_stddev", net_tput_stddev), + ("retx_rate_mean", retx_rate_mean), ("retx_rate_stddev", retx_rate_stddev), + ("mem_bw_mean", mem_bw_mean), ("mem_bw_stddev", mem_bw_stddev), + ("pcie_wr_tput_mean", pcie_wr_tput_mean), ("pcie_wr_tput_stddev", pcie_wr_tput_stddev), + + ("iotlb_first_lookup_mean", iotlb_first_lookup_mean), ("iotlb_first_lookup_stddev", iotlb_first_lookup_stddev), + ("iotlb_all_lookup_mean", iotlb_all_lookup_mean), ("iotlb_all_lookup_stddev", iotlb_all_lookup_stddev), + ("iotlb_miss_mean", iotlb_miss_mean), ("iotlb_miss_stddev", iotlb_miss_stddev), + ("iommu_mem_access_mean", iommu_mem_access_mean), ("iommu_mem_access_stddev", iommu_mem_access_stddev), + ("iotlb_inv_mean", iotlb_inv_mean), ("iotlb_inv_stddev", iotlb_inv_stddev), + ("pwt_occupancy_mean", pwt_occupancy_mean), ("pwt_occupancy_stddev", pwt_occupancy_stddev), + + ("mlc_tput_mean", 0 if not mlc_tputs else mean_or_zero(mlc_tputs)), + ("mlc_tput_stddev", 0 if len(mlc_tputs) < 2 else stdev_or_zero(mlc_tputs)), + ("sent_packets_mean", sent_packets_mean), ("sent_packets_stddev", sent_packets_stddev), +] + +headers, outputs = zip(*output_list) +headers = ",".join(headers) +outputs = list(outputs) + +# Save array to DAT file +np.savetxt(FILE_NAME + '/tput_metrics.dat', + [outputs], delimiter=",", header=headers, comments='', fmt='%.10f') diff --git a/scripts/vm-tx-run-dctcp-tput-experiment.sh b/scripts/vm-tx-run-dctcp-tput-experiment.sh new file mode 100755 index 000000000..15f9d375c --- /dev/null +++ b/scripts/vm-tx-run-dctcp-tput-experiment.sh @@ -0,0 +1,631 @@ +#!/bin/bash + +# Treat unset variables as an error when substituting. +set -u + +#------------------------------------------------------------------------------- +# CONFIGURATION AND PATHS +#------------------------------------------------------------------------------- +SCRIPT_NAME="run-rdma-tput-experiment" +INIT_PORT=3000 +MLC_DURATION_S=100 +GUEST_MLC_DIR_REL="mlc/Linux" + +FTRACE_BUFFER_SIZE_KB=20000 +FTRACE_OVERWRITE_ON_FULL=0 # 0=no overwrite (tracing stops when full), 1=overwrite +PERF_TRACING_ENABLED=0 +PERF_TRACING_HOST_ENABLED=1 + +# --- Base Directory Paths (Relative to respective home directories) --- +GUEST_FandS_REL="viommu_iks" +GUEST_PERF_REL="linux-6.12.9/tools/perf/perf" # TODO: Siyuan change for your directory +CLIENT_FandS_REL="Fast-and-Safe-IO-Memory-Protection" +HOST_FandS_REL="viommu/Fast-and-Safe-IO-Memory-Protection" +HOST_VIOMMU_REL="viommu/Fast-and-Safe-IO-Memory-Protection" +HOST_RESULTS_REL="viommu" +HOST_PERF_REL="viommu/linux-6.12.9/tools/perf/perf" # TODO: Siyuan change for your directory + +# --- F and S Directory Paths (Relative to respective F and S directories) --- +GUEST_SETUP_DIR_REL="utils" +GUEST_EXP_DIR_REL="utils/tcp" +CLIENT_SETUP_DIR_REL="utils" +CLIENT_EXP_DIR_REL="utils/tcp" +HOST_SETUP_DIR_REL="utils" + +EBPF_GUEST_LOADER_REL="$GUEST_FandS_REL/tracing/guest_loader" +EBPF_HOST_LOADER_REL="$HOST_VIOMMU_REL/tracing/host_loader" + +# --- Remote Access (SSH) Configuration --- +HOST_SSH_UNAME="lbalara" +HOST_SSH_PASSWORD="" +HOST_SSH_IDENTITY_FILE="/home/schai/.ssh/id_rsa" +HOST_USE_PASS_AUTH=0 + +#------------------------------------------------------------------------------- +# DEFAULT CONFIGURATION AND PATHS EDITABLE BY COMMAND LINE +#------------------------------------------------------------------------------- +# --- Experiment Setup --- +EXP_NAME="tput-test" +NUM_RUNS=1 +CORE_DURATION_S=20 # Duration for the main workload +MLC_CORES="none" +EBPF_TRACING_ENABLED=1 #test +EBPF_TRACING_HOST_ENABLED=0 + +# --- Guest (Server) Machine Configuration --- +GUEST_HOME="/home/schai" +GUEST_IP="10.10.1.50" +GUEST_INTF="enp8s0np1" +GUEST_NIC_BUS="0x08" +GUEST_NUM_SERVERS=5 +GUEST_CPU_MASK="0,1,2,3,4" + +# --- Client Machine Configuration --- +CLIENT_HOME="/users/Leshna/" +CLIENT_IP="10.10.1.2" +CLIENT_INTF="eno12409np1" +CLIENT_NUM_CLIENTS=5 +CLIENT_CPU_MASK="0,4,8,12,16" +CLIENT_BANDWIDTH="100g" + +# --- Host Machine Configuration --- +HOST_HOME="/users/Leshna" +HOST_IP="192.168.122.1" + +# --- Network & System Parameters --- +MTU=4000 +DDIO_ENABLED=1 +RING_BUFFER_SIZE=256 +TCP_SOCKET_BUF_MB=1 + +# --- Remote Access (SSH) Configuration --- +CLIENT_SSH_UNAME="saksham" +CLIENT_SSH_HOST="genie12.cs.cornell.edu" # Public IP or hostname for SSH "genie12.cs.cornell.edu" +CLIENT_SSH_PASSWORD="saksham" +CLIENT_USE_PASS_AUTH=1 # 1 to use password, 0 to use identity file +CLIENT_SSH_IDENTITY_FILE="/home/schai/.ssh/id_ed25519" + +#------------------------------------------------------------------------------- +# Help/usage +#------------------------------------------------------------------------------- +help() { + echo "Usage: $SCRIPT_NAME" + echo "Server/Guest Configuration:" + echo " [ --guest-home (Guest home directory) ]" + echo " [ --guest-ip (IP address of the server/guest) ]" + echo " [ --guest-intf (Network interface for the server/guest) ]" + echo " [ --guest-bus (NIC’s PCI bus number) ]" + echo " [ -n | --guest-num (Number of server instances; default: 5) ]" + echo " [ -c | --guest-cpu-mask (Guest CPU mask, comma-separated; default: 0,1,2,3,4) ]" + echo + echo "Client Configuration:" + echo " [ --client-home (Client home directory) ]" + echo " [ --client-ip (IP address of the client) ]" + echo " [ --client-intf (Interface name for the client) ]" + echo " [ -N | --client-num (Number of client instances; default: 5) ]" + echo " [ -C | --client-cpu-mask (Client CPU mask, comma-separated; default: 0,4,8,12,16) ]" + echo + echo "Host Configuration:" + echo " [ --host-home (Host home directory) ]" + echo " [ --host-ip (IP address of the host) ]" + echo + echo "Experiment Parameters:" + echo " [ -e | --exp-name (Experiment name for output directories; default: tput-test) ]" + echo " [ -m | --mtu (MTU size: 256/512/1024/2048/4096; default: 4000) ]" + echo " [ -d | --ddio <0|1> (DDIO enabled; default: 1) ]" + echo " [ -b | --bandwidth (Client bandwidth in bits/sec, e.g., 100g; default: 100g) ]" + echo " [ -r | --ring-buffer (NIC Rx ring buffer size; default: 256) ]" + echo " [ --mlc-cores (MLC cores; default: none) ]" + echo " [ --socket-buf (TCP socket buffer size in MB; default: 1) ]" + echo " [ --dur (Core experiment duration in seconds; default: 20) ]" + echo " [ --runs (Number of experiment repetitions; default: 1) ]" + echo " [ --ebpf-tracing <0|1> (Enable eBPF tracing; default: 0) ]" + echo + echo "Client SSH Configuration" + echo " [ --client-ssh-name (SSH username for client) ]" + echo " [ --client-ssh-host (Public IP or hostname for client) ]" + echo " [ --client-ssh-use-pass <0|1> (Use password for SSH instead of identity file) ]" + echo " [ --client-ssh-pass (SSH Password for client; needed if client-ssh-use-pass 1) ]" + echo " [ --client-ssh-ifile (Path of identity file; needed if client-ssh-use-pass 0) ]" + echo "Help:" + echo " [ -h | --help ]" + exit 2 +} + + +#------------------------------------------------------------------------------- +# COMMAND-LINE ARGUMENT PARSING +#------------------------------------------------------------------------------- +SHORT_OPTS="n:c:N:C:e:m:d:b:r:h" +LONG_OPTS="guest-home:,guest-ip:,guest-intf:,guest-bus:,guest-num:,guest-cpu-mask:,\ +client-home:,client-ip:,client-intf:,client-num:,client-cpu-mask:,\ +host-home:,host-ip:,\ +exp-name:,mtu:,ddio:,bandwidth:,ring-buffer:,mlc-cores:,socket-buf:,dur:,runs:,ebpf-tracing:,\ +client-ssh-name:,client-ssh-host:,client-ssh-use-pass:,client-ssh-pass:,client-ssh-ifile:,help" + +PARSED_OPTS=$(getopt -a -n "$SCRIPT_NAME" --options "$SHORT_OPTS" --longoptions "$LONG_OPTS" -- "$@") +VALID_ARGUMENTS=$# +if [ "$VALID_ARGUMENTS" -eq 0 ]; then + help +fi +eval set -- "$PARSED_OPTS" + +while :; do + case "$1" in + --guest-home) GUEST_HOME="$2"; shift 2 ;; + --guest-ip) GUEST_IP="$2"; shift 2 ;; + --guest-intf) GUEST_INTF="$2"; shift 2 ;; + --guest-bus) GUEST_NIC_BUS="$2"; shift 2 ;; + -n | --guest-num) GUEST_NUM_SERVERS="$2"; shift 2 ;; + -c | --guest-cpu-mask) GUEST_CPU_MASK="$2"; shift 2 ;; + --client-home) CLIENT_HOME="$2"; shift 2 ;; + --client-ip) CLIENT_IP="$2"; shift 2 ;; + --client-intf) CLIENT_INTF="$2"; shift 2 ;; + -N | --client-num) CLIENT_NUM_CLIENTS="$2"; shift 2 ;; + -C | --client-cpu-mask) CLIENT_CPU_MASK="$2"; shift 2 ;; + --host-home) HOST_HOME="$2"; shift 2 ;; + --host-ip) HOST_IP="$2"; shift 2 ;; + -e | --exp-name) EXP_NAME="$2"; shift 2 ;; + -m | --mtu) MTU="$2"; shift 2 ;; + -d | --ddio) DDIO_ENABLED="$2"; shift 2 ;; + -b | --bandwidth) CLIENT_BANDWIDTH="$2"; shift 2 ;; + -r | --ring-buffer) RING_BUFFER_SIZE="$2"; shift 2 ;; + --mlc-cores) MLC_CORES="$2"; shift 2 ;; + --socket-buf) TCP_SOCKET_BUF_MB="$2"; shift 2 ;; + --dur) CORE_DURATION_S="$2"; shift 2 ;; + --runs) NUM_RUNS="$2"; shift 2 ;; + --ebpf-tracing) EBPF_TRACING_ENABLED="$2"; shift 2 ;; + --client-ssh-name) CLIENT_SSH_UNAME="$2"; shift 2 ;; + --client-ssh-host) CLIENT_SSH_HOST="$2"; shift 2 ;; + --client-ssh-use-pass) CLIENT_USE_PASS_AUTH="$2"; shift 2 ;; + --client-ssh-pass) CLIENT_SSH_PASSWORD="$2"; shift 2 ;; + --client-ssh-ifile) CLIENT_SSH_IDENTITY_FILE="$2"; shift 2 ;; + -h | --help) help ;; + --) shift; break ;; + *) echo "Unexpected option: $1"; help ;; + esac +done + +GUEST_SETUP_DIR="${GUEST_HOME}/${GUEST_FandS_REL}/${GUEST_SETUP_DIR_REL}" +GUEST_EXP_DIR="${GUEST_HOME}/${GUEST_FandS_REL}/${GUEST_EXP_DIR_REL}" +GUEST_MLC_DIR="${GUEST_HOME}/${GUEST_MLC_DIR_REL}" +GUEST_PERF="${GUEST_HOME}/${GUEST_PERF_REL}" +CLIENT_SETUP_DIR="${CLIENT_HOME}/${CLIENT_FandS_REL}/${CLIENT_SETUP_DIR_REL}" +CLIENT_EXP_DIR="${CLIENT_HOME}/${CLIENT_FandS_REL}/${CLIENT_EXP_DIR_REL}" +HOST_RESULTS_DIR="${HOST_HOME}/${HOST_RESULTS_REL}" # TODO: Siyuan (Better name suggestion) +HOST_SETUP_DIR="${HOST_HOME}/${HOST_FandS_REL}/${HOST_SETUP_DIR_REL}" +HOST_PERF="${HOST_HOME}/${HOST_PERF_REL}" # Path on host for perf +EBPF_GUEST_LOADER="${GUEST_HOME}/${EBPF_GUEST_LOADER_REL}" +EBPF_HOST_LOADER="${HOST_HOME}/${EBPF_HOST_LOADER_REL}" +PROFILING_LOGGING_DUR_S=$((CORE_DURATION_S)) + +if [ "$CLIENT_USE_PASS_AUTH" -eq 1 ]; then + SSH_CLIENT_CMD="sshpass -p $CLIENT_SSH_PASSWORD ssh ${CLIENT_SSH_UNAME}@${CLIENT_SSH_HOST}" +else + SSH_CLIENT_CMD="ssh -i $CLIENT_SSH_IDENTITY_FILE ${CLIENT_SSH_UNAME}@${CLIENT_SSH_HOST}" +fi + +if [ "$HOST_USE_PASS_AUTH" -eq 1 ]; then + SSH_HOST_CMD="sshpass -p $HOST_SSH_PASSWORD ssh ${HOST_SSH_UNAME}@${HOST_IP}" +else + SSH_HOST_CMD="ssh -i $HOST_SSH_IDENTITY_FILE ${HOST_SSH_UNAME}@${HOST_IP}" +fi + +log_info() { + echo "[INFO] - $1" +} + +log_error() { + echo "[ERROR] - $1" >&2 +} + +progress_bar() { + local duration_secs=$1 + local interval_secs=$2 + local elapsed_time_secs=0 + + if [ "$duration_secs" -eq 0 ]; then + printf "[==================================================] 100%% (0/0s)\n" + return + fi + + local progress_bar_width=50 + while [ "$elapsed_time_secs" -lt "$duration_secs" ]; do + elapsed_time_secs=$((elapsed_time_secs + interval_secs)) + if [ "$elapsed_time_secs" -gt "$duration_secs" ]; then + elapsed_time_secs=$duration_secs + fi + + local progress_percent=$((elapsed_time_secs * 100 / duration_secs)) + local bar_filled_length=$((progress_percent * progress_bar_width / 100)) + + local bar_visual="" + for ((k=0; k/dev/null || true + sudo pkill -9 -f "$guest_loader_basename" 2>/dev/null || true + fi + if [ "$EBPF_TRACING_HOST_ENABLED" -eq 1 ]; then + local host_loader_basename + host_loader_basename=$(basename "$EBPF_HOST_LOADER") + $SSH_HOST_CMD \ + "sudo pkill -SIGINT -f '$host_loader_basename'; sleep 5; sudo pkill -9 -f '$host_loader_basename'; screen -S ebpf_host_tracer -X quit || true" + sleep 5 + fi + + log_info "Terminating screen sessions..." + $SSH_CLIENT_CMD \ + 'screen -ls | grep -E "\.client_session|\.logging_session_client" | cut -d. -f1 | xargs -r -I % screen -S % -X quit' + $SSH_CLIENT_CMD \ + 'sudo pkill -9 -f iperf; screen -wipe || true' + $SSH_HOST_CMD \ + 'screen -ls | grep -E "\.host_session|\.perf_screen|\.perf_kvm_screen|\.perf_sched_screen|\.logging_session_host" | cut -d. -f1 | xargs -r -I % screen -S % -X quit' + $SSH_HOST_CMD \ + 'screen -wipe || true' + + log_info "Resetting GUEST ftrace..." + sudo echo 0 > /sys/kernel/debug/tracing/tracing_on + sudo echo 0 > /sys/kernel/debug/tracing/options/overwrite + sudo echo 20000 > /sys/kernel/debug/tracing/buffer_size_kb + + log_info "Resetting HOST..." + $SSH_HOST_CMD \ + "cd '$HOST_SETUP_DIR'; sudo bash reset-host.sh" + + log_info "Resetting GUEST network interface $GUEST_INTF..." + sudo ip link set "$GUEST_INTF" down + sleep 2 + sudo ip link set "$GUEST_INTF" up + sleep 2 + log_info "--- Cleanup Phase Finished ---" +} + +save_config_to_report_json() { + local report_dir="${1:-$current_guest_reports_dir}" + local config_file="$report_dir/config.json" + + local guest_cmdline=$(cat /proc/cmdline) + local guest_kernel=$(uname -r) + local host_cmdline=$($SSH_HOST_CMD 'cat /proc/cmdline') + local host_kernel=$($SSH_HOST_CMD 'uname -r') + local client_cmdline=$($SSH_CLIENT_CMD 'cat /proc/cmdline') + local client_kernel=$($SSH_CLIENT_CMD 'uname -r') + + cat > "$config_file" << EOF +{ + "timestamp": "$(date -Iseconds)", + "test_params": { + "core_duration_s": "$CORE_DURATION_S", + "mtu": "$MTU", + "ddio_enabled": "$DDIO_ENABLED", + "ring_buffer_size": "$RING_BUFFER_SIZE", + "tcp_socket_buf_mb": "$TCP_SOCKET_BUF_MB", + "mlc_cores": "$MLC_CORES" + }, + "guest": { + "ip": "$GUEST_IP", + "interface": "$GUEST_INTF", + "num_servers": "$GUEST_NUM_SERVERS", + "cpu_mask": "$GUEST_CPU_MASK", + "nic_bus": "$GUEST_NIC_BUS", + "kernel": "$guest_kernel", + "cmdline": "$guest_cmdline" + }, + "client": { + "ip": "$CLIENT_IP", + "interface": "$CLIENT_INTF", + "num_clients": "$CLIENT_NUM_CLIENTS", + "cpu_mask": "$CLIENT_CPU_MASK", + "bandwidth": "$CLIENT_BANDWIDTH", + "kernel": "$client_kernel", + "cmdline": "$client_cmdline" + }, + "host": { + "kernel": "$host_kernel", + "cmdline": "$host_cmdline" + } +} +EOF +} + +save_vm_config_to_report() { + local report_dir="${1:-$current_guest_reports_dir}" + + log_info "Fetching running VM configurations..." + + local virsh_out=$($SSH_HOST_CMD 'bash -l -c "virsh list --all"') + local running_vms=$(echo "$virsh_out" | grep running | awk '{print $2}') + + if [ -z "$running_vms" ]; then + log_error "Warning: No VMs are currently running" + return 1 + fi + + log_info "Found running VMs: $running_vms" + + for vm in $running_vms; do + log_info "Dumping XML for: $vm" + local xml_file="$report_dir/${vm}_domain.xml" + + $SSH_HOST_CMD "bash -l -c \"virsh dumpxml $vm\"" > "$xml_file" 2>&1 + + if [ $? -eq 0 ]; then + log_info "Saved to: ${vm}_domain.xml" + else + log_error "Failed to dump XML for $vm" + fi + done +} + +log_info "Starting experiment: $EXP_NAME" +log_info "Number of runs: $NUM_RUNS" + +for ((j = 0; j < NUM_RUNS; j += 1)); do + echo + log_info "############################################################" + log_info "### Starting Experiment Run: $j / $(($NUM_RUNS - 1)) for EXP: $EXP_NAME" + log_info "############################################################" + + # --- Per-Run Directory and File Definitions --- + # Guest (Server) side paths for reports and data + current_guest_reports_dir="${GUEST_SETUP_DIR}/reports/${EXP_NAME}-RUN-${j}" + host_reports_dir_remote="${HOST_SETUP_DIR}/reports/${EXP_NAME}-RUN-${j}" + client_reports_dir_remote="${CLIENT_SETUP_DIR}/reports/${EXP_NAME}-RUN-${j}" + + perf_guest_data_file="${current_guest_reports_dir}/perf_guest_cpu.data" + iova_ftrace_guest_output_file="${current_guest_reports_dir}/iova_ftrace_guest.txt" + ebpf_guest_stats="${current_guest_reports_dir}/ebpf_guest_stats.csv" + guest_server_app_log_file="${current_guest_reports_dir}/server_app.log" + guest_mlc_log_file="${current_guest_reports_dir}/mlc.log" + perf_host_data_file_remote="${host_reports_dir_remote}/perf_host_cpu.data" + perf_kvm_data_file_remote="${host_reports_dir_remote}/perf_host_kvm.data" + perf_sched_data_file_remote="${host_reports_dir_remote}/perf_host_sched.data" + iova_ftrace_host_output_file_remote="${host_reports_dir_remote}/iova_ftrace_host.txt" + ebpf_host_stats="${host_reports_dir_remote}/ebpf_host_stats.csv" + + sudo mkdir -p "$current_guest_reports_dir" + $SSH_HOST_CMD "sudo mkdir -p '$host_reports_dir_remote'" + + # --- Pre-run cleanup --- + cleanup + + # --- Add config to reports --- + save_config_to_report_json "$current_guest_reports_dir" + save_vm_config_to_report "$current_guest_reports_dir" + + # --- Start MLC (Memory Latency Checker) if configured --- + if [ "$MLC_CORES" != "none" ]; then + log_info "Starting MLC on cores: $MLC_CORES; logs at $guest_mlc_log_file..." + "$GUEST_MLC_DIR/mlc" --loaded_latency -T -d0 -e -k"$MLC_CORES" -j0 -b1g -t10000 -W2 &> "$guest_mlc_log_file" & + log_info "Waiting for MLC to ramp up (30 seconds)..." + progress_bar 30 1 + else + log_info "MLC not configured for this run." + fi + + # --- Setup and Start Clients --- + log_info "Setting up and starting CLIENTS on $CLIENT_SSH_HOST..." + client_cmd="cd '$CLIENT_SETUP_DIR'; sudo bash setup-envir.sh --dep '$CLIENT_HOME' --intf '$CLIENT_INTF' --ip '$CLIENT_IP' -m '$MTU' -d '$DDIO_ENABLED' -r '$RING_BUFFER_SIZE' --socket-buf '$TCP_SOCKET_BUF_MB' --hwpref 1 --rdma 0 --pfc 0 --ecn 1 --opt 1; " + client_cmd+="cd '$CLIENT_EXP_DIR'; sudo bash run-tx-netapp-tput.sh --mode server -n '$GUEST_NUM_SERVERS' -N '$CLIENT_NUM_CLIENTS' -o '${EXP_NAME}-RUN-${j}' -p '$INIT_PORT' -c '$CLIENT_CPU_MASK'; exec bash" + $SSH_CLIENT_CMD "screen -dmS client_session sudo bash -c \"$client_cmd\"" + sleep 2 + + # --- Setup Guest (Server) Environment --- + log_info "Setting up GUEST server environment..." + cd "$GUEST_SETUP_DIR" || { log_error "Failed to cd to $GUEST_SETUP_DIR"; exit 1; } + sudo bash setup-envir.sh --dep "$GUEST_HOME" --intf "$GUEST_INTF" --ip "$GUEST_IP" -m "$MTU" -d "$DDIO_ENABLED" -r "$RING_BUFFER_SIZE" \ + --socket-buf "$TCP_SOCKET_BUF_MB" --hwpref 1 --rdma 0 --pfc 0 --ecn 1 --opt 1 --nic-bus "$GUEST_NIC_BUS" + cd - > /dev/null # Go back to previous directory silently + + # --- Setup Host Environment --- + log_info "Setting up HOST environment on $HOST_IP..." + $SSH_HOST_CMD \ + "screen -dmS host_session sudo bash -c \"cd '$HOST_SETUP_DIR'; sudo bash setup-host.sh -m '$MTU' --socket-buf '$TCP_SOCKET_BUF_MB' --hwpref 1 --rdma 0 --ecn 1; exec bash\"" + + # --- Start Guest (Server) Application --- + log_info "Starting GUEST server application; logs at $guest_server_app_log_file" + cd "$GUEST_EXP_DIR" || { log_error "Failed to cd to $GUEST_EXP_DIR"; exit 1; } + # echo "sudo bash run-tx-netapp-tput.sh --mode client --server-ip '$CLIENT_IP' -n "$GUEST_NUM_SERVERS" -N "$CLIENT_NUM_CLIENTS" -o "${EXP_NAME}-RUN-${j}" -p "$INIT_PORT" -c "$GUEST_CPU_MASK" --b '$CLIENT_BANDWIDTH' &> "$guest_server_app_log_file"" + sudo bash run-tx-netapp-tput.sh --mode client --server-ip "$CLIENT_IP" -n "$GUEST_NUM_SERVERS" -N "$CLIENT_NUM_CLIENTS" -o "${EXP_NAME}-RUN-${j}" \ + -p "$INIT_PORT" -c "$GUEST_CPU_MASK" --b "$CLIENT_BANDWIDTH" &> "$guest_server_app_log_file" + sleep 2 # Allow server app to initialize + cd - > /dev/null + + # --- Warmup Phase --- + log_info "Warming up experiment (10 seconds)..." + progress_bar 10 1 + + # --- Start eBPF Tracers (if enabled) --- + if [ "$EBPF_TRACING_ENABLED" -eq 1 ]; then + log_info "Starting GUEST eBPF tracer..." + echo "current_time: $(date) $(date +%s)" + sudo taskset -c 13 "$EBPF_GUEST_LOADER" -d $CORE_DURATION_S -o "$ebpf_guest_stats" & + sleep 2 # Allow eBPF loaders to initialize + fi + if [ "$EBPF_TRACING_HOST_ENABLED" -eq 1 ]; then + log_info "Starting HOST eBPF tracer on $HOST_IP..." + host_loader_cmd="sudo taskset -c 33 $EBPF_HOST_LOADER -o $ebpf_host_stats" + $SSH_HOST_CMD "screen -dmS ebpf_host_tracer sudo bash -c \"$host_loader_cmd\"" + sleep 2 # Allow eBPF loaders to initialize + fi + + # --- Ftrace Setup (Guest & Host) --- + log_info "Configuring GUEST ftrace for IOVA logging (Buffer: ${FTRACE_BUFFER_SIZE_KB}KB, Overwrite: ${FTRACE_OVERWRITE_ON_FULL})..." + sudo echo "$FTRACE_BUFFER_SIZE_KB" > /sys/kernel/debug/tracing/buffer_size_kb + sudo echo "$FTRACE_OVERWRITE_ON_FULL" > /sys/kernel/debug/tracing/options/overwrite + sudo echo > /sys/kernel/debug/tracing/trace # Clear buffer + sudo echo 1 > /sys/kernel/debug/tracing/tracing_on + log_info "GUEST IOVA ftrace is ON." + + log_info "Configuring HOST ftrace for IOVA logging on $HOST_IP..." + $SSH_HOST_CMD \ + "sudo bash -c 'sudo echo '$FTRACE_BUFFER_SIZE_KB' > /sys/kernel/debug/tracing/buffer_size_kb; \ + sudo echo '$FTRACE_OVERWRITE_ON_FULL' > /sys/kernel/debug/tracing/options/overwrite; \ + sudo echo > /sys/kernel/debug/tracing/trace; \ + sudo echo 1 > /sys/kernel/debug/tracing/tracing_on'" + log_info "HOST IOVA ftrace is ON." + + # --- Start Main Profiling & Logging Phase --- + if [ "$PERF_TRACING_ENABLED" -eq 1 ]; then + log_info "Starting GUEST perf record (CPU profiling)..." + sudo "$GUEST_PERF" record -F 99 -a -g --call-graph dwarf -o "$perf_guest_data_file" -- sleep "$PROFILING_LOGGING_DUR_S" & + fi + + if [ "$PERF_TRACING_HOST_ENABLED" -eq 1 ]; then + log_info "Starting HOST perf record (CPU profiling) on $HOST_IP..." + host_perf_cmd="cd '$HOST_SETUP_DIR'; sudo bash perf-record-host.sh -d '$PROFILING_LOGGING_DUR_S' -e '${EXP_NAME}-RUN-${j}'; exec bash" + $SSH_HOST_CMD "screen -dmS perf_screen sudo bash -c \"$host_perf_cmd\"" + fi + + log_info "Starting CLIENT-side logging on $CLIENT_SSH_HOST..." + client_logging_cmd="cd '$CLIENT_SETUP_DIR'; sudo bash record-host-metrics.sh \ + --dep '$CLIENT_HOME' -o '${EXP_NAME}-RUN-${j}' --dur '$CORE_DURATION_S' \ + --cpu-util 1 -c '$CLIENT_CPU_MASK' --retx 1 --tcplog 1 --bw 1 --flame 0 \ + --pcie 0 --membw 0 --iio 0 --pfc 0 --intf '$CLIENT_INTF' --type 0; exec bash" + $SSH_CLIENT_CMD "screen -dmS logging_session_client sudo bash -c \"$client_logging_cmd\"" + + log_info "Starting HOST-side logging on $HOST_IP..." + host_logging_cmd="cd '$HOST_SETUP_DIR'; sudo bash record-host-metrics.sh \ + --dep '$HOST_RESULTS_DIR' -o '${EXP_NAME}-RUN-${j}' --dur '$CORE_DURATION_S' \ + --cpu-util 0 --retx 1 --tcplog 1 --bw 1 --flame 0 \ + --pcie 1 --membw 1 --iio 1 --pfc 0 --type 0; exec bash" + echo $host_logging_cmd + $SSH_HOST_CMD "screen -dmS logging_session_host sudo bash -c \"$host_logging_cmd\"" + + log_info "Starting GUEST-side (server) logging..." + cd "$GUEST_SETUP_DIR" || { log_error "Failed to cd to $GUEST_SETUP_DIR"; exit 1; } + sudo bash record-host-metrics.sh --dep "$GUEST_HOME" -o "${EXP_NAME}-RUN-${j}" \ + --dur "$CORE_DURATION_S" --cpu-util 1 -c "$GUEST_CPU_MASK" --retx 1 --tcplog 1 --bw 1 --flame 0 \ + --pcie 0 --membw 1 --iio 1 --pfc 0 --intf "$GUEST_INTF" --type 0 + cd - > /dev/null + + log_info "Logging done." + log_info "Primary data collection phase on GUEST complete." + + # --- Save Ftrace Data (Guest & Host) --- + log_info "Stopping and saving GUEST IOVA ftrace data..." + sudo echo 0 > /sys/kernel/debug/tracing/tracing_on + sudo cat /sys/kernel/debug/tracing/trace > "$iova_ftrace_guest_output_file" + sudo echo > /sys/kernel/debug/tracing/trace # Clear buffer after saving + log_info "GUEST IOVA ftrace data saved to $iova_ftrace_guest_output_file" + + log_info "Stopping and saving HOST IOVA ftrace data on $HOST_IP..." + $SSH_HOST_CMD \ + "sudo bash -c 'sudo echo 0 > /sys/kernel/debug/tracing/tracing_on; \ + sudo cat /sys/kernel/debug/tracing/trace > '$iova_ftrace_host_output_file_remote'; \ + sudo echo > /sys/kernel/debug/tracing/trace'" + + # --- Stop eBPF Tracers (if enabled) --- + if [ "$EBPF_TRACING_ENABLED" -eq 1 ]; then + log_info "Stopping eBPF tracers..." + echo "current_time: $(date) $(date +%s)" + guest_loader_basename=$(basename "$EBPF_GUEST_LOADER") + sudo pkill -SIGINT -f "$guest_loader_basename" 2>/dev/null && log_info "SIGINT sent to GUEST eBPF loader." || log_info "WARN: GUEST eBPF loader process not found or SIGINT failed." + fi + if [ "$EBPF_TRACING_HOST_ENABLED" -eq 1 ]; then + host_loader_basename=$(basename "$EBPF_HOST_LOADER") + $SSH_HOST_CMD "sudo pkill -SIGINT -f '$host_loader_basename'" + fi + + # --- Transfer Report Files from Remote Machines --- + log_info "Transferring report files from CLIENT and HOST..." + # Client files + if [ "$CLIENT_USE_PASS_AUTH" -eq 1 ]; then + sshpass -p $CLIENT_SSH_PASSWORD \ + scp ${CLIENT_SSH_UNAME}@${CLIENT_SSH_HOST}:${client_reports_dir_remote}/retx.rpt ${current_guest_reports_dir}/client-retx.rpt + else + scp -i "$CLIENT_SSH_IDENTITY_FILE" \ + "${CLIENT_SSH_UNAME}@${CLIENT_SSH_HOST}:${client_reports_dir_remote}/retx.rpt" \ + "${current_guest_reports_dir}/client-retx.rpt" || log_error "Failed to SCP client retx.rpt" + fi + + # Host files + if [ "$HOST_USE_PASS_AUTH" -eq 1 ]; then + sshpass -p $HOST_SSH_PASSWORD scp \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/retx.rpt" \ + "${current_guest_reports_dir}/host-retx.rpt" || log_error "Failed to SCP host retx.rpt" + sshpass -p $HOST_SSH_PASSWORD scp \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/pcie.rpt" \ + "${current_guest_reports_dir}/host-pcie.rpt" || log_error "Failed to SCP host pcie.rpt" + sshpass -p $HOST_SSH_PASSWORD scp \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/membw.rpt" \ + "${current_guest_reports_dir}/host-membw.rpt" || log_error "Failed to SCP host membw.rpt" + else + scp -i "$HOST_SSH_IDENTITY_FILE" \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/retx.rpt" \ + "${current_guest_reports_dir}/host-retx.rpt" || log_error "Failed to SCP host retx.rpt (${host_reports_dir_remote}/retx.rpt)" + scp -i "$HOST_SSH_IDENTITY_FILE" \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/pcie.rpt" \ + "${current_guest_reports_dir}/host-pcie.rpt" || log_error "Failed to SCP host pcie.rpt (${host_reports_dir_remote}/pcie.rpt)" + scp -i "$HOST_SSH_IDENTITY_FILE" \ + "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/membw.rpt" \ + "${current_guest_reports_dir}/host-membw.rpt" || log_error "Failed to SCP host membw.rpt (${host_reports_dir_remote}/membw.rpt)" + fi + # SCP profiling data to host (as guest has limited space) + # sudo sshpass -p "$HOST_SSH_PASSWORD" scp "$perf_guest_data_file" "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/perf_guest_cpu.data" + # sudo sshpass -p "$HOST_SSH_PASSWORD" scp "$iova_ftrace_guest_output_file" "${HOST_SSH_UNAME}@${HOST_IP}:${host_reports_dir_remote}/iova_ftrace_guest.data" + + log_info "Waiting for remote operations and data transfers to settle (original sleep: $(($CORE_DURATION_S * 2))s)..." + progress_bar $((CORE_DURATION_S * 2)) 2 + + # --- Post-run cleanup --- + cleanup + log_info "############################################################" + log_info "### Finished Experiment Run: $j / $(($NUM_RUNS - 1))" + log_info "############################################################" + echo # Blank line +done + + +if [ "$MLC_CORES" != "none" ]; then + log_info "MLC cores were used. The original script had a second phase for MLC throughput which is currently skipped." +else + log_info "No MLC instance used, or MLC throughput collection phase skipped." +fi + +log_info "Collecting and processing statistics from all runs..." +# The '0' or '1' at the end of collect-tput-stats.py might indicate whether MLC was run. Adjust as needed. +if [ "$MLC_CORES" = "none" ]; then + sudo python3 vm-collect-tput-stats.py "$EXP_NAME" "$NUM_RUNS" 0 +else + sudo python3 vm-collect-tput-stats.py "$EXP_NAME" "$NUM_RUNS" 0 # TODO: Change back to 1 +fi + +log_info "Experiment $EXP_NAME finished." diff --git a/utils/tcp/run-tx-netapp-tput.sh b/utils/tcp/run-tx-netapp-tput.sh new file mode 100644 index 000000000..8c01ab20b --- /dev/null +++ b/utils/tcp/run-tx-netapp-tput.sh @@ -0,0 +1,92 @@ +#!/bin/bash +SCRIPT_NAME="run-netapp-tput" + +#default values +MODE="server" +OUT_DIR="tcptest" +SERVER_IP="192.168.11.127" +CPU_MASK="0,1,2,3,4" +NUM_SERVERS=5 +NUM_CLIENTS=5 +PORT=3000 +BANDWIDTH="100g" + +help() +{ + echo "Usage: $SCRIPT_NAME [ --mode (=client/server) ] + [ -o | --outdir (output directory to store the application stats log; default='test')] + [ -n | --num_servers (number of server instances)] + [ -N | --num_clients (number of client instances, only use this option at client)] + [ -p | --port (port number for the first connection) ] + [ --server-ip (ip address of the server, only use this option at client) ] + [ -c | --cores (comma separated cpu core values to run the clients/servers at, for eg., cpu=4,8,12,16; if the number of clients/servers > the number of input cpu cores, the clients/servers will round-robin over the provided input cores; recommended to run on NUMA node local to the NIC for maximum performance) ] + [ -b | --bandwidth (bandwidth to send at in bits/sec)] + [ -h | --help ]" + exit 2 +} + +SHORT=o:,n:,N:,p:,c:,b:,h +LONG=mode:,outdir:,num_servers:,num_clients:,port:,server-ip:,cores:,bandwidth:,help +OPTS=$(getopt -a -n run-netapp-tput --options $SHORT --longoptions $LONG -- "$@") +VALID_ARGUMENTS=$# # Returns the count of arguments that are in short or long options +if [ "$VALID_ARGUMENTS" -eq 0 ]; then + help +fi +eval set -- "$OPTS" + +while :;do + case "$1" in + --mode) MODE="$2"; shift 2 ;; + -o | --outdir) OUT_DIR="$2"; shift 2 ;; + -n | --num_servers) NUM_SERVERS="$2"; shift 2 ;; + -N | --num_clients) NUM_CLIENTS="$2"; shift 2 ;; + -p | --port) PORT="$2"; shift 2 ;; + --server-ip) SERVER_IP="$2"; shift 2 ;; + -c | --cores) CPU_MASK="$2"; shift 2 ;; + -b | --bandwidth) BANDWIDTH="$2"; shift 2 ;; + -h | --help) help ;; + --) shift; break ;; + *) echo "Unexpected option: $1"; help ;; + esac +done + +IFS=',' read -ra core_values <<< $CPU_MASK + +mkdir -p ../reports #Directory to store collected logs +mkdir -p ../reports/$OUT_DIR #Directory to store collected logs +mkdir -p ../logs #Directory to store collected logs +mkdir -p ../logs/$OUT_DIR #Directory to store collected logs +rm -f ../logs/$OUT_DIR/iperf.bw.log + +function collect_stats() { + echo "Collecting app throughput for TCP server..." + echo "Avg_iperf_tput: " $(cat ../logs/$OUT_DIR/iperf.bw.log | grep "30.*-60.*" | awk '{ sum += $7; n++ } END { if (n > 0) printf "%.3f", sum/1000; }') > ../reports/$OUT_DIR/iperf.bw.rpt +} + +counter=0 +if [ "$MODE" = "server" ]; then + sudo pkill -9 -f iperf #kill existing iperf servers/clients + while [ $counter -lt $NUM_SERVERS ]; do + index=$(( counter % ${#core_values[@]} )) + core=${core_values[index]} + echo "Starting server $counter on core $core" + sudo taskset -c $core nice -n -20 iperf3 -s --port $(($PORT + $counter)) -i 1 -f m & + ((counter++)) + done +elif [ "$MODE" = "client" ]; then + sudo pkill -9 -f iperf #kill existing iperf servers/clients + while [ $counter -lt $NUM_CLIENTS ]; do + index=$(( counter % ${#core_values[@]} )) + core=${core_values[index]} + echo "Starting client $counter on core $core" + taskset -c $core nice -n -20 iperf3 -c $SERVER_IP --port $(($PORT+$(($counter%$NUM_SERVERS)))) -i 30 -f m -t 10000 -C dctcp -b $BANDWIDTH --logfile ../logs/$OUT_DIR/iperf.bw.log & + ((counter++)) + done + echo "waiting for few minutes before collecting stats..." + sleep 120 + echo "collecting stats..." + collect_stats +else + echo "incorrect argument specified" + help +fi