226 lines
6.9 KiB
Bash
226 lines
6.9 KiB
Bash
#!/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
|