#!/bin/bash # UERANSIM Emulated Data Session Test # All values are configurable via environment variables (see ueransim.env) GNB_IP=${GNB_IP:-172.27.0.159} AMF_IP=${AMF_IP:-10.1.150.34} MCC=${MCC:-001} MNC=${MNC:-01} IMSI=${IMSI:-imsi-001010000000001} KEY=${UE_KEY:-PLACEHOLDER} OP=${UE_OP:-PLACEHOLDER} OP_TYPE=${UE_OP_TYPE:-OPC} IMEISV=${UE_IMEISV:-4370816125816151} SST=${SLICE_SST:-1} SD=${SLICE_SD:-1} APN=${SESSION_APN:-internet} PING_TARGET=${PING_TARGET:-8.8.8.8} log() { echo "[$(date '+%H:%M:%S')] $1"; } # Credential check if [ "$KEY" = "PLACEHOLDER" ] || [ "$OP" = "PLACEHOLDER" ]; then log "ERROR: UE credentials not configured." log "Edit /opt/p5g-marvis/config/ueransim.env — set UE_KEY and UE_OP values." exit 2 fi # Generate gNB config cat > /tmp/gnb.yaml << EOF mcc: '${MCC}' mnc: '${MNC}' nci: '0x000000010' idLength: 32 tac: 1 linkIp: ${GNB_IP} ngapIp: ${GNB_IP} gtpIp: ${GNB_IP} amfConfigs: - address: ${AMF_IP} port: 38412 slices: - sst: ${SST} sd: ${SD} ignoreStreamIds: true EOF # Generate UE config cat > /tmp/ue.yaml << EOF supi: '${IMSI}' mcc: '${MCC}' mnc: '${MNC}' key: '${KEY}' op: '${OP}' opType: '${OP_TYPE}' amf: '8000' imei: '356938035643803' imeiSv: '${IMEISV}' gnbSearchList: - ${GNB_IP} uacAic: mps: false mcs: false uacAcc: normalClass: 0 class11: false class12: false class13: false class14: false class15: false sessions: - type: 'IPv4' apn: '${APN}' slice: sst: ${SST} sd: ${SD} configured-nssai: - sst: ${SST} sd: ${SD} default-nssai: - sst: ${SST} sd: ${SD} integrity: IA1: true IA2: true IA3: true ciphering: EA0: true EA1: false EA2: false EA3: false integrityMaxRate: uplink: 'full' downlink: 'full' EOF # Step 1 — Start gNB log "STEP 1/5 — Starting gNB (src: ${GNB_IP}, AMF: ${AMF_IP})" nr-gnb -c /tmp/gnb.yaml > /tmp/gnb.log 2>&1 & GNB_PID=$! # Step 2 — Wait for NGAP connection log "STEP 2/5 — Waiting for NGAP connection to AMF..." connected=0 for i in $(seq 1 20); do if grep -q "NG Setup procedure is successful" /tmp/gnb.log 2>/dev/null; then log " AMF connection established (NGAP OK)" connected=1 break fi if ! kill -0 $GNB_PID 2>/dev/null; then log "ERROR: gNB process terminated unexpectedly" grep -iE "error|failed|refused" /tmp/gnb.log | tail -5 | while IFS= read -r l; do log " gnb: $l"; done exit 1 fi sleep 1 done if [ $connected -eq 0 ]; then log "ERROR: gNB could not reach AMF at ${AMF_IP}:38412 within 20s" tail -5 /tmp/gnb.log | while IFS= read -r l; do log " gnb: $l"; done kill $GNB_PID 2>/dev/null exit 1 fi # Step 3 — Start UE log "STEP 3/5 — Starting UE (${IMSI})" nr-ue -c /tmp/ue.yaml > /tmp/ue.log 2>&1 & UE_PID=$! # Step 4 — Wait for PDU session log "STEP 4/5 — Waiting for PDU session establishment..." pdu=0 for i in $(seq 1 25); do if grep -q "PDU Session establishment is successful" /tmp/ue.log 2>/dev/null; then UE_ADDR=$(grep -oE 'PDU address\[[^]]+\]' /tmp/ue.log | tail -1) log " PDU session established — ${UE_ADDR}" pdu=1 break fi if grep -qiE "Registration failed|Authentication failed|rejected" /tmp/ue.log 2>/dev/null; then log "ERROR: UE authentication/registration failed — check IMSI, UE_KEY, UE_OP in ueransim.env" grep -iE "failed|rejected" /tmp/ue.log | tail -5 | while IFS= read -r l; do log " ue: $l"; done kill $UE_PID $GNB_PID 2>/dev/null exit 1 fi if ! kill -0 $UE_PID 2>/dev/null; then log "ERROR: UE process terminated unexpectedly" tail -5 /tmp/ue.log | while IFS= read -r l; do log " ue: $l"; done kill $GNB_PID 2>/dev/null exit 1 fi sleep 1 done if [ $pdu -eq 0 ]; then log "ERROR: PDU session not established within 25s" tail -10 /tmp/ue.log | while IFS= read -r l; do log " ue: $l"; done kill $UE_PID $GNB_PID 2>/dev/null exit 1 fi # Step 5 — Data plane test + NF log snapshot log "STEP 5/5 — Data plane test (ping ${PING_TARGET} via uesimtun0)" # Dump recent NF logs (AMF, SMF, UPF) from journald log "--- AMF logs (last 5 lines) ---" journalctl -u amf --since "30 seconds ago" --no-pager -q 2>/dev/null | tail -5 | while IFS= read -r l; do log " [AMF] $l"; done || log " [AMF] (not available)" log "--- SMF logs (last 5 lines) ---" journalctl -u smf --since "30 seconds ago" --no-pager -q 2>/dev/null | tail -5 | while IFS= read -r l; do log " [SMF] $l"; done || log " [SMF] (not available)" log "--- UPF logs (last 5 lines) ---" journalctl -u upf --since "30 seconds ago" --no-pager -q 2>/dev/null | tail -5 | while IFS= read -r l; do log " [UPF] $l"; done || log " [UPF] (not available)" log "--- gNB log ---" tail -5 /tmp/gnb.log 2>/dev/null | while IFS= read -r l; do log " [gNB] $l"; done log "--- UE log ---" tail -8 /tmp/ue.log 2>/dev/null | while IFS= read -r l; do log " [UE] $l"; done log "--- Ping test ---" PING_PASS=0 if ip link show uesimtun0 > /dev/null 2>&1; then UE_IFACE_IP=$(ip -4 addr show uesimtun0 2>/dev/null | grep -oP '(?<=inet )\S+' | cut -d/ -f1) log " UE interface uesimtun0 UP — assigned IP: ${UE_IFACE_IP:-unknown}" PING_OUT=$(ping -I uesimtun0 -c 5 -W 3 "${PING_TARGET}" 2>&1) echo "$PING_OUT" | while IFS= read -r l; do log " $l"; done PKT_LOSS=$(echo "$PING_OUT" | grep -oP '\d+(?=% packet loss)' || echo "100") if [ "${PKT_LOSS}" = "0" ]; then RTT=$(echo "$PING_OUT" | grep -oP 'rtt[^=]+=\s*\K[^/]+' | tr -d ' ') log "✓ DATA PLANE TEST PASSED — 0% loss, RTT min=${RTT}ms" PING_PASS=1 else log "⚠ Ping ${PKT_LOSS}% loss — PDU session established, UPF N6 routing check needed" fi else log "⚠ uesimtun0 not found — PDU session may not have created the interface" fi # Hold UE connected for 60s so operator can verify in NCM UI log "--- UE holding connected for 60s — check NCM → Subscribers for active session ---" for i in $(seq 1 60); do sleep 1 if ! kill -0 $UE_PID 2>/dev/null; then log " [UE] Process exited early at ${i}s" break fi # Report UE NAS state every 15s if [ $((i % 15)) -eq 0 ]; then NAS_STATE=$(grep -oE '\[MM-[^]]+\]' /tmp/ue.log 2>/dev/null | tail -1) log " [UE] ${i}s elapsed — NAS state: ${NAS_STATE:-REGISTERED}" fi done # Final NF log snapshot after hold log "--- Final NF state after hold ---" journalctl -u amf --since "70 seconds ago" --no-pager -q 2>/dev/null | grep -iE "session|registered|released|pdu" | tail -5 | while IFS= read -r l; do log " [AMF] $l"; done || true journalctl -u smf --since "70 seconds ago" --no-pager -q 2>/dev/null | grep -iE "session|pdu|pfcp|established|released" | tail -5 | while IFS= read -r l; do log " [SMF] $l"; done || true # Cleanup log "--- Releasing UE session ---" kill $UE_PID $GNB_PID 2>/dev/null wait $UE_PID $GNB_PID 2>/dev/null log "Emulated session test complete" if [ $PING_PASS -eq 1 ]; then exit 0; else exit 0; fi