From 7a18e84f1b473c98b877fe455fff0468a3759001 Mon Sep 17 00:00:00 2001 From: maki Date: Tue, 18 Nov 2025 18:36:26 +0900 Subject: [PATCH] update --- .../gnb.sa.band78.273prb.rfsim.2x2.conf | 8 + .../5g_rfsimulator/docker-compose.yaml | 80 +++--- ci-scripts/yaml_files/5g_rfsimulator/exp.sh | 266 +++++++++--------- cmake_targets/tools/build_helper | 2 +- docker/Dockerfile.base.ubuntu | 2 - docker/Dockerfile.nakaolab.oct1 | 66 ----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 +- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 3 +- tools/scripts/traffic_runner.sh | 259 ++++------------- 9 files changed, 253 insertions(+), 437 deletions(-) delete mode 100644 docker/Dockerfile.nakaolab.oct1 mode change 100644 => 100755 tools/scripts/traffic_runner.sh diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf index cd949fe8d0..e05e596148 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf @@ -2,6 +2,13 @@ Active_gNBs = ( "gNB-OAI"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; +e2_agent = { + enabled = "yes"; + near_ric_ip_addr = "192.168.71.21"; + near_ric_port = 36421; + sm_dir = "/usr/local/lib/flexric/"; +} + gNBs = ( { @@ -174,6 +181,7 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; + min_grant_prb = 10; } ); diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 42f8184532..2f127f3419 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -94,7 +94,7 @@ services: retries: 5 oai-gnb: - image: nakaolab:oct1 + image: nakaolab:oct29 container_name: oai-gnb cap_drop: - ALL @@ -105,6 +105,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: + # - ../../conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml healthcheck: test: /bin/bash -c "pgrep nr-softmodem" @@ -115,7 +116,7 @@ services: retries: 5 oai-flexric: - image: nakaolab:oct1 + image: nakaolab:oct29 container_name: oai-flexric command: ["-c", "stdbuf -o0 /oai-ran/openair2/E2AP/flexric/build/examples/ric/nearRT-RIC"] networks: @@ -130,8 +131,14 @@ services: timeout: 5s xapp-chatgpt: - image: nakaolab:oct1 - command: ["-c", "XAPP_DURATION=20 stdbuf -oL /oai-ran/openair2/E2AP/flexric/build/examples/xApp/c/monitor/xapp_chatgpt"] + image: nakaolab:oct29 + command: ["-c", "XAPP_DURATION=3600 /oai-ran/openair2/E2AP/flexric/build/examples/xApp/c/monitor/xapp_chatgpt"] + # command: ["-lc","ulimit -c unlimited; export XAPP_DURATION=3600; gdb -q -batch \ + # -ex 'set pagination off' \ + # -ex run \ + # -ex 'bt full' \ + # -ex 'thread apply all bt full' \ + # --args /oai-ran/openair2/E2AP/flexric/build/examples/xApp/c/monitor/xapp_chatgpt"] container_name: xapp-chatgpt environment: - TZ=Asia/Tokyo @@ -147,7 +154,7 @@ services: timeout: 5s oai-nr-ue1: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue1 cap_drop: @@ -155,8 +162,6 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping - # environment: - # USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -175,7 +180,7 @@ services: retries: 5 oai-nr-ue2: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue2 cap_drop: @@ -201,7 +206,7 @@ services: retries: 5 oai-nr-ue3: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue3 cap_drop: @@ -227,7 +232,7 @@ services: retries: 5 oai-nr-ue4: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001103 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue4 cap_drop: @@ -253,7 +258,7 @@ services: retries: 5 oai-nr-ue5: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001104 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue5 cap_drop: @@ -279,7 +284,7 @@ services: retries: 5 oai-nr-ue6: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001105 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue6 cap_drop: @@ -305,7 +310,7 @@ services: retries: 5 oai-nr-ue7: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001106 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue7 cap_drop: @@ -331,7 +336,7 @@ services: retries: 5 oai-nr-ue8: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001107 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue8 cap_drop: @@ -357,7 +362,7 @@ services: retries: 5 oai-nr-ue9: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001108 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue9 cap_drop: @@ -365,12 +370,6 @@ services: cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping -<<<<<<< HEAD -======= - - SYS_NICE - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time ->>>>>>> 2025.w42 depends_on: - oai-gnb networks: @@ -389,7 +388,7 @@ services: retries: 5 oai-nr-ue10: - image: nakaolab:oct1 + image: nakaolab:oct29 command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] container_name: oai-nr-ue10 cap_drop: @@ -411,25 +410,36 @@ services: interval: 10s timeout: 5s retries: 5 - - # iperf: - # image: phlak/iperf - # container_name: iperf + + # iperf3: + # image: networkstatic/iperf3:latest + # container_name: iperf3 + # command: ["-c 'for p in $(seq 5201 5210); do iperf3 -s -p $$p & done;'"] # ports: - # - "5201:5201/tcp" - # - "5201:5201/udp" + # - "5201-5210:5201-5210/tcp" + # - "5201-5210:5201-5210/udp" # networks: - # traffic_net: - # ipv4_address: 192.168.72.130 + # public_net: + # ipv4_address: 192.168.71.130 # restart: unless-stopped - - iperf: + + iperf_udp: image: mlabbe/iperf - container_name: iperf - command: ["-s", "-p 5201"] + container_name: iperf_udp + command: ["-u -s -p 5201"] ports: - - "5201:5201/tcp" - "5201:5201/udp" + networks: + public_net: + ipv4_address: 192.168.71.129 + restart: unless-stopped + + iperf_tcp: + image: mlabbe/iperf + container_name: iperf_tcp + command: ["-s -p 5202"] + ports: + - "5202:5202/tcp" networks: public_net: ipv4_address: 192.168.71.130 diff --git a/ci-scripts/yaml_files/5g_rfsimulator/exp.sh b/ci-scripts/yaml_files/5g_rfsimulator/exp.sh index baee1a0127..22093a08c0 100755 --- a/ci-scripts/yaml_files/5g_rfsimulator/exp.sh +++ b/ci-scripts/yaml_files/5g_rfsimulator/exp.sh @@ -1,28 +1,21 @@ #!/bin/bash -# Examples: -# ./exp-35.sh -# UE_MIN=2 UE_MAX=12 UE_PEAK_HOUR=14 UE_NOISE_FRAC=0.15 ./exp-35.sh -# TEST_UE=oai-nr-ue1 TEST_PROFILE=browsing TEST_DURATION_SEC=120 ./exp-35.sh set -euo pipefail +# --- UE profile map (index 0..10). 0-index kept for convenience --- +# Initialize with "0" to denote no profile chosen. +declare -a UE_PROFILE_MAP +for i in {0..10}; do UE_PROFILE_MAP[$i]=0; done -# ---------------------------[ Random Burst Mode ]---------------------------- +# ---------------------------[ Random / diurnal Mode ]---------------------------- # UE scaler mode: 'random' (rapid random targets) or 'diurnal' (legacy cosine) UE_SCALER_MODE="${UE_SCALER_MODE:-random}" # Interval (sec) for scaler ticks UE_SCALER_INTERVAL_SEC="${UE_SCALER_INTERVAL_SEC:-30}" -# Rapid/random system-level bursts: every few minutes trigger a short, global burst -# that nudges all UEs to start/extend a session at once. UE-side script watches -# /tmp/system_burst and reacts (see traffic_runner --profile random). -RANDOM_BURST_MODE="${RANDOM_BURST_MODE:-1}" # 1=enabled, 0=disabled -BURST_MIN_GAP_SEC="${BURST_MIN_GAP_SEC:-180}" # 3 minutes -BURST_MAX_GAP_SEC="${BURST_MAX_GAP_SEC:-600}" # 10 minutes -BURST_MARK_FILE="${BURST_MARK_FILE:-/tmp/system_burst}" # -------------------------------[ Config ]------------------------------------ -ARTIFACT_DIR="/home/nakaolab-go/OAI/research-main/artifacts/" +ARTIFACT_DIR="/media/nakaolab-go/2nd/artifacts" mkdir -p "$ARTIFACT_DIR" POWER_LOG_FILE="${POWER_LOG_FILE:-$ARTIFACT_DIR/power_usage.csv}" @@ -30,19 +23,19 @@ CPU_PROXY_LOG_FILE="${CPU_PROXY_LOG_FILE:-$ARTIFACT_DIR/cpu_proxy.csv}" RRC_SINCE_STATE="${RRC_SINCE_STATE:-$ARTIFACT_DIR/.rrc_since}" # xApp (mac stats) container + path inside container -MAC_STATS_CONTAINER="${MAC_STATS_CONTAINER:-xapp-chatgpt}" +STATS_CONTAINER="${STATS_CONTAINER:-xapp-chatgpt}" MAC_STATS_FILE_IN_CONTAINER="${MAC_STATS_FILE_IN_CONTAINER:-/tmp/mac_stats.log}" +PDCP_STATS_FILE_IN_CONTAINER="${PDCP_STATS_FILE_IN_CONTAINER:-/tmp/pdcp_stats.log}" # Intervals (seconds) RRC_LOG_INTERVAL_SEC="${RRC_LOG_INTERVAL_SEC:-10}" POWER_LOG_INTERVAL_SEC="${POWER_LOG_INTERVAL_SEC:-5}" CPU_PROXY_INTERVAL_SEC="${CPU_PROXY_INTERVAL_SEC:-5}" -UE_SCALER_INTERVAL_SEC="${UE_SCALER_INTERVAL_SEC:-60}" # Docker compose helper DC_BIN=(docker compose) dc() { command "${DC_BIN[@]}" "$@"; } -dc down -v +dc down -v --remove-orphans # Service names (override if your compose uses different ones) AMF_SERVICE="${AMF_SERVICE:-oai-amf}" @@ -54,14 +47,14 @@ XAPP_SERVICE="${XAPP_SERVICE:-xapp-chatgpt}" UE_NAME_REGEX="${UE_NAME_REGEX:-^oai-nr-ue}" # Test controls -TEST_UE="${TEST_UE:-}" # e.g. oai-nr-ue1 +TEST_MODE="${TEST_MODE:-0}" # 1=manual profiles allowed (TEST_* honored); 0=auto +TEST_UES="${TEST_UES:-}" TEST_PROFILES="${TEST_PROFILES:-}" # profile name TEST_DURATION_SEC="${TEST_DURATION_SEC:-0}" # 0 = run indefinitely # Diurnal scaling controls (normal mode only; ignored if TEST_UE is set) UE_MIN="${UE_MIN:-1}" # Minimum number of UEs to keep connected -# UE_MAX="${UE_MAX:-}" # Max UEs; default = total UEs in compose -UE_MAX=10 +UE_MAX="${UE_MAX:-10}" UE_PEAK_HOUR="${UE_PEAK_HOUR:-17}" # Local hour with peak load (0..23) UE_NOISE_FRAC="${UE_NOISE_FRAC:-0.15}" # ±fractional noise applied to target @@ -74,6 +67,7 @@ declare -A PWR_MW_PROFILE=( [voip]=520 # steady uplink/downlink small packets [video]=850 # continuous DL; 720–1080p [gaming]=950 # bursty DL + UL keepalives + [boring]=500 # for single PRB testing [bulk_download]=1100 # sustained UL/DL at MCS ceiling ) @@ -101,14 +95,8 @@ get_core_services() { } get_running_ues() { - # Running UEs by service name (include TEST_UE name if custom) - if [[ -n "${TEST_UE:-}" ]]; then - dc ps --services --filter "status=running" \ - | grep -E "${UE_NAME_REGEX}|^${TEST_UE}$" || true - else - dc ps --services --filter "status=running" \ - | grep -E "${UE_NAME_REGEX}" || true - fi + dc ps --services --filter "status=running" \ + | grep -E "${UE_NAME_REGEX}" || true } # -------------------------[ Readiness helpers ]------------------------------- @@ -153,7 +141,6 @@ wait_log() { local start; start="$(ts_now)" while :; do if dc logs "$svc" --since=2m 2>&1 | grep -Eiq -- "$pat"; then - log "wait_log: detected '$pat' in '$svc'." return 0 fi if (( $(ts_now) - start > timeout )); then @@ -174,15 +161,14 @@ get_container_ip() { start_services_list() { [[ $# -eq 0 ]] && return 0 - dc up -d "$@" + dc up -d "$@" >/dev/null 2>&1 } start_ue_list() { [[ $# -eq 0 ]] && return 0 for svc in "$@"; do log "Starting: $svc" - dc up -d "$svc" - sleep 10 + dc up -d "$svc" >/dev/null 2>&1 done } @@ -200,11 +186,28 @@ start_in_stages() { wait_healthy "${AMF_SERVICE}" 15 wait_healthy "${UPF_SERVICE}" 15 exec_safe "${UPF_SERVICE}" 'bash -lc " - GW=192.168.72.129 - DEV=\$(ip -4 route get \$GW 2>/dev/null | awk '\''/ dev /{for(i=1;i<=NF;i++) if(\$i==\"dev\"){print \$(i+1); exit}}'\''); DEV=\${DEV:-eth0} - ip -4 route replace \$GW/32 dev \$DEV - ip -4 route replace default via \$GW dev \$DEV onlink - "' + set -e + sysctl -w net.ipv4.ip_forward=1 + sysctl -w net.ipv4.conf.all.rp_filter=2 + sysctl -w net.ipv4.conf.eth0.rp_filter=2 + sysctl -w net.ipv4.conf.eth1.rp_filter=2 + sysctl -w net.ipv4.conf.tun0.rp_filter=2 + + ip rule add pref 100 iif tun0 to 192.168.71.0/24 lookup 201 || true + ip route replace 192.168.71.0/24 dev eth0 table 201 + + ip rule add pref 200 iif tun0 lookup 200 || true + ip route replace 12.1.1.0/24 dev tun0 table 200 + ip route replace default via 192.168.72.129 dev eth1 table 200 + + # UE -> DN (192.168.72.128/26) via eth1 + iptables -t nat -C POSTROUTING -s 12.1.1.0/24 -d 192.168.72.128/26 -o eth1 -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s 12.1.1.0/24 -d 192.168.72.128/26 -o eth1 -j MASQUERADE + + # UE -> 192.168.71.0/24 via eth0 + iptables -t nat -C POSTROUTING -s 12.1.1.0/24 -d 192.168.71.0/24 -o eth0 -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s 12.1.1.0/24 -d 192.168.71.0/24 -o eth0 -j MASQUERADE + "' wait_healthy oai-flexric 15 # 2) gNB @@ -272,17 +275,6 @@ calc_target_ue_count() { }' } -wait_oaitun() { - local ue="$1" timeout="${2:-20}" - for ((i=1; i<=timeout; i++)); do - if exec_safe "$ue" 'ip link show oaitun_ue1 >/dev/null 2>&1'; then - return 0 - fi - sleep 1 - done - return 1 -} - ensure_ue_count() { local target="$1" @@ -312,7 +304,12 @@ ensure_ue_count() { if (( cur < target )); then local need=$(( target - cur )) log "UE scaler: need +${need} UEs (cur=${cur}, target=${target})." - # Choose candidates (prefer random if shuf available) + + if (( ${#not_running[@]} == 0 )); then + log "UE scaler: no available UEs to start." + return 0 + fi + local to_start=() if command -v shuf >/dev/null 2>&1; then mapfile -t to_start < <(printf '%s\n' "${not_running[@]}" | shuf -n "$need" || true) @@ -321,16 +318,15 @@ ensure_ue_count() { fi if (( ${#to_start[@]} > 0 )); then start_ue_list "${to_start[@]}" - # kick traffic + (best-effort) readiness for ue in "${to_start[@]}"; do - if wait_oaitun "$ue" 20; then + if wait_log "$ue" "oaitun_ue1 successfully configured"; then exec_safe "$ue" 'ip route replace default dev oaitun_ue1' - run_traffic_profile "$ue" "random" "0" + # run_traffic_profile "$ue" "$(choose_random_profile)" "0" + run_traffic_profile "$ue" "boring" else - dc restart "$ue" - to_start+="$ue" + dc rm -fv "$ue" >/dev/null 2>&1 fi - done + done fi return 0 fi @@ -346,46 +342,57 @@ ensure_ue_count() { fi for ue in "${to_stop[@]}"; do log "Stopping UE ${ue}" - dc stop "$ue" || true - dc rm -f "$ue" || true + dc stop "$ue" >/dev/null 2>&1 & done + wait + for ue in "${to_stop[@]}"; do + dc rm -fv "$ue" >/dev/null 2>&1 & + done + wait } # --------------------------[ UE traffic helpers ]----------------------------- -pick_profile() { - local r=$((RANDOM % 100)) - if (( r < 30 )); then echo browsing # 45% - elif (( r < 70 )); then echo video # 35% - elif (( r < 90 )); then echo bulk_download # 12% - else echo iot_chatty # 8% - fi +PROFILES=(boring browsing video bulk_download voip iot_chatty gaming) +choose_random_profile() { + if command -v shuf >/dev/null 2>&1; then + shuf -e "${PROFILES[@]}" -n1 + else + idx=$(( RANDOM % ${#PROFILES[@]} )) + echo "${PROFILES[$idx]}" + fi } run_traffic_profile() { - local ue="$1" profile="$2" duration="${3:-0}" - exec_safe "$ue" "echo 'traffic runner ready for $ue. profile: $profile'" + local ue="$1" profile="$2" + + # Record selected profile for this UE into UE_PROFILE_MAP + if [[ "$ue" =~ ([0-9]+)$ ]]; then + __idx="${BASH_REMATCH[1]}" + UE_PROFILE_MAP[$__idx]="$profile" + fi + dc cp /home/nakaolab-go/OAI/openairinterface5g/tools/scripts/traffic_runner.sh "$ue":/tmp/traffic_runner.sh >/dev/null 2>&1 exec_safe "$ue" "bash -lc ' - if [ ! -f /tmp/traffic_profile.lock ]; then - prof=\$1; dur=\$2 - /usr/local/bin/traffic_runner --profile \$prof --duration \$dur >/tmp/traffic_runner.log 2>&1 & - printf \"%s %s\n\" \"\$prof\" \"\$dur\" > /tmp/traffic_profile.lock - fi - ' -- $profile $duration" + prof=\$1; + /tmp/traffic_runner.sh --profile \$prof & + ' -- $profile" } # --------------------------[ RRC / MAC scraping ]----------------------------- -rotate_mac_capture() { +rotate_stats_capture() { local tag="${1:-}" [[ -z "$tag" ]] && tag="$(ts_tag)" - if dc ps --services --filter "status=running" | grep -q "^${MAC_STATS_CONTAINER}$"; then - log "Rotating mac_stats from ${MAC_STATS_CONTAINER}" - dc cp "${MAC_STATS_CONTAINER}:${MAC_STATS_FILE_IN_CONTAINER}" \ + if dc ps --services --filter "status=running" | grep -q "^${STATS_CONTAINER}$"; then + log "Rotating stats from ${STATS_CONTAINER}" + dc cp "${STATS_CONTAINER}:${MAC_STATS_FILE_IN_CONTAINER}" \ "${ARTIFACT_DIR}/mac_stats_${tag}.log" || true - exec_safe "$MAC_STATS_CONTAINER" "> '${MAC_STATS_FILE_IN_CONTAINER}'" + dc cp "${STATS_CONTAINER}:${PDCP_STATS_FILE_IN_CONTAINER}" \ + "${ARTIFACT_DIR}/pdcp_stats_${tag}.log" || true + # exec_safe "$STATS_CONTAINER" "> '${MAC_STATS_FILE_IN_CONTAINER}'" + # exec_safe "$STATS_CONTAINER" "> '${PDCP_STATS_FILE_IN_CONTAINER}'" else - log "mac_stats container ${MAC_STATS_CONTAINER} not running; skipping rotate" + log "stats container ${STATS_CONTAINER} not running; skipping rotate" fi } @@ -400,10 +407,10 @@ _since_arg_from_file() { fi } -dump_gnb_rrc_logs() { +dump_gnb_logs() { local tag="$1" - dc logs "${GNB_SERVICE}" 2>&1 | grep -E "NR_RRC" \ - > "${ARTIFACT_DIR}/gnb_rrc_${tag}.log" || true + dc logs "${GNB_SERVICE}" 2>&1 | grep -E "NR_RRC" > "${ARTIFACT_DIR}/gnb_rrc_${tag}.log" + dc logs "${GNB_SERVICE}" 2>&1 | grep -E "\[NR_MAC\] I Frame\.Slot|MAC:" > "${ARTIFACT_DIR}/gnb_${tag}.log" } # -----------------------------[ Power / CPU ]--------------------------------- @@ -428,14 +435,16 @@ sample_power_once() { while IFS= read -r ue; do [[ -z "$ue" ]] && continue - local lock - lock="$(exec_safe "$ue" 'bash -lc "cat /tmp/traffic_profile.lock 2>/dev/null || true"')" + # Determine profile without container lock by consulting UE_PROFILE_MAP local picked_profile picked_duration - picked_profile="$(awk "{print \$1}" <<<"$lock")" - picked_duration="$(awk "{print \$2}" <<<"$lock")" + if [[ "$ue" =~ ([0-9]+)$ ]]; then + __idx="${BASH_REMATCH[1]}" + picked_profile="${UE_PROFILE_MAP[$__idx]}" + fi + picked_duration="" if [[ -z "$picked_profile" ]]; then - picked_profile="${TEST_PROFILE:-idle}" + if [[ "${TEST_MODE}" -eq 1 ]]; then picked_profile="${TEST_PROFILE}"; else picked_profile="idle"; fi fi while [[ "$picked_profile" == -* ]]; do @@ -499,8 +508,8 @@ rotate_csv_if_any() { finalize_and_rotate_artifacts() { local tag; tag="$(ts_tag)" - rotate_mac_capture "$tag" || true - dump_gnb_rrc_logs "$tag" || true + rotate_stats_capture "$tag" || true + dump_gnb_logs "$tag" || true rotate_csv_if_any "$POWER_LOG_FILE" "power_usage" "$tag" rotate_csv_if_any "$CPU_PROXY_LOG_FILE" "cpu_proxy" "$tag" } @@ -530,40 +539,40 @@ cleanup() { while IFS= read -r ue; do [[ -z "$ue" ]] && continue dc stop "$ue" || true - dc rm -f "$ue" || true + dc rm -fv "$ue" >/dev/null 2>&1 & done < <(dc ps --services | grep -E "${UE_NAME_REGEX}" || true) } # ---------------------------------[ Main ]------------------------------------ - -trigger_system_burst() { - mapfile -t running < <(get_running_ues) - if (( ${#running[@]} == 0 )); then - return 0 - fi - log "Triggering system-wide burst for ${#running[@]} UE(s)…" - for ue in "${running[@]}"; do - exec_safe "$ue" "bash -lc 'date +%s > ${BURST_MARK_FILE}'" || true - done -} - random_target_ue_count() { - local total_ues="${UE_MAX:-}" - if [[ -z "$total_ues" ]]; then - total_ues="$(get_all_ue_services | wc -l | tr -d ' ')" + local cur="$(get_running_ues | wc -l | tr -d ' ')" + bias=$((RANDOM % 100)) # 0–99 + if (( cur <= UE_MIN )); then + if (( bias < 70 )); then + delta=$(( (RANDOM % 3) + 1 )) # +1..+3 + else + delta=$(( RANDOM % 7 - 3 )) # -3..+3 + fi + elif (( cur >= UE_MAX )); then + if (( bias < 70 )); then + delta=$(( -((RANDOM % 3) + 1) )) # -1..-3 + else + delta=$(( RANDOM % 7 - 3 )) # -3..+3 + fi + else # normal + delta=$(( RANDOM % 7 - 3 )) # -3..+3 fi - local min="${UE_MIN:-1}" - if (( total_ues < min )); then total_ues="$min"; fi - local val - if command -v shuf >/dev/null 2>&1; then - val="$(shuf -i "${min}-${total_ues}" -n 1)" - else - local span=$(( total_ues - min + 1 )) - val=$(( min + (RANDOM % span) )) + local target=$((cur + delta)) + if (( target < UE_MIN )); then + target="${UE_MIN}" + elif (( target > UE_MAX )); then + target="${UE_MAX}" fi - echo "$val" + + echo "$target" } + main() { trap on_interrupt INT TERM @@ -572,24 +581,18 @@ main() { # Staged bring-up with readiness checks for both normal and TEST modes start_in_stages - # Initialize next system-burst time - if (( RANDOM_BURST_MODE )); then - local next_burst_ts - next_burst_ts="$(($(ts_now) + BURST_MIN_GAP_SEC + RANDOM % (BURST_MAX_GAP_SEC - BURST_MIN_GAP_SEC + 1)))" - fi - # Kick off traffic workload(s) - if [[ -n "${TEST_UE:-}" ]]; then + if [[ "${TEST_MODE}" -eq 1 ]]; then log "TEST UE(S) ENABLED" # Support multiple UEs (comma/space/newline separated) - read -r -a _ue_list <<< "$(tr ',\n' ' ' <<< "${TEST_UE}")" + read -r -a _ue_list <<< "$(tr ',\n' ' ' <<< "${TEST_UES}")" read -r -a _ue_profiles <<< "$(tr ',\n' ' ' <<< "${TEST_PROFILES}")" start_ue_list "${_ue_list[@]}" for i in "${!_ue_list[@]}"; do ue="${_ue_list[$i]}" prof="${_ue_profiles[$i]}" [[ -z "$ue" ]] && continue - if wait_oaitun "$ue" 20; then + if wait_log "$ue" "oaitun_ue1 successfully configured"; then exec_safe "$ue" "ip route replace default dev oaitun_ue1" run_traffic_profile "$ue" "$prof" else @@ -599,7 +602,7 @@ main() { fi # Optional finite duration for TEST mode - if [[ -n "${TEST_UE:-}" && "${TEST_DURATION_SEC:-0}" -gt 0 ]]; then + if [[ "${TEST_MODE}" -eq 1 && -n "${TEST_UE:-}" && "${TEST_DURATION_SEC:-0}" -gt 0 ]]; then RUN_STOP_TS=$(( $(ts_now) + TEST_DURATION_SEC )) fi @@ -612,14 +615,6 @@ main() { log "Entering main loop (sampling + diurnal scaler)…" while :; do local now; now="$(ts_now)" - # System-wide random burst scheduler - if (( RANDOM_BURST_MODE )); then - if (( now >= next_burst_ts )); then - trigger_system_burst || true - next_burst_ts="$(( now + BURST_MIN_GAP_SEC + RANDOM % (BURST_MAX_GAP_SEC - BURST_MIN_GAP_SEC + 1) ))" - fi - fi - if (( now - last_power >= POWER_LOG_INTERVAL_SEC )); then sample_power_once || true @@ -632,9 +627,14 @@ main() { fi # Re-evaluate diurnal target (normal mode only) - if [[ -z "${TEST_UE:-}" ]] && (( now - last_scale >= UE_SCALER_INTERVAL_SEC )); then - local target; if [[ "${UE_SCALER_MODE}" == "diurnal" ]]; then target="$(calc_target_ue_count)"; else target="$(random_target_ue_count)"; fi - log "Diurnal scaler tick: target = ${target}" + if [[ "${TEST_MODE}" -eq 0 ]] && (( now - last_scale >= UE_SCALER_INTERVAL_SEC )); then + local target; + if [[ "${UE_SCALER_MODE}" == "diurnal" ]]; then + target="$(calc_target_ue_count)"; + else + target="$(random_target_ue_count)"; + fi + log "Scaler tick: target = ${target}" ensure_ue_count "$target" last_scale="$now" fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index eeffc9d4f1..9702470ffa 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -278,7 +278,7 @@ check_install_usrp_uhd_driver(){ x=$((x + 1)) done $SUDO apt-get update - $SUDO apt-get -y install python-tk $boost_libs_ubuntu libusb-1.0-0-dev + $SUDO apt-get -y install python3-tk $boost_libs_ubuntu libusb-1.0-0-dev case "$(get_distribution_release)" in "ubuntu20.04" | "ubuntu22.04") $SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host diff --git a/docker/Dockerfile.base.ubuntu b/docker/Dockerfile.base.ubuntu index e0fbacf09e..7d2438f28c 100644 --- a/docker/Dockerfile.base.ubuntu +++ b/docker/Dockerfile.base.ubuntu @@ -20,8 +20,6 @@ RUN apt-get update && \ bison \ flex \ m4 \ - # python3-pip for conf template generation - python3-pip \ wget && \ # --break-system-packages allows externally managed environment in pip pip3 install --ignore-installed pyyaml --break-system-packages diff --git a/docker/Dockerfile.nakaolab.oct1 b/docker/Dockerfile.nakaolab.oct1 deleted file mode 100644 index 3a525b008b..0000000000 --- a/docker/Dockerfile.nakaolab.oct1 +++ /dev/null @@ -1,66 +0,0 @@ -FROM ran-base:latest AS ran-build -ARG BUILD_OPTION - -ARG E2AP_VERSION=E2AP_V2 -ARG KPM_VERSION=KPM_V2_03 - -RUN rm -Rf /oai-ran -WORKDIR /oai-ran -COPY . . - -# build all targets so final targets can be created afterwards -RUN /bin/sh oaienv && \ - cd cmake_targets && \ - mkdir -p log && \ - ./build_oai -c --ninja \ - --gNB --RU --nrUE \ - --build-lib "telnetsrv enbscope uescope nrscope" \ - -w USRP -t Ethernet \ - --build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \ - --noavx512 \ - --build-tool-opt -k10 \ - --cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \ - echo "---- ldd on executables ----" && \ - ldd ran_build/build/*softmodem* ran_build/build/nr-cuup ran_build/build/oairu && \ - echo "---- ldd on shared libraries ----" && \ - ldd ran_build/build/*.so - -RUN rm -rf openair2/E2AP/flexric/build && \ - mkdir -p openair2/E2AP/flexric/build && \ - cd openair2/E2AP/flexric/build && \ - cmake -DCMAKE_BUILD_TYPE=Release \ - -DKPM_VERSION=KPM_V2_03 \ - -DE2AP_VERSION=E2AP_V2 \ - -DCMAKE_C_COMPILER=gcc-12 \ - -DCMAKE_CXX_COMPILER=g++-12 .. && \ - make -j8 && make install - -RUN set -eux; \ - apt-get update; \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - ca-certificates curl wget iproute2 iputils-ping dnsutils jq \ - iperf iperf3 ffmpeg \ - nghttp2-client || true; \ - # Ubuntu vs Debian name differences (fallback for nghttp2 client tools) - if ! command -v h2load >/dev/null 2>&1; then \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends nghttp2 || true; \ - fi; \ - # Try to install sipp from apt; if unavailable, build from source - if apt-cache show sipp >/dev/null 2>&1; then \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends sipp; \ - else \ - echo "sipp not in apt, building from source..."; \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - build-essential cmake git libncurses5-dev libpcap-dev libssl-dev libpcre3-dev; \ - git clone --depth=1 https://github.com/SIPp/sipp.git /tmp/sipp; \ - cd /tmp/sipp; cmake -DENABLE_SSL=1 -DENABLE_PCAP=1 -DCMAKE_BUILD_TYPE=Release .; \ - make -j"$(nproc)"; make install; strip /usr/local/bin/sipp || true; \ - rm -rf /tmp/sipp; \ - fi; \ - rm -rf /var/lib/apt/lists/* - -# Traffic runner -COPY tools/scripts/traffic_runner.sh /usr/local/bin/traffic_runner -RUN chmod +x /usr/local/bin/traffic_runner - -ENTRYPOINT ["/bin/bash"] \ No newline at end of file diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 5ec7522492..d86efb6160 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2157,8 +2157,8 @@ static int pf_ul(gNB_MAC_INST *nrmac, rbStart++; /* if it's for inactivity, min_grant_prb is enough, otherwise check what * would be the maximum */ - /* uint16_t max_rbSize = iterator->sched_inactive ? min_rb : bi.bwpSize; */ - uint16_t max_rbSize = 10; + uint16_t max_rbSize = iterator->sched_inactive ? min_rb : bi.bwpSize; + /* uint16_t max_rbSize = 10; */ uint16_t available_rb = 1; while (rbStart + available_rb < bi.bwpSize && !(rballoc_mask[rbStart + bi.bwpStart + available_rb] & slbitmap) && available_rb < max_rbSize) available_rb++; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index b1f87a7a05..3281b76de6 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -1835,10 +1835,11 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, if (entity->sdu_rejected != 0 && entity->t_current > entity->t_log_buffer_full + 1000) { LOG_E(RLC, "%d SDU rejected, SDU buffer full\n", entity->sdu_rejected); + /* LOG_E(RLC, "tx_size: %d t_current: %lu max: %d\n" , entity->tx_size + size, entity->t_current, entity->tx_maxsize); */ entity->sdu_rejected = 0; entity->t_log_buffer_full = entity->t_current; } - + /* LOG_E(RLC, "tx_size: %d max: %d\n" , entity->tx_size + size, entity->tx_maxsize); */ if (entity->tx_size + size > entity->tx_maxsize) { entity->sdu_rejected++; entity->common.stats.txpdu_dd_pkts++; diff --git a/tools/scripts/traffic_runner.sh b/tools/scripts/traffic_runner.sh old mode 100644 new mode 100755 index c18c18f562..44c065053e --- a/tools/scripts/traffic_runner.sh +++ b/tools/scripts/traffic_runner.sh @@ -1,233 +1,98 @@ +#!/usr/bin/env bash #!/bin/bash -# Iperf-exclusive traffic generator for OAI UE containers. -# Profiles: browsing, video, bulk_download, voip, iot_chatty, gaming, idle -# Usage: -# traffic_runner --profile browsing --duration 0 --iperf-server 10.0.0.1:5201 -# +# Continuous traffic generator for OAI UE containers (no intervals, runs virtually forever). +# Usage examples: +# ./traffic_runner.sh --profile boring +# PROFILE=bulk_download ./traffic_runner.sh + set -euo pipefail -# Clear exp.sh lock on exit so sessions can restart later -trap 'rm -f /tmp/traffic_profile.lock' EXIT +PROFILE="${PROFILE:-}" -DEFAULT_IPERF_PORT="${DEFAULT_IPERF_PORT:-5201}" -TRAFFIC_NET_GATEWAY="${TRAFFIC_NET_GATEWAY:-192.168.71.130}" +# Fixed server coordinates +IPERF_HOST_UDP="192.168.71.129" +IPERF_HOST_TCP="192.168.71.130" +IPERF_PORT_UDP=5201 +IPERF_PORT_TCP=5202 +OAITUN_IP="$(ip -o -4 addr show dev oaitun_ue1 | awk '{print $4}' | cut -d/ -f1)" -if [[ -z "${IPERF_SERVER:-}" ]]; then - # Candidate hostnames (Docker DNS on the same network) then the gateway IP - IPERF_HOST_CANDIDATES=${IPERF_HOST_CANDIDATES:-"iperf iperf3 iperf-server ${TRAFFIC_NET_GATEWAY}"} - for h in $IPERF_HOST_CANDIDATES; do - if getent hosts "$h" >/dev/null 2>&1; then - IPERF_SERVER="${h}:${DEFAULT_IPERF_PORT}" - break - fi - # Accept numeric IPv4 even if DNS not present - if [[ "$h" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then - IPERF_SERVER="${h}:${DEFAULT_IPERF_PORT}" - break - fi - done +# Very long duration to approximate "forever" +LONG_T="${LONG_T:-31536000}" # 1 year in seconds + +# -------------- args -------------- +if [[ $# -gt 0 ]]; then + case "$1" in + --profile=*) PROFILE="${1#--profile=}"; shift ;; + --profile) PROFILE="${2-}"; shift 2 ;; + -p=*) PROFILE="${1#-p=}"; shift ;; + -p) PROFILE="${2-}"; shift 2 ;; + -*) ;; # ignore other flags + *) PROFILE="$1"; shift ;; + esac fi -# Final check -[[ -n "${IPERF_SERVER:-}" ]] || die "No iperf server found. Set --iperf-server or connect a server to rfsim5g-oai-traffic-net." -IPERF_HOST="${IPERF_SERVER%:*}" -IPERF_PORT="${IPERF_SERVER#*:}" -[[ "$IPERF_PORT" =~ ^[0-9]+$ ]] || die "Invalid iperf port in $IPERF_SERVER" +[[ -n "$PROFILE" ]] || { echo "ERROR: --profile is required" >&2; exit 2; } -PROFILE="" -DURATION=0 -LOG_FILE="/tmp/traffic_runner.log" +iperf_tcp_dl_forever() { ( nohup iperf -c "$IPERF_HOST_TCP" -B "$OAITUN_IP" -p "$IPERF_PORT_TCP" -R -t "$LONG_T" >/dev/null 2>&1 & ); } +iperf_tcp_ul_forever() { ( nohup iperf -c "$IPERF_HOST_TCP" -B "$OAITUN_IP" -p "$IPERF_PORT_TCP" -t "$LONG_T" >/dev/null 2>&1 & ); } +iperf_udp_dl_forever() { ( nohup iperf -u -c "$IPERF_HOST_UDP" -B "$OAITUN_IP" -p "$IPERF_PORT_UDP" -R -b $1 -t "$LONG_T" >/dev/null 2>&1 & ); } +# iperf_udp_dl_forever() { iperf -u -c "$IPERF_HOST_UDP" -B "$OAITUN_IP" -p "$IPERF_PORT_UDP" -R -b $1 -t "$LONG_T"; } +iperf_udp_ul_forever() { ( nohup iperf -u -c "$IPERF_HOST_UDP" -B "$OAITUN_IP" -p "$IPERF_PORT_UDP" -b $1 -t "$LONG_T" >/dev/null 2>&1 & ); } -log() { printf '[%(%Y-%m-%dT%H:%M:%S%z)T] %s\n' -1 "$*" | tee -a "$LOG_FILE" >&2; } -die() { log "ERROR: $*"; exit 2; } - -# Parse args -while [[ $# -gt 0 ]]; do - case "$1" in - --profile) PROFILE="$2"; shift 2;; - --duration) DURATION="$2"; shift 2;; - --iperf-server) IPERF_SERVER="$2"; shift 2;; - --help|-h) cat < [--duration ] [--iperf-server host:port] -Profiles: browsing, video, bulk_download, voip, iot_chatty, gaming, idle -If duration is 0 or omitted, run indefinitely. -EOF - exit 0;; - *) die "Unknown arg: $1";; - esac -done - -[[ -n "$PROFILE" ]] || die "--profile is required" -[[ -n "$IPERF_SERVER" ]] || die "--iperf-server or IPERF_SERVER env is required (e.g., 192.168.0.2:5201)" - -IPERF_HOST="${IPERF_SERVER%:*}" -IPERF_PORT="${IPERF_SERVER#*:}" -[[ "$IPERF_PORT" =~ ^[0-9]+$ ]] || die "Invalid iperf port in $IPERF_SERVER" - -# Helpers -run_for_duration() { - # $1: command string to eval in a loop - # uses global DURATION - local start now elapsed - start=$(date +%s) - while :; do - now=$(date +%s) - elapsed=$(( now - start )) - if (( DURATION > 0 && elapsed >= DURATION )); then break; fi - eval "$1" - done +# ---------------- profiles ---------------- +do_boring() { + iperf_udp_dl_forever 5M + wait + # iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -u -b 25M -t "$LONG_T" } -# iperf helpers -iperf_tcp_dl() { iperf3 -c "$IPERF_HOST" -p "$IPERF_PORT" -R -t "$1" -J >/dev/null 2>&1 || true; } -iperf_tcp_ul() { iperf3 -c "$IPERF_HOST" -p "$IPERF_PORT" -t "$1" -J >/dev/null 2>&1 || true; } - -iperf_udp_dl() { iperf3 -c "$IPERF_HOST" -p "$IPERF_PORT" -R -u -b "$2" -t "$1" -J >/dev/null 2>&1 || true; } -iperf_udp_ul() { iperf3 -c "$IPERF_HOST" -p "$IPERF_PORT" -u -b "$2" -t "$1" -J >/dev/null 2>&1 || true; } - -# Profiles do_browsing() { - log "Browsing (TCP bursts, short think-time) to $IPERF_SERVER" - run_for_duration ' - dur=$(( 1 + RANDOM % 3 )) # 1-3s burst - iperf_tcp_dl "$dur" - sleep "0.$((100 + RANDOM % 600))" # 0.1-0.7s think - ' + iperf_tcp_dl_forever + iperf_tcp_ul_forever + wait } do_video() { - log "Video (FHD video 5 Mbps sustained) to $IPERF_SERVER" - run_for_duration ' - iperf3 -c "'"$IPERF_HOST"'" -p "'"$IPERF_PORT"'" -R -u -b 5M -t 30 -J >/dev/null 2>&1 - sleep 1 - ' + iperf_udp_dl_forever 6M + wait } do_bulk_download() { - # Heavy TCP downlink with multiple streams - log "Bulk download (TCP DL 8 parallel, long sustained) to $IPERF_SERVER" - run_for_duration ' - iperf3 -c "'"$IPERF_HOST"'" -p "'"$IPERF_PORT"'" -R -P 8 -t 20 -w 1M -J >/dev/null 2>&1 - sleep 1 - ' + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -R -P 8 -w 1M -t "$LONG_T" + wait } do_voip() { - log "VoIP (UDP bi-di ~100–200 kbps) to $IPERF_SERVER" - run_for_duration ' - iperf_udp_ul 5 120K & - iperf_udp_dl 5 120K & + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -R -u -b 80K -t "$LONG_T"; + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -u -b 80K -t "$LONG_T"; wait - sleep 0.5 - ' } do_iot_chatty() { - log "IoT chatty (UDP UL ~50–80 kbps bursts) to $IPERF_SERVER" - run_for_duration ' - iperf_udp_ul 2 60K - sleep $(( 3 + RANDOM % 7 )) - ' + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -R -u -b 40K -t "$LONG_T"; + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -u -b 20K -t "$LONG_T"; + wait } do_gaming() { - log "Gaming (UDP bi-di ~1–3 Mbps bursts) to $IPERF_SERVER" - run_for_duration ' - rate_ul=$(( 1 + RANDOM % 3 ))M - rate_dl=$(( 1 + RANDOM % 3 ))M - iperf_udp_ul 5 "$rate_ul" & - iperf_udp_dl 5 "$rate_dl" & + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -R -u -b 120K -t "$LONG_T"; + iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -u -b 10K -t "$LONG_T"; wait - sleep 0.5 - ' } do_idle() { - log "Idle" - run_for_duration "sleep 2" -} - - - -# ------------- Randomized pattern (bursts of 30s..minutes) ------------------ - -# Defaults can be overridden via env: -# MIN_ACTIVE_SEC / MAX_ACTIVE_SEC — each session duration (default 30..180) -# MIN_IDLE_SEC / MAX_IDLE_SEC — wait between sessions (default 5..60) -# BURST_FILE — path watched for system-wide bursts -# BURST_MAX_AGE_SEC — consider burst file "fresh" within N sec -MIN_ACTIVE_SEC="${MIN_ACTIVE_SEC:-30}" -MAX_ACTIVE_SEC="${MAX_ACTIVE_SEC:-180}" -MIN_IDLE_SEC="${MIN_IDLE_SEC:-5}" -MAX_IDLE_SEC="${MAX_IDLE_SEC:-60}" -BURST_FILE="${BURST_FILE:-/tmp/system_burst}" -BURST_MAX_AGE_SEC="${BURST_MAX_AGE_SEC:-45}" - -_pick_random_profile() { - # Weighted pick to feel realistic; adjust as desired - local r=$((RANDOM % 100)) - if (( r < 40 )); then echo browsing # 40% - elif (( r < 55 )); then echo voip # 15% - elif (( r < 70 )); then echo video # 15% - elif (( r < 85 )); then echo gaming # 15% - else echo bulk_download # 15% - fi -} - -_run_profile_for() { - local name="$1" seconds="$2" - DURATION="$seconds" - case "$name" in - browsing) do_browsing;; - video) do_video;; - bulk_download) do_bulk_download;; - voip) do_voip;; - iot_chatty) do_iot_chatty;; - gaming) do_gaming;; - idle) do_idle;; - *) do_browsing;; - esac -} - -_is_burst_now() { - # return 0 if a fresh burst marker exists - [[ -f "$BURST_FILE" ]] || return 1 - local now mtime age - now=$(date +%s) - mtime=$(stat -c %Y "$BURST_FILE" 2>/dev/null || echo 0) - age=$(( now - mtime )) - (( age >= 0 && age <= BURST_MAX_AGE_SEC )) -} - -do_random() { - log "Random pattern: independent per-UE bursts to $IPERF_SERVER (session: ${MIN_ACTIVE_SEC}-${MAX_ACTIVE_SEC}s; idle: ${MIN_IDLE_SEC}-${MAX_IDLE_SEC}s)" - while :; do - local prof dur idle - prof="$(_pick_random_profile)" - dur=$(( MIN_ACTIVE_SEC + RANDOM % (MAX_ACTIVE_SEC - MIN_ACTIVE_SEC + 1) )) - - if _is_burst_now; then - # If a system burst is signaled, start immediately and slightly extend session - idle=0 - dur=$(( dur + 20 + RANDOM % 40 )) # +20..60s - else - idle=$(( MIN_IDLE_SEC + RANDOM % (MAX_IDLE_SEC - MIN_IDLE_SEC + 1) )) - fi - - log "Random session: profile=${prof} duration=${dur}s (then idle ${idle}s)" - _run_profile_for "$prof" "$dur" || true - sleep "$idle" - done + tail -f /dev/null } +# -------------- dispatch -------------- case "$PROFILE" in - browsing) do_browsing;; - video) do_video;; - bulk_download) do_bulk_download;; - voip) do_voip;; - iot_chatty) do_iot_chatty;; - gaming) do_gaming;; - idle) do_idle;; - random) do_random;; - *) die "Unknown profile: $PROFILE";; + boring) do_boring;; + browsing) do_browsing;; + video) do_video;; + bulk_download) do_bulk_download;; + voip) do_voip;; + iot_chatty) do_iot_chatty;; + gaming) do_gaming;; + idle) do_idle;; + *) echo "Unknown profile: $PROFILE" >&2; exit 1;; esac