N2 handover intra-AMF 2Gnb 1ue

This commit is contained in:
agtuser
2025-09-11 06:16:32 +00:00
parent 10ca9395e5
commit 388389428d
38 changed files with 4031 additions and 13 deletions

346
scripts/auto_n2_handover.sh vendored Executable file
View File

@@ -0,0 +1,346 @@
#!/bin/bash
# Auto N2 Handover Test Script
# 自动启动两个基站和一个UE完成N2切换测试
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
# 获取脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
UERANSIM_DIR="$(dirname "$SCRIPT_DIR")"
# 配置文件路径
GNB1_CONFIG="$UERANSIM_DIR/config/free5gc-gnb.yaml"
GNB2_CONFIG="$UERANSIM_DIR/config/free5gc-gnb2.yaml"
UE_CONFIG="$UERANSIM_DIR/config/free5gc-ue.yaml"
# 日志目录
LOG_DIR="$UERANSIM_DIR/logs"
mkdir -p "$LOG_DIR"
# PID文件
GNB1_PID_FILE="$LOG_DIR/gnb1.pid"
GNB2_PID_FILE="$LOG_DIR/gnb2.pid"
UE_PID_FILE="$LOG_DIR/ue.pid"
# 清理函数
cleanup() {
log_step "开始清理进程..."
# 停止UE
if [ -f "$UE_PID_FILE" ]; then
UE_PID=$(cat "$UE_PID_FILE")
if kill -0 "$UE_PID" 2>/dev/null; then
log_info "停止UE进程 (PID: $UE_PID)"
sudo kill "$UE_PID" || true
fi
rm -f "$UE_PID_FILE"
fi
# 停止gNB进程
if [ -f "$GNB1_PID_FILE" ]; then
GNB1_PID=$(cat "$GNB1_PID_FILE")
if kill -0 "$GNB1_PID" 2>/dev/null; then
log_info "停止gNB1进程 (PID: $GNB1_PID)"
sudo kill "$GNB1_PID" || true
fi
rm -f "$GNB1_PID_FILE"
fi
if [ -f "$GNB2_PID_FILE" ]; then
GNB2_PID=$(cat "$GNB2_PID_FILE")
if kill -0 "$GNB2_PID" 2>/dev/null; then
log_info "停止gNB2进程 (PID: $GNB2_PID)"
sudo kill "$GNB2_PID" || true
fi
rm -f "$GNB2_PID_FILE"
fi
# 清理所有相关进程
sudo pkill -f "nr-gnb" || true
sudo pkill -f "nr-ue" || true
log_info "清理完成"
}
# 检查进程状态
check_process() {
local pid=$1
local name=$2
if kill -0 "$pid" 2>/dev/null; then
log_info "$name 运行正常 (PID: $pid)"
return 0
else
log_error "$name 进程异常退出"
return 1
fi
}
# 等待gNB连接到AMF
wait_gnb_ready() {
local gnb_name=$1
local log_file=$2
local max_wait=30
local count=0
log_info "等待 $gnb_name 连接到AMF..."
while [ $count -lt $max_wait ]; do
if grep -q "NG Setup procedure is successful" "$log_file" 2>/dev/null; then
log_info "$gnb_name 成功连接到AMF"
return 0
fi
sleep 1
count=$((count + 1))
done
log_error "$gnb_name 连接AMF超时"
return 1
}
# 等待UE注册完成
wait_ue_registered() {
local log_file=$1
local max_wait=30
local count=0
log_info "等待UE完成注册..."
while [ $count -lt $max_wait ]; do
if grep -q "Initial Registration is successful" "$log_file" 2>/dev/null; then
log_info "UE注册成功"
return 0
fi
sleep 1
count=$((count + 1))
done
log_error "UE注册超时"
return 1
}
# 获取UE ID
get_ue_id() {
local gnb_name=$1
local ue_list_output
ue_list_output=$("$UERANSIM_DIR/build/nr-cli" "$gnb_name" -e "ue-list" 2>/dev/null || echo "")
if [ -n "$ue_list_output" ]; then
echo "$ue_list_output" | grep "ue-id:" | head -1 | sed 's/.*ue-id: *//' | awk '{print $1}'
else
echo ""
fi
}
# 检查handover是否成功
check_handover_success() {
local source_gnb=$1
local target_gnb=$2
local original_ue_id=$3
log_info "检查handover结果..."
# 检查目标gNB是否有UE
local target_ue_id
target_ue_id=$(get_ue_id "$target_gnb")
# 检查源gNB的UE数量
local source_ue_count
source_ue_count=$("$UERANSIM_DIR/build/nr-cli" "$source_gnb" -e "ue-list" 2>/dev/null | grep -c "ue-id:" || echo "0")
log_info "源gNB ($source_gnb) UE数量: $source_ue_count"
log_info "目标gNB ($target_gnb) UE ID: ${target_ue_id:-}"
# 如果目标gNB有UE认为handover成功源gNB可能需要更多时间清理
if [ -n "$target_ue_id" ]; then
log_info "✅ Handover成功"
log_info " 目标gNB ($target_gnb): UE ID = $target_ue_id"
if [ "$source_ue_count" -eq 0 ]; then
log_info " 源gNB ($source_gnb): UE已完全清理"
else
log_warn " 源gNB ($source_gnb): UE还未完全清理 (数量: $source_ue_count) - 这是正常的,清理可能需要更多时间"
fi
return 0
else
log_error "❌ Handover失败"
log_error " 源gNB UE数量: $source_ue_count"
log_error " 目标gNB UE ID: ${target_ue_id:-}"
return 1
fi
}
# 主函数
main() {
log_step "=== 自动N2 Handover测试开始 ==="
# 设置退出时清理
trap cleanup EXIT
# 1. 清理现有进程
log_step "步骤1: 清理现有进程"
cleanup
sleep 2
# 2. 启动gNB1 (目标gNB)
log_step "步骤2: 启动gNB1 (192.168.8.117)"
sudo "$UERANSIM_DIR/build/nr-gnb" -c "$GNB1_CONFIG" > "$LOG_DIR/gnb1.log" 2>&1 &
GNB1_PID=$!
echo "$GNB1_PID" > "$GNB1_PID_FILE"
log_info "gNB1已启动 (PID: $GNB1_PID)"
# 等待gNB1连接AMF
if ! wait_gnb_ready "gNB1" "$LOG_DIR/gnb1.log"; then
log_error "gNB1启动失败"
exit 1
fi
# 3. 启动gNB2 (源gNB)
log_step "步骤3: 启动gNB2 (192.168.8.118)"
sleep 3
sudo "$UERANSIM_DIR/build/nr-gnb" -c "$GNB2_CONFIG" > "$LOG_DIR/gnb2.log" 2>&1 &
GNB2_PID=$!
echo "$GNB2_PID" > "$GNB2_PID_FILE"
log_info "gNB2已启动 (PID: $GNB2_PID)"
# 等待gNB2连接AMF
if ! wait_gnb_ready "gNB2" "$LOG_DIR/gnb2.log"; then
log_error "gNB2启动失败"
exit 1
fi
# 4. 启动UE并连接到gNB2
log_step "步骤4: 启动UE并连接到gNB2"
sleep 3
sudo "$UERANSIM_DIR/build/nr-ue" -c "$UE_CONFIG" > "$LOG_DIR/ue.log" 2>&1 &
UE_PID=$!
echo "$UE_PID" > "$UE_PID_FILE"
log_info "UE已启动 (PID: $UE_PID)"
# 等待UE注册完成
if ! wait_ue_registered "$LOG_DIR/ue.log"; then
log_error "UE注册失败"
exit 1
fi
# 5. 检查初始状态
log_step "步骤5: 检查初始UE分布"
sleep 2
# 确定UE连接到哪个gNB
log_info "检查gNB1的UE列表..."
UE_LIST_GNB1=$("$UERANSIM_DIR/build/nr-cli" "UERANSIM-gnb-460-0-1" -e "ue-list" 2>/dev/null || echo "")
log_info "gNB1 UE列表输出: '$UE_LIST_GNB1'"
log_info "检查gNB2的UE列表..."
UE_LIST_GNB2=$("$UERANSIM_DIR/build/nr-cli" "UERANSIM-gnb-460-0-16" -e "ue-list" 2>/dev/null || echo "")
log_info "gNB2 UE列表输出: '$UE_LIST_GNB2'"
UE_ID_GNB1=$(echo "$UE_LIST_GNB1" | grep "ue-id:" | head -1 | sed 's/.*ue-id: *//' | awk '{print $1}')
UE_ID_GNB2=$(echo "$UE_LIST_GNB2" | grep "ue-id:" | head -1 | sed 's/.*ue-id: *//' | awk '{print $1}')
if [ -n "$UE_ID_GNB1" ]; then
SOURCE_GNB="UERANSIM-gnb-460-0-1"
TARGET_GNB="UERANSIM-gnb-460-0-16"
TARGET_CELL="16"
UE_ID="$UE_ID_GNB1"
log_info "UE连接到gNB1UE ID: $UE_ID"
elif [ -n "$UE_ID_GNB2" ]; then
SOURCE_GNB="UERANSIM-gnb-460-0-16"
TARGET_GNB="UERANSIM-gnb-460-0-1"
TARGET_CELL="1"
UE_ID="$UE_ID_GNB2"
log_info "UE连接到gNB2UE ID: $UE_ID"
else
log_error "未找到UE连接"
exit 1
fi
# 6. 执行handover
log_step "步骤6: 执行N2 Handover"
log_info "$SOURCE_GNB 切换UE $UE_ID 到目标Cell $TARGET_CELL"
HANDOVER_OUTPUT=$("$UERANSIM_DIR/build/nr-cli" "$SOURCE_GNB" -e "handover $UE_ID $TARGET_CELL" 2>&1)
log_info "Handover命令输出: $HANDOVER_OUTPUT"
# 7. 等待handover完成
log_step "步骤7: 等待handover完成"
sleep 15 # 等待handover完成 (8秒清理时间 + 7秒缓冲)
# 8. 验证handover结果
log_step "步骤8: 验证handover结果"
if check_handover_success "$SOURCE_GNB" "$TARGET_GNB" "$UE_ID"; then
log_step "=== ✅ N2 Handover测试成功完成 ==="
# 显示最终状态
echo ""
log_info "最终UE分布:"
echo "gNB1 (UERANSIM-gnb-460-0-1):"
"$UERANSIM_DIR/build/nr-cli" "UERANSIM-gnb-460-0-1" -e "ue-list" 2>/dev/null || echo " 无UE连接"
echo ""
echo "gNB2 (UERANSIM-gnb-460-0-16):"
"$UERANSIM_DIR/build/nr-cli" "UERANSIM-gnb-460-0-16" -e "ue-list" 2>/dev/null || echo " 无UE连接"
# 保持运行以便观察
echo ""
log_info "测试完成按Ctrl+C退出并清理进程"
while true; do
sleep 5
# 检查进程状态
if ! check_process "$GNB1_PID" "gNB1" || ! check_process "$GNB2_PID" "gNB2" || ! check_process "$UE_PID" "UE"; then
log_warn "发现进程异常,退出测试"
break
fi
done
else
log_step "=== ❌ N2 Handover测试失败 ==="
exit 1
fi
}
# 检查是否以root权限运行
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}[ERROR]${NC} 请使用sudo运行此脚本"
exit 1
fi
# 检查构建目录
if [ ! -f "$UERANSIM_DIR/build/nr-gnb" ] || [ ! -f "$UERANSIM_DIR/build/nr-ue" ]; then
log_error "找不到UERANSIM构建文件请先运行make编译"
exit 1
fi
# 检查配置文件
for config in "$GNB1_CONFIG" "$GNB2_CONFIG" "$UE_CONFIG"; do
if [ ! -f "$config" ]; then
log_error "找不到配置文件: $config"
exit 1
fi
done
# 运行主函数
main "$@"

