Week: 6-7 -- Cellular Protocols
Points: 25
Time estimate: 90 min lab + 3 hr independent
Deliverable: lab-5-report.md
Objectives
- Bring up an OAI LTE eNB in Docker; connect a software UE (srsUE) and complete an LTE attach.
- Capture the RACH procedure in a packet capture and annotate the 4-step sequence.
- Measure the PUSCH SNR across the receiver chain using OAI's built-in instrumentation.
- Observe 5G-AKA key material derivation in the AMF logs (NSA mode optional extension).
Part A: OAI LTE Stack Bring-Up (30 min)
# Clone configuration templates
git clone https://github.com/open5gs/open5gs.git # for EPC/MME alternative
# OR use OAI EPC (below)
# Pull OAI LTE images
docker pull oaisoftwarealliance/oai-enb:develop
docker pull oaisoftwarealliance/oai-mme:develop
docker pull oaisoftwarealliance/oai-spgwu-tiny:develop
docker pull oaisoftwarealliance/oai-hss:develop
# Create lab5 directory with docker-compose
mkdir lab5 && cd lab5
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: oai_db
volumes:
- ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
oai-hss:
image: oaisoftwarealliance/oai-hss:develop
network_mode: host
environment:
TZ: America/New_York
MYSQL_SERVER: 127.0.0.1
MYSQL_USER: root
MYSQL_PASS: root
depends_on:
- mysql
oai-mme:
image: oaisoftwarealliance/oai-mme:develop
network_mode: host
environment:
TZ: America/New_York
MCC: "208"
MNC: "93"
TAC: "1"
SGW_S11_IP: "127.0.0.1"
oai-spgwu:
image: oaisoftwarealliance/oai-spgwu-tiny:develop
network_mode: host
cap_add:
- NET_ADMIN
environment:
TZ: America/New_York
SGW_INTERFACE_NAME_FOR_S1U: "lo"
PGW_INTERFACE_NAME_FOR_SGI: "lo"
oai-enb:
image: oaisoftwarealliance/oai-enb:develop
network_mode: host
cap_add:
- SYS_RAWIO
- NET_ADMIN
environment:
TZ: America/New_York
ENODEB_NAME: "lab5-eNB"
MCC: "208"
MNC: "93"
MNC_LENGTH: "2"
TAC: "1"
UTRA_BAND_ID: "7" # Band 7: 2600 MHz (or change to available band)
DL_FREQUENCY_IN_MHZ: "2680"
UL_FREQUENCY_OFFSET_IN_MHZ: "120"
NB_PRB: "25" # 25 RBs = 5 MHz channel
MME_S1_IP: "127.0.0.1"
ENB_S1_IP: "127.0.0.1"
THREAD_PARALLEL_CONF: "PARALLEL_RU_L1_L2_TRX_SPLIT"
USE_ZMQ: "yes" # ZeroMQ RF (no physical radio needed for software UE)
EOF
# Start the stack
docker-compose up -d mysql oai-hss oai-mme oai-spgwu
sleep 10
docker-compose up -d oai-enb
# Verify eNB is running
docker-compose logs oai-enb | grep -E "eNB.*started|RRC.*SIB"
srsUE (software UE):
# Install srsRAN (includes srsUE)
sudo apt-get install srsran srsran-4g
# Configure srsUE to connect to the OAI eNB (ZMQ mode)
cat > /etc/srslte/ue.conf << 'EOF'
[rf]
freq_offset = 0
tx_gain = 80
rx_gain = 40
device_name = zmq
device_args = tx_port=tcp://127.0.0.1:2001,rx_port=tcp://127.0.0.1:2000,id=ue,base_srate=23.04e6
[usim]
mode = soft
algo = milenage
opc = 63BFA50EE6523365FF14C1F45F88737D
k = 00112233445566778899aabbccddeeff
imsi = 208930000000001
imei = 353490069873319
EOF
# Connect the software UE
sudo srsue /etc/srslte/ue.conf 2>&1 | tee lab5-srsue.log &
UE_PID=$!
# Watch the UE connection log
sleep 5
grep -E "RACH|Attach|RRC|NAS|CONNECTED" lab5-srsue.log | head -20
Part B: RACH Capture and Annotation (30 min)
Capture the air-interface traffic using Wireshark or tshark in the ZMQ loopback:
# Start packet capture on the loopback interface
sudo tshark -i lo -w lab5-rach.pcap -f "port 2000 or port 2001" &
TSHARK_PID=$!
# Trigger a new attach by restarting srsUE
kill $UE_PID
sudo srsue /etc/srslte/ue.conf 2>&1 | tee lab5-srsue2.log &
sleep 30 # wait for attach
kill $TSHARK_PID
# Analyze in Wireshark
# Filter: lte-rrc or nas-eps
# Look for: RRC Connection Request, RRC Connection Setup,
# RRC Connection Setup Complete, Attach Request, Attach Accept
Annotation task: In your report, annotate the following 5-step LTE attach sequence by matching Wireshark frames to the protocol layer:
| Step | Protocol message | Layer | What it contains |
|---|---|---|---|
| 1 | RACH Preamble | PHY | Zadoff-Chu sequence; random selection |
| 2 | RAR (Random Access Response) | MAC | TA, Temporary C-RNTI, UL grant |
| 3 | RRC Connection Request | RRC | UE identity (S-TMSI or random value) |
| 4 | RRC Connection Setup | RRC | Radio bearer configuration |
| 5 | Attach Request / RRC Connection Setup Complete | NAS/RRC | IMSI (or GUTI), UE capabilities |
OAI eNB log analysis:
# Extract PHY-layer RACH events from eNB logs
docker-compose logs oai-enb | grep -E "PRACH|RA-Msg|CRNTI|SNR" | head -30
# Expected output format:
# [PHY] PRACH_RX subframe X: preamble_index Y, TA Z, RSSI -W dBm
# [MAC] RA-Msg2: UE RNTI 0xABCD TA=Z ul_grant=...
# [RRC] RRC Connection Request UE RNTI 0xABCD
Part C: PUSCH SNR Budget Instrumentation (30 min)
OAI instruments the uplink SNR at the PUSCH decoder. Extract and analyze:
# Capture PUSCH SNR logs
docker-compose logs oai-enb | grep -E "SNR|PUSCH|BLER|MCS" | tail -50
# Expected: eNB reports per-subframe SNR estimates
# Format: "UE RNTI 0xABCD PUSCH: SNR=15.2 dB, BLER=0.0, MCS=18"
#!/usr/bin/env python3
"""Lab 5 Part C: Parse and analyze OAI PUSCH SNR logs."""
import re
import numpy as np
import matplotlib.pyplot as plt
# Parse SNR measurements from eNB log
log_file = 'lab5-enb.log'
snr_values = []
mcs_values = []
with open(log_file) as f:
for line in f:
# Adjust regex to match actual OAI log format
snr_match = re.search(r'SNR=(-?\d+\.?\d*)', line)
mcs_match = re.search(r'MCS=(\d+)', line)
if snr_match:
snr_values.append(float(snr_match.group(1)))
if mcs_match:
mcs_values.append(int(mcs_match.group(1)))
if snr_values:
print(f"PUSCH SNR statistics:")
print(f" Mean: {np.mean(snr_values):.1f} dB")
print(f" Std: {np.std(snr_values):.1f} dB")
print(f" Min: {np.min(snr_values):.1f} dB")
print(f" Max: {np.max(snr_values):.1f} dB")
plt.figure(figsize=(10, 4))
plt.plot(snr_values, 'b-', alpha=0.7, label='PUSCH SNR per subframe')
plt.axhline(np.mean(snr_values), color='r', linestyle='--', label=f'Mean = {np.mean(snr_values):.1f} dB')
plt.xlabel('Subframe index')
plt.ylabel('SNR (dB)')
plt.title('OAI eNB PUSCH SNR Over Time (ZMQ loopback)')
plt.legend()
plt.grid(True)
plt.savefig('lab5/pusch_snr.png', dpi=150)
else:
print("No SNR values parsed -- check log format and regex")
print("Manual approach: scan logs for PUSCH-related lines")
Link budget verification: Compare measured PUSCH SNR to the theoretical link budget:
# ZMQ loopback: no propagation loss (should see near-perfect SNR)
# Theoretical: limited by srsUE TX power + OAI receiver noise figure
# Fill in from OAI configuration and AD9361 (or ZMQ) parameters
tx_power_dBm = 23.0 # srsUE default UL max power
rx_nf_dB = 0.0 # ZMQ is ideal (no noise); replace with hardware NF for RF test
path_loss_dB = 0.0 # ZMQ loopback: no propagation
P_rx_dBm = tx_power_dBm - path_loss_dB
thermal_noise_dBm = -174 + 10*np.log10(180e3) # 180 kHz RB bandwidth
SNR_theoretical_dB = P_rx_dBm - (thermal_noise_dBm + rx_nf_dB)
print(f"Theoretical PUSCH SNR (ZMQ): {SNR_theoretical_dB:.0f} dB")
print(f"(Hardware test would see ~15-25 dB depending on cable losses)")
Part D: 5G-AKA Observation (optional extension)
If OAI 5G NSA mode is available:
# Observe AMF logs for AUSF interaction during UE attach
# Look for SUCI, AUSF authentication, key derivation
docker-compose logs oai-amf | grep -E "SUCI|AUSF|5G-AKA|HXRES|KAUSF" | head -20
# Expected format (varies by OAI version):
# [AMF] Authentication: SUCI received from UE
# [AMF] NAUSF_UEAuthentication request sent to AUSF
# [AMF] 5G-AKA: HXRES* received; verifying RES*
# [AMF] Authentication success; KAUSF derived
Lab Report
Create lab-5-report.md with:
- eNB bring-up: docker-compose output showing all containers healthy
- LTE attach annotation table (5 steps completed with actual Wireshark frame numbers or OAI log timestamps)
- PUSCH SNR statistics: mean, std, min, max from log analysis; plot
- Link budget verification: theoretical vs. measured SNR (ZMQ or hardware)
- Analysis (150 words): "The OAI eNB's RACH procedure uses Zadoff-Chu sequences as preambles. Explain the cyclic autocorrelation property of Zadoff-Chu sequences and why it allows the eNB to distinguish 64 different preambles and simultaneously estimate the UE's timing advance."
Grading
| Component | Points |
|---|---|
| Stack bring-up: all containers healthy, srsUE connects | 6 |
| RACH annotation: 5 steps identified with evidence | 8 |
| PUSCH SNR: statistics and plot from log analysis | 7 |
| Analysis: Zadoff-Chu autocorrelation property explained | 4 |
| Total | 25 |