89
scripts/uecfgs/ue_imsi-460000000000001.yaml vendored Executable file
View File

@@ -0,0 +1,89 @@
# IMSI number of the UE. IMSI = [MCC|MNC|MSISDN] (In total 15 digits)
supi: 'imsi-460000000000001'
# Mobile Country Code value of HPLMN
mcc: '460'
# Mobile Network Code value of HPLMN (2 or 3 digits)
mnc: '00'
# SUCI Protection Scheme : 0 for Null-scheme, 1 for Profile A and 2 for Profile B
protectionScheme: 0
# Home Network Public Key for protecting with SUCI Profile A
homeNetworkPublicKey: '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650'
# Home Network Public Key ID for protecting with SUCI Profile A
homeNetworkPublicKeyId: 1
# Routing Indicator
routingIndicator: '0000'
# Permanent subscription key
key: '11111111111111111111111111111111'
# Operator code (OP or OPC) of the UE
op: '11111111111111111111111111111111'
# This value specifies the OP type and it can be either 'OP' or 'OPC'
opType: 'OPC'
# Authentication Management Field (AMF) value
amf: '8000'
# IMEI number of the device. It is used if no SUPI is provided
imei: '356938035643803'
# IMEISV number of the device. It is used if no SUPI and IMEI is provided
imeiSv: '4370816125816151'
# Network mask used for the UE's TUN interface to define the subnet size
tunNetmask: '255.255.255.0'
# List of gNB IP addresses for Radio Link Simulation
gnbSearchList:
- 192.168.8.117
- 192.168.8.118
# UAC Access Identities Configuration
uacAic:
mps: false
mcs: false
# UAC Access Control Class
uacAcc:
normalClass: 0
class11: false
class12: false
class13: false
class14: false
class15: false
# Initial PDU sessions to be established
sessions:
- type: 'IPv4'
apn: 'cmnet'
slice:
sst: 0x01
sd: 0x000001
- type: IPv4
apn: ims
slice:
sst: 0x01
sd: 0x000001
# Configured NSSAI for this UE by HPLMN
configured-nssai:
- sst: 0x01
sd: 0x000001
# Default Configured NSSAI for this UE
default-nssai:
- sst: 1
sd: 1
# Supported integrity algorithms by this UE
integrity:
IA1: true
IA2: true
IA3: true
# Supported encryption algorithms by this UE
ciphering:
EA1: true
EA2: true
EA3: true
# Integrity protection maximum data rate for user plane
integrityMaxRate:
uplink: 'full'
downlink: 'full'