0. 部署环境声明
部署 OpenAirInterface(OAI)的服务器部分核心参数如下:
| 项目 | 参数 |
|---|---|
| 系统架构 | x86_64 |
| 字节序 | 小端序 |
| CPU 型号 | AMD Ryzen Threadripper PRO 7955WX 16-Cores |
| CPU 最大频率 | 7639 MHz |
| CPU 最小频率 | 545 MHz |
| L1 缓存 | 1MB |
| L2 缓存 | 16MB |
| L3 缓存 | 64MB |
| 显卡 | NVIDIA T400 4GB |
| 操作系统 | Ubuntu 22.04.5 LTS |
由于部署 OAI 的服务器处于离线环境,因此本文档所述过程稍显繁琐,在常规联网环境下部分步骤可以更便捷,因此可视本文档所述为基线部署过程。
1. OAI 接入网项目下载
本系统搭建所使用的 OAI 接入网项目版本为 v2.4.0,可采用两种方式将源码下载至本地。
1.1 下载压缩包后解压(离线方式)
使用可联网的计算机访问上述项目地址,在界面右上角的 “代码” 下拉菜单中选择任意压缩包或归档文件进行下载,如图所示。

下载到本地后迁移到离线服务器的指定目录进行解压。参考解压命令(解压到当前文件夹):
$ tar -xvf Filename.tar # for *.tar
$ tar -zxvf Filename.tar.gz # for *.tar.gz
$ unzip Filename.zip # for *.zip
1.2 git clone(联网方式)
在联网状态下,可以便捷地使用 git clone 命令将项目代码下载至本地,但由于这里使用的是特定标签的项目版本,因此需要指定额外命令行参数,参考命令:
$ git clone -b v2.4.0 --depth=1 https://gitlab.eurecom.fr/oai/openairinterface5g.git
其中,-b 后跟版本标签,这里即 v2.4.0;--depth 指示 clone 深度,指定为 1 时表示只 clone 最新版本。或者也可先将整个 git 仓库先 clone 至本地,再使用 git checkout 切换到 v2.4.0 这一标签,即:
$ git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
$ git checkout v2.4.0
2. 运行环境及依赖配置
2.1 低时延内核切换及BIOS电源管理功能删除
2.4.0 版本的 OAI 部署指引中并未提及 低时延内核切换和删除BIOS电源管理功能 的步骤,但在 2022.w47 版本的部署过程中有执行这两个步骤。由于该网页的上次更新时间还是 2019 年 4 月,恐有过时之嫌,因此采用低时延内核和删除 BIOS 电源管理功能的必要性还留待验证。如果在对性能要求较高的运行场景下出现问题,则需对本节中提及的两项配置进行回顾。
Ubuntu 22.04.5 LTS 默认使用的内核可用以下命令查看:
$ uname -r
内核版本应为 linux-image-6.8.0-40-generic,属于通用内核。
安装低时延内核(需提前制作本地 apt-get 源):
$ sudo apt install linux-headers-6.8.0-40-lowlatency linux-image-6.8.0-40-lowlatency
$ sudo update-initramfs -u -k all
修改引导菜单:
$ sudo vim /etc/default/grub
将其中的 GRUB_TIMEOUT_STYLE=hidden 注释,保存退出后执行
$ sudo update-grub
重启服务器,在 grub 界面选择 Advanced options for Ubuntu,回车后继续选择带有 lowlatency 后缀的内核进行启动即可。
如果需要默认以该内核启动,须将 /etc/default/grub 文件中的 GRUB_DEFAULT=0 修改为 GRUB_DEFAULT=“1> x”。注意等号后面的内容需要带有双引号;将 x 替换为期望选择的内核顺序,从 0 开始计数;> 后有空格。
完成以上操作后,再次查看内核,此时的内核版本应为 linux-image-6.8.0-40-lowlatency。
2.2 设置环境变量
OAI 在项目代码的根目录下有 oaienv 文件,执行命令
$ cd <OAI directory>
$ source oaienv
即可完成 OAI 项目编译和运行所需的所有环境变量的配置。
2.3 安装依赖
OAI 项目根目录的 cmake_targets/ 目录下有 build_oai 文件,指定 -I 选项执行以安装 OAI 所需的依赖,脚本会自动执行 apt-get install、git clone 及 wget 等操作:
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai -I
针对离线场景,查看 build_oai 中的 main() 函数,发现当指定 -I 选项时,会执行 INSTALL_EXTERNAL=1,并在随后的 if 语句块中调用 check_install_oai_software() 函数,该函数定义在 cmake_targets/tools/build_helper 文件中。从该文件头部可知对于 Ubuntu 操作系统,其 OS_BASEDISTRO="debian",因此会执行以下语句:
if [[ "$OS_BASEDISTRO" == "debian" ]]; then
$SUDO apt install -y software-properties-common
case "$(get_distribution_release)" in
"debian11")
specific_packages="libz-dev"
;;
esac
$SUDO apt-get install -y \
$specific_packages \
automake \
build-essential \
$CMAKE \
ninja-build \
pkg-config \
git \
libblas-dev \
liblapack-dev \
liblapacke-dev \
libreadline-dev \
libconfig-dev \
libsctp-dev \
libssl-dev \
libtool \
patch \
openssl \
zlib1g-dev \
xxd \
libyaml-cpp-dev
此外还有 if 语句块外的
install_asn1c_from_source $1
install_simde_from_source $1
install_asn1c_from_source() 函数以及 install_simde_from_source() 函数在 build_helper 文件中也都有定义。
针对通过 apt-get 下载安装的依赖,可同理采用制作本地 apt-get 源的方式;针对通过 git clone 或 wget 下载安装的依赖,先通过可联网的计算机下载到本地,然后迁移到离线服务器的指定目录,再在离线服务器的 build_helper 文件中注释掉 git clone 或 wget 操作,即可在少量改动的前提下通过同一脚本实现依赖的安装。
以 install_asn1c_from_source() 函数为例,其内容为:
install_asn1c_from_source(){
echo_info "\nInstalling ASN1."
$SUDO $INSTALLER -y install bison flex
$SUDO rm -rf /tmp/asn1c
# GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c
git clone https://github.com/mouse07410/asn1c /tmp/asn1c
cd /tmp/asn1c
#git checkout vlm_master
# hotfix: current vlm_master (5fa129cf3161da9ff2d67341e6277e818c0f5d6a)
# breaks F1, NG, so use the one before.
git checkout 940dd5fa9f3917913fd487b13dfddfacd0ded06e
# Showing which version is used
git log -n1
autoreconf -iv
CFLAGS="-O2 -fno-strict-aliasing" ./configure --prefix /opt/asn1c/
make -j`nproc`
$SUDO make install
cd -
$SUDO ldconfig
if [[ -v CI_ENV ]]; then
$SUDO rm -rf /tmp/asn1c
fi
}
现行做法是:
在能联网的计算机上执行
git clone https://github.com/mouse07410/asn1c;在离线服务器的
/tmp目录下执行mkdir asn1c创建与脚本内容一致的文件夹;将下载的整个目录迁移至
/tmp/asn1c目录下;注释
install_asn1c_from_source()函数中的$SUDO rm -rf /tmp/asn1c和git clone https://github.com/mouse07410/asn1c /tmp/asn1c语句,并保存。
这样执行修改后的 install_asn1c_from_source() 函数就能达到与联网状态下执行原始版本函数同样的效果。
注意:除非其中某些依赖发生改变,否则安装依赖这一步骤在整个 OAI 的使用过程中仅需执行一次。
2.4 安装可选库
OAI 还支持对 gNB、nrUE 等运行状态的可视化,这需要额外的依赖提供支持,同样通过对 build_oai 指定命令行选项来实现:
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai --build-lib all
上述指令实现了对所有可选库的构建,但也可以结合实际需求选择其中一项或某几项构建,具体支持的可选库包括但不限于 telnetsrv、nrscope 等,具体可执行 sudo ./build_oai -h 获取帮助。
3. 接入网实例构建
3.1 构建 RF Simulator 模式下的 gNB 和 nrUE 实例
进入 OAI cmake_targets/ 目录,执行以下命令,得到如下图所示的构建结果。当终端输出 BUILD SHOULD BE SUCCESSFUL 即可认定构建成功。
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai -w SIMU --gNB --nrUE --ninja

其中,-w 指定运行所构建代码的射频类型,SIMU 表示 RF Simulator,USRP 表示实体射频硬件;--gNB 和 --nrUE 分别指示构建 gNB 实例和 nrUE 实例;--ninja 指示使用 ninja 构建工具(应已通过 sudo ./build_oai -I 安装),此非必选项但指定该参数相较于不指定可以显著加快构建速度。
3.2 构建具有射频硬件实体的 gNB 和 nrUE 实例
如上一小节所述,如果射频硬件实体为 USRP,仅需将构建指令 -w 后的内容替换为 USRP 即可,即:
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai -w USRP --gNB --nrUE --ninja
OAI 还支持其他类型的硬件,具体支持硬件列表可执行 sudo ./build_oai -h 获取帮助。
4. OAI 核心网项目下载
本系统搭建所使用的 OAI 核心网项目版本为 v2.2.1,可采用两种方式将源码下载至本地。
4.1 下载压缩包后解压(离线方式)
使用可联网的计算机访问上述项目地址,在界面右上角的“代码”下拉菜单中选择任意压缩包或归档文件进行下载,如图所示。

下载到本地后迁移到离线服务器的指定目录进行解压。
4.2 git clone(联网方式)
在联网状态下,可以便捷地使用 git clone 命令将项目代码下载至本地,但由于这里使用的是特定标签的项目版本,因此需要指定额外命令行参数,参考命令:
$ git clone -b v2.2.1 --depth=1 https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed.git
或者也可先将整个 git 仓库先 clone 至本地,再使用 git checkout 切换到 v2.2.1 这一标签,即:
$ git clone https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed.git
$ git checkout v2.2.1
5. docker 及镜像下载与安装
本节内容部分参考 OAI cn5g 部署前提条件、OAI cn5g basic 模式部署文档 以及 OAI cn5g 镜像拉取文档。
5.1 docker 及其部件下载与安装
根据 OAI cn5g basic 模式部署文档,docker engine 版本应为 29.1.2。使用可联网的计算机打开 docker 下载地址 下载如下文件:
docker-ce_29.1.2-1~ubuntu.22.04~jammy_amd64.deb
docker-ce-cli_29.1.2-1~ubuntu.22.04~jammy_amd64.deb
docker-compose-plugin_2.40.3-1~ubuntu.22.04~jammy_amd64.deb
迁移至离线服务器,执行如下命令以进行安装:
$ sudo dpkg -i xxx.deb
其中,xxx 须替换为实际的包名称。完成以上三个 .deb 包的安装后,执行 dpkg --list | grep docker, 应有如下屏幕输出:

注意:docker compose 从大版本可区分为 V1 和 V2 两个版本,其中 V1 以独立命令
docker-compose的形式体现,已于 2023 年 7 月停止更新;V2 则深度集成在 docker CLI 中,以子命令docker compose的形式体现,这使得 V2 能共享 docker 根命令的全局选项,用法更统一。然而v2.2.1版本的 OAI cn5g 在一些脚本中仍采用docker-compose的写法,有必要使用docker compose替换之,否则执行相关语句会报错。
默认情况下,执行以 docker 命令都需要使用管理员权限,为了避免每次输入命令都加前缀 sudo,可以考虑将主机用户添加到 docker 组中,执行以下命令即可:
$ sudo usermod -a -G docker <Username>
以下均默认已将主机用户添加到 docker 组中。
5.2 docker 镜像下载及迁移
本小节内容参考 OAI cn5g 镜像拉取文档。
从 Docker Hub 下载镜像需要账户,因此如果没有账户需要先行注册。在已拥有账户的前提下,在联网且能访问 Docker Hub 的计算机(这里以Windows 11为例)上打开 powershell,执行
$ docker login -u <Username>
输入密码后回车等待响应,显示 Login Succeeded 即登录成功。
注意:OAI 文档中提供的
docker login命令,采用弹出网页提供验证码,再在 powershell 中输入验证码登录的方式。由于先前已注册过 docker 账户,因此没有采用这种单次登录的方式。
执行以下命令以从 Docker Hub 拉取 OAI cn5g 镜像:
$ docker pull oaisoftwarealliance/oai-amf:v2.1.0
$ docker pull oaisoftwarealliance/oai-nrf:v2.1.0
$ docker pull oaisoftwarealliance/oai-upf:v2.1.0
$ docker pull oaisoftwarealliance/oai-smf:v2.1.0
$ docker pull oaisoftwarealliance/oai-udr:v2.1.0
$ docker pull oaisoftwarealliance/oai-udm:v2.1.0
$ docker pull oaisoftwarealliance/oai-ausf:v2.1.0
$ docker pull oaisoftwarealliance/oai-upf-vpp:v2.1.0
$ docker pull oaisoftwarealliance/oai-nssf:v2.1.0
$ docker pull oaisoftwarealliance/oai-pcf:v2.1.0
$ docker pull oaisoftwarealliance/oai-lmf:v2.1.0
# Utility image to generate traffic
$ docker pull oaisoftwarealliance/trf-gen-cn5g:latest
此外,由于 v2.2.1 的 oai-cn5g-fed/docker-compose 目录下的 docker-compose-basic-nrf.yaml 文件中,还依赖镜像 mysql:9.0 以构建数据库容器,因此还需要拉取该镜像:
$ docker pull mysql:9.0
最后登出账户:
$ docker logout
回车后等待响应,显示 Removing login credentials for https://index.docker.io/v1/ 即登出成功。
新建一个文件夹,在该目录下通过 powershell 执行以下命令:
$ docker save -o docker_images.tar oaisoftwarealliance/oai-amf:v2.1.0 oaisoftwarealliance/oai-nrf:v2.1.0 oaisoftwarealliance/oai-upf:v2.1.0 oaisoftwarealliance/oai-smf:v2.1.0 oaisoftwarealliance/oai-udr:v2.1.0 oaisoftwarealliance/oai-udm:v2.1.0 oaisoftwarealliance/oai-ausf:v2.1.0 oaisoftwarealliance/oai-upf-vpp:v2.1.0 oaisoftwarealliance/oai-nssf:v2.1.0 oaisoftwarealliance/oai-pcf:v2.1.0 oaisoftwarealliance/oai-lmf:v2.1.0 oaisoftwarealliance/trf-gen-cn5g:latest mysql:9.0
将得到的 tar 文件迁移至离线服务器,执行如下命令以加载镜像:
$ docker load -i docker_images.tar
之后可通过 docker images 查看当前主机上的镜像:

注意:使用
docker save将镜像进行归档时,也可指定镜像 ID,但迁移至另一部主机后,镜像名称会丢失,如下所示,还需要额外通过执行docker tag <镜像ID> <镜像名>:<标签>命令为镜像命名。因此在将镜像进行归档时还是尽量优先指定镜像名。
untagged_images.png
6. 核心网及关联配置
以下除非另外说明,均以 basic 模式部署核心网,对应的配置文件为 docker-compose/docker-compose-basic-nrf.yaml。
6.1 python 版本检查
OAI cn5g 部署前提条件 中提及,部署核心网所需的最低 python 版本为 3.6,而执行 python3 --version 查询到 Ubuntu 22.04.5 LTS 自带的 python 版本是 3.10.12,已满足条件。
注意:早先部署 OAI 核心网是通过执行
docker-compose/core-network.py脚本实现的,但v2.2.1版本是直接针对docker-compose/docker-compose-basic-nrf.yaml执行的docker compose操作,因此 python3 版本检查的步骤可能也不必要?但至少 Ubuntu 22.04.5 LTS 自带的 python 版本已满足基线要求。
6.2 同步核心网 git 子模块
执行该步骤的作用不明,但在 OAI cn5g 镜像拉取文档 中有提及。
$ cd oai-cn5g-fed/scripts
$ ./syncComponents.sh
应得到如下屏幕回显:

6.3 网络配置
6.3.1 开启 IP 转发
部署核心网的服务器上须开启 IP 转发:
$ sudo sysctl net.ipv4.conf.all.forwarding=1
$ sudo iptables -P FORWARD ACCEPT
注意:该两项配置重启服务器后可能失效,每次重启后均需检查。
6.3.2 更改 docker 网桥(可选)
默认 docker 网桥位于 172.17.0.0/16 网段,但该网段在 Eurocom 内部网络中已被使用,所以 OAI cn5g 部署前提条件 提供了修改 docker 网桥的方法。虽然当前部署环境没有用到172.17.0.0/16 网段,但仍参考教程将 docker 网段更改至 192.168.17.1/24。
执行以下命令创建新文件:
$ vim /etc/docker/daemon.json
输入以下内容,保存后退出:
{
"bip": "192.168.17.1/24"
}
重启 docker 守护进程,查看网桥信息:
$ sudo service docker restart
$ docker network inspect bridge

由子网网段和网关地址可知,修改成功。
6.3.3 创建 demo-oai 网桥
所有 OAI 核心网网元均连接至名为 demo-oai 的网桥,执行以下命令手动创建 demo-oai 网桥:
$ docker network create --driver=bridge --subnet=192.168.70.128/26 -o "com.docker.network.bridge.name"="demo-oai" demo-oai-public-net
命令行会回显一段十六进制 ID,据此判定 demo-oai 创建成功。
此时执行以下命令,应能看到 demo-oai 的网络信息:
$ ifconfig demo-oai
$ docker network ls


docker-compose/docker-compose-basic-nrf.yaml 文件的末尾声明了使用的外部网络:
networks:
public_net:
driver: bridge
name: demo-oai-public-net
ipam:
config:
- subnet: 192.168.70.128/26
driver_opts:
com.docker.network.bridge.name: "demo-oai"
将以上内容替换为:
networks:
public_net:
name: demo-oai-public-net
external: true
注意:官方教程中提供的
yaml文件版本:networks: public_net: external: name: demo-oai-public-net使用的是旧版语法,若使用该语法的
yaml文件部署核心网,会告警networks.public_net: external.name is deprecated. Please set name and external:true.,但不影响部署的实际效果。
6.3.4 添加转发路由
gNB 与核心网部署在不同服务器的情况下,需要在部署 gNB 的服务器上添加路由转发规则:
$ sudo ip route add route 192.168.70.128/26 via IP_ADDR_NIC1 dev NIC1_NAME
其中,192.168.70.128/26 为 demo-oai 网桥地址,只要完全按照 6.3.3 节步骤成功创建了 demo-oai 网桥,则该地址保持不变;NIC1_NAME 为 gNB 上连接核心网服务器的物理接口名称,IP_ADDR_NIC1 为该物理接口的 IP 地址。
注意:如果 gNB 和核心网部署在同一台服务器,则该步骤可省略。
6.4 配置文件修改
6.4.1 构建容器所基于镜像名称修改
以 docker-compose-basic-nrf.yaml 文件中的 AMF 网元配置为例:
oai-amf:
container_name: "oai-amf"
image: oaisoftwarealliance/oai-amf:develop
expose:
- 80/tcp
- 8080/tcp
- 38412/sctp
volumes:
- ./conf/basic_nrf_config.yaml:/openair-amf/etc/config.yaml
environment:
- TZ=Europe/Paris
depends_on:
- oai-nrf
networks:
public_net:
# For CI purposes, we are keeping the line commented
# ipv4_address: 192.168.70.132
原始文件中的 image 行指定采用 oaisoftwarealliance/oai-amf:develop 构建容器,与所下载镜像版本不符,须手动改为 oaisoftwarealliance/oai-amf:v2.1.0,其他网元同理修改。
末行的 ipv4 地址用于指定网元地址,对于已稳定部署的核心网,可将该行取消注释以获得稳定的网元地址,否则每次启动核心网时各网元将会被随机分配 192.168.70.130/26 开始的地址。
各网元的稳定地址如下:
| 网元 | IP 地址 |
|---|---|
mysql |
192.168.70.131 |
oai-udr |
192.168.70.136 |
oai-udm |
192.168.70.137 |
oai-ausf |
192.168.70.138 |
oai-nrf |
192.168.70.130 |
oai-amf |
192.168.70.132 |
oai-smf |
192.168.70.133 |
oai-upf |
192.168.70.134 |
oai-ext-dn |
192.168.70.135 |
6.4.2 UE 身份信息及 DNN 配置定位
使用 basic 模式部署核心网时,UE 的身份信息保存在 docker-compose/database/oai_db2.sql 文件中,其中的
INSERT INTO `AuthenticationSubscription` (`ueid`, `authenticationMethod`, `encPermanentKey`, `protectionParameterId`, `sequenceNumber`, `authenticationManagementField`, `algorithmId`, `encOpcKey`, `encTopcKey`, `vectorGenerationInHss`, `n5gcAuthMethod`, `rgAuthenticationInd`, `supi`) VALUES
后跟的即为 AMF 网元中存储的 UE 信息,包括 IMSI、KEY 和 OPC 等,UE 配置文件中的相关配置项必须事先在数据库中录入,否则 UE 无法完成注册和鉴权步骤。
DNN 的全称是 Data Network Name,可将其理解为 4G 网络中 APN(Access Point Name,接入点名称)的演进与等效概念。DNN 的相关配置位于 docker-compose/conf/basic_nrf_config.yaml 文件中:
snssais:
- &embb_slice1
sst: 1
- &embb_slice2
sst: 1
sd: 000001 # in hex
- &custom_slice
sst: 222
sd: 00007B # in hex
smf_info:
sNssaiSmfInfoList:
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "oai"
- sNssai: *embb_slice2
dnnSmfInfoList:
- dnn: "oai.ipv4"
...
local_subscription_infos:
- single_nssai: *embb_slice1
dnn: "oai"
qos_profile:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
- single_nssai: *embb_slice2
dnn: "oai.ipv4"
qos_profile:
5qi: 9
session_ambr_ul: "100Mbps"
session_ambr_dl: "200Mbps"
...
upf:
support_features:
enable_bpf_datapath: no # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_snat: yes # If "on": Source natting is done for UE, DEFAULT= off
remote_n6_gw: localhost # Dummy host since simple-switch does not use N6 GW
smfs:
- host: oai-smf # To be used for PFCP association in case of no-NRF
upf_info:
sNssaiUpfInfoList:
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "oai"
- sNssai: *embb_slice2
dnnUpfInfoList:
- dnn: "oai.ipv4"
...
## DNN configuration
dnns:
- dnn: "oai"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.1.128/25"
- dnn: "oai.ipv4"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.1.64/26"
...
从 SMF 和 UPF 的相关配置中可以看出,一个 DNN 与一种 sst-sd 配置存在一一对应关系。并且 DNN 的选择还直接决定了 UE 业务流的 5QI 等级、会话聚合最大比特速率(Aggregate Maximum Bit Rate, AMBR)和被分配的 IP 地址范围。
6.4.3 gNB 配置文件修改
针对 gNB 配置文件的修改主要集中在以下两处:

gNB_ID和gNB_name会作为 gNB 信息的一部分体现在核心网 AMF 的日志中,可根据实际需要随意设置。tracking_area_code、mcc、mnc须分别与docker-compose/conf/basic_nrf_config.yaml文件中 AMFplmn_support_list配置项下的参数匹配:
amf:
amf_name: "OAI-AMF"
...
plmn_support_list:
- mcc: 208
mnc: 95
tac: 0xa000
nssai:
- *embb_slice1
- *embb_slice2
- *custom_slice
mnc_length默认值为 2,保持不变。sst和sd的取值组合须在docker-compose/conf/basic_nrf_config.yaml文件中有对应的snssais预设值,这里sst = 1; sd = 1;对应snssais为embb_slice2的情况。nr_cellid为小区 ID,可根据实际需要随意设置。

6.4.1 节已经指定了各网元的稳定 IP 地址,因此 amf_ip_address 项的 ipv4 地址可固定为 192.168.70.132;GNB_IPV4_ADDRESS_FOR_NG_AMF 和 GNB_IPV4_ADDRESS_FOR_NGU 填写 gNB 上连接核心网服务器的物理接口 IP 地址。
6.4.4 nrUE 配置文件修改
nrUE 配置文件中需要修改的部分集中在上半段的 uicc0 部分:

imsi、key、opc:均需在docker-compose/database/oai_db2.sql中已有相应配置,其中imsi字段数值与数据库中ueid字段数值一致,key字段数值与数据库中encPermanentKey字段数值一致,opc字段数值与数据库中encOpcKey字段数值一致。dnn:须为docker-compose/conf/basic_nrf_config.yaml中dnns配置中的一项。nssai_sst、nssai_sd:须与dnn所对应的snssai配置中的sst和sd值分别对应。
7. 5G NR SA RF Simulator 模式地面场景系统启动和运行
整个 OAI 系统各组成部分均须按以下顺序启动:5GC → gNB → nrUE。目前三者均部署于同一服务器。
除非另外提及,否则部署 5GC 所使用的配置文件均为 docker-compose/docker-compose-basic-nrf.yaml。
7.1 单 UE 全链路双向通信
本小节所使用的配置文件:
gNB:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf;nrUE:
targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf。
7.1.1 核心网启动
执行如下命令以在后台启动核心网:
$ cd <oai-cn5g-fed directory>
$ cd docker-compose
$ docker compose -f docker-compose-basic-nrf.yaml up -d
应有 9 个容器被启动,各容器状态均应为 Started:

可执行以下命令以查看容器健康状态、开放的端口等信息:
$ docker compose -f docker-compose-basic-nrf.yaml ps -a

执行以下命令以查看容器日志:
$ docker logs -f oai-amf
在未启动 gNB 和 nrUE 的条件下,oai-amf 应周期性刷新如下日志内容:

使用如下命令以解除核心网部署:
$ docker compose -f docker-compose-basic-nrf.yaml down -t2
7.1.2 gNB 启动
另起一 terminal,执行如下命令以启动 gNB:
$ cd <openairinterface5g directory>
$ cd cmake_targets/ran_build/build
$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim
gNB 完成初始化并正常启动后应周期性输出当前帧号时隙号信息,如下所示:

若 gNB 成功连接至核心网,则 AMF 日志应体现 gNB 的状态为 Connected,并显示其全局 ID、gNB 名称及 PLMN 信息:

7.1.3 nrUE 启动
另起一 terminal,执行如下命令以启动 nrUE:
$ cd <openairinterface5g directory>
$ cd cmake_targets/ran_build/build
$ sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf
7.1.4 随机接入
nrUE 完成初始化后,会自动发起初始接入和随机接入流程,如下所示:

nrUE 作为 RF Simulator 客户端与服务端 127.0.0.1:4043 采用 TCP 协议通过 socket 接口进行通信。nrUE 在初始接入过程依次完成以下步骤:
扫频与小区驻留:nrUE 对其所支持的频段进行扫描,检测 gNB 广播的 SSB,解码其中的 PBCH;
解码 PSS 和 SSS:通过解码 PSS 和 SSS,计算获得小区 ID,并实现下行时间频率同步。
RF Simulator 模式下不体现波束成形和波束配对的过程。
通过包括 SIB1 在内的系统信息获得网络信息后,nrUE 开始基于竞争的四步随机接入过程(Contention Based Random Access, CBRA):
第 901 帧的第 19 个时隙为一个随机接入时机(RACH Occasion, RO),nrUE 在该时隙发送 PRACH;
nrUE 在第 902 帧的第 10 个时隙收到 Msg2 (RAR),解析获得包括 TA Command 在内的信息;
nrUE 在第 902 帧的第 19 个时隙发送 Msg3;
nrUE 在第 903 帧的第 12 个时隙收到 Msg4,认为 CBRA 过程已结束,RRC 状态转为
RRC_CONNECTED态,并新增 SRB1 以传输后续控制信令。
相应地,gNB 侧也有相关日志回显:

nrUE 采用 127.0.0.1:210 与 gNB 进行 socket 通信。gNB 侧进行 CBRA 的步骤:
gNB 在第 901 帧的第 19 个时隙收到 PRACH,为该 nrUE 分配 TC-RNTI 0xba29;
在第 902 帧的第 10 个时隙发送 Msg2;
在第 902 帧的第 19 个时隙收到 Msg3,并新增 SRB1 以传输后续控制信令;
调度、生成并发送 Msg4 (根据 nrUE 侧日志,gNB 应是在第 903 帧的第 12 个时隙发送 Msg4),为接收 Msg4 ACK调度资源;
gNB 在第 903 帧的第 18 个时隙收到 Msg4 ACK,将 TC-RNTI 升级为 C-RNTI。
7.1.5 注册、鉴权、建立 PDU 会话
nrUE 完成随机接入后,自动发起面向核心网的注册、鉴权和建立 PDU 会话等流程。
nrUE 侧日志:

nrUE 生成并向核心网 AMF 发送注册请求,然后依次接收并处理 securityModeCommand、UECapabilityEnquiry等信令,返回 UECapabilityInformation,在收到注册接受信令后发送 RegistrationComplete 信令,紧接着发送 PduSessionEstablishRequest 信令以请求建立 PDU 会话,相应地新创建 SRB1 和 DRB1 以开展后续传输,最后收到 PduSessionEstablishmentAccept 信令并拿到核心网为 nrUE 分配的 IP 地址(图中为 12.1.1.66)。
gNB 侧日志:

gNB 侧日志展现了一些更为详尽的日志,在此不做详细分析。nrUE 拿到 IP 后,gNB 与之进行随机数据交互,并以 128 帧为周期输出 nrUE 上下行信道信息和 MAC 层收发字节数。
nrUE 成功建立 PDU 会话后,核心网 AMF 日志应体现:

nrUE 状态应为 5GMM-REGISTERED,IMSI 应与 nrUE 配置文件中相同,Cell Id 应与 gNB 配置文件中相同。
同时,执行 ifconfig oaitun_ue1 应能查看到 nrUE 的虚拟网卡信息:

oaitun_ue1 的 IP 地址与 nrUE 侧日志中 nrUE 被分配到的 IP 地址相同,均为 12.1.1.66。
7.1.6 业务验证
OAI 核心网中提供了外部数据网络(oai-ext-dn)网元来模拟通过核心网能连接和访问到的外部网络,其可以是互联网(Internet)、企业内部专网(Intranet),或是运营商提供的特定服务网络,如 IP 多媒体子系统(IMS)等。如果从 oaitun_ue1 能够访问到 oai-ext-dn,则表明该 nrUE具备与外部网络进行业务交互的能力。由 6.4.1 节可知,oai-ext-dn 的 IP 地址为 192.168.70.135。
下面将采用 ping 和 iperf 两种方式对 nrUE 的业务可用性进行验证。
7.1.6.1 ping 验证
ping 默认通过本机网卡 IP 进行收发包,因此需要指定发起 ping 的源地址,命令如下:
$ ping 192.168.70.135 -I oaitun_ue1 -c 5
其中,-I <接口名称或地址> 指定发起 ping 的接口,-c x 表示进行 x 次 ping 包。
以 oai-ext-dn 作为 ping 发起方,需要先进入该容器,再发起 ping,命令如下:
$ docker exec -it oai-ext-dn /bin/bash
$ ping 12.1.1.66 -I 192.168.70.135 -c 5
测试结果如下所示:


可以通过两张截图各自回显的第一行确认 ping 包源地址是否正确。由于 ping 采用的是 ICMP 协议,该协议属于网络层,因此可以认为通信双方在网络层是互通的。
7.1.6.2 iperf 验证
适用于 AMD CPU 的 ieprf 软件须另行安装。先同构可联网的计算机前往 下载地址 下载 deb 安装包,迁移至离线服务器再进行安装,安装命令参见 5.1 节。
采用 iperf 进行灌包测试可选用 UDP 协议或 TCP 协议,以下均以 UDP 协议为例进行测试。应注意的是,虽然在 UDP 协议中没有服务端(Server)和客户端(Client)的概念,但在 iperf 中必须指定,可将服务端理解为 UDP 包接受方,客户端理解为 UDP 包发送方。
下行方向,以 nrUE 为服务端,执行如下命令以启动监听:
$ iperf -s -u -B 12.1.1.66 -i 1
其中,-s 指示本进程作为 iperf 服务端启动;-u 指示采用 UDP 协议;-B <IP Address> 表示监听的 IP 地址;-i x 表示以 x 秒为间隔输出测试结果。
oai-ext-dn 为客户端,执行如下命令以发送 UDP 包:
$ docker exec -it oai-ext-dn /bin/bash
$ iperf -c 12.1.1.66 -u --bind 192.168.70.135 -i 1 -b 250M
其中,-c 指示本进程作为 iperf 客户端启动;-u 指示采用 UDP 协议;--bind <IP Address> 表示发包的 IP 地址;-i x 表示以 x 秒为间隔输出测试结果;-b <Bandwidth> 指示发包速率,单位为 bps。
测试结果如下,在时长为 10s 的测试中,共传输 313M 字节,平均带宽达到 262 Mbps,平均抖动 0.058ms,共传输 222916 个数据包且无一丢包。


上行方向,以 oai-ent-dn 为服务端,执行如下命令以启动监听:
$ docker exec -it oai-ext-dn /bin/bash
$ iperf -s -u -B 192.168.70.135 -i 1
nrUE 为客户端,执行如下命令以发送 UDP 包:
$ iperf -c 192.168.70.135 -u --bind 12.1.1.66 -i 1 -b 100M
测试结果如下,在时长为 10s 的测试中,共传输 125M 字节,平均带宽达到 105 Mbps,平均抖动 0.162ms,共传输 89168 个数据包且无一丢包。


7.2 多 UE 全链路双向通信
本小节参考 NR_SA_Tutorial_OAI_multi_UE.md 及 telnetusage.md,采用 telnet server 在单台服务器上部署多部 nrUE。
OAI 提供的 telnet server 以共享库的形式实现,要使用该功能须执行如下命令:
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai --build-lib telnetsrv
构建成功后会在 cmake_targets/ran_build/build 目录下创建 libtelnetsrv.so 以及 libtelnetsrv_<app> 文件,其中 <app> 为enb、gnb、 4GUE、 5GUE、 ci 或 ciUE 中的一项。
注意:
- 多部 nrUE 均须与 gNB 进程运行在同一物理服务器;
- 须为每部 nrUE 单独创建一个命名空间,且每个命名空间拥有不同的地址,该地址将用作 RF Simulator server 的地址;
- 每部 nrUE 须具有不同的 IMSI,且该 IMSI 须存在于 MySQL 数据库的相应表中;
- 每部 nrUE 须在不同端口上运行 telnet server,通过命令行选项
--telnetsrv.listenport指定。
执行如下命令以为 nrUE-1 创建命名空间,并在其中执行 shell 命令:
$ cd <OAI directory>/tools/scripts
$ sudo ./multi-ue.sh -c1
$ sudo ./multi-ue.sh -o1
进入 bash 环境后,执行以下命令以启动 nrUE-1(确保 5GC 与 gNB 均已启动并正常运行):
$ cd ../../cmake_tarets/ran_build/build
$ sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.201.1.100 --telnetsrv --telnetsrv.listenport 9095
nrUE-1 的运行状态及日志输出应与不使用 telnet server 情形下的表现一致,且能在核心网完成注册、鉴权和建立 PDU 会话,通过 ifconfig 也能查询到 oaitun_ue1 的 IP 地址。
执行如下命令以为 nrUE-2 创建命名空间,并在其中执行 shell 命令:
$ cd <OAI directory>/tools/scripts
$ sudo ./multi-ue.sh -c2
$ sudo ./multi-ue.sh -o2
进入 bash 环境后,执行以下命令以启动 nrUE-2(确保 5GC 与 gNB 均已启动并正常运行):
$ cd ../../cmake_tarets/ran_build/build
$ sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue2.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.202.1.100 --telnetsrv --telnetsrv.listenport 9096
相较于 nrUE-1 的启动命令,变化有以下三点:
- nrUE 配置文件不同,且配置文件中这些 nrUE 的 IMSI 均相异,必要时须手动添加配置文件;
- 通过
--rfsimulator.serveraddr指定的 telnet server 地址不同,变化规律为,针对第x部 nrUE,其该配置项所指定的点分十进制 IP 地址的第二项数值为200 + x; - 通过
--telnetsrv.listenport指定的端口不同,新启动的 nrUE 通过该配置项所指定的端口号须异于先前所有以此法指定的端口号。
以同样的方式启动第三部 nrUE:
$ cd <OAI directory>/tools/scripts
$ sudo ./multi-ue.sh -c3
$ sudo ./multi-ue.sh -o3
$ cd ../../cmake_tarets/ran_build/build
$ sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue3.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.203.1.100 --telnetsrv --telnetsrv.listenport 9097
待第三部 nrUE 在核心网完成注册、鉴权和建立 PDU 会话后,对当前三部 nrUE 分别开展业务验证,结果如下:

由左上方核心网 AMF 日志可知,在 gNB 正常连接至核心网的前提下,三部 nrUE 均处于 5GMM-REGISTERED 态;由左下方 gNB 日志可知,gNB 管理着三部具有相异 C-RNTI 的 nrUE,能够正常周期性输出上下行链路数据统计情况;由右侧自上而下三列 ping oai-ext-dn 的结果可知,三部具有不同 IP 地址的 nrUE 均可与 oai-ext-dn 进行交互。
以 nrUE-1 为 iperf 服务端,nrUE-3 为 iperf 客户端进行灌包测试:
# in nrUE-1 terminal
$ iperf -s -u -B 12.1.1.66 -i 1
# in nrUE-3 terminal
$ iperf -c 12.1.1.66 -u --bind 12.1.1.68 -i 1 -b 30M
结果如下:


以上测试结果表明,可以实现连接至同一 gNB 的两部 nrUE 之间的通信。
综上,以此法可以实现在单台服务器上部署多 nrUE 的目的。
7.3 基站间切换
本小节参考 handover-tutorial.md。
基站间切换可分为两类:
基于 F1 接口的切换,gNB 采用 CU-DU 分离架构,两部 DU 连接至同一 CU,实现从 DU-0 切换至 DU-1;
基于 N2 接口的切换,实现从 gNB-0 切换至 gNB-1。
当前 UE 侧未实现测量报告和处理 RRC 移动性重配的功能,因此无法实现自主切换,必须手动以 telnet 的方式触发。通过 build_oai 脚本构建 telnet 功能:
$ cd <OAI directory>/cmake_targets
$ sudo ./build_oai --build-lib telnetsrv
7.3.1 基于 F1 接口的切换
本小节使用的配置文件:
gNB-CU:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf;gNB-DU0:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf;gNB-DU1:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf;nrUE:
targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf。
须注意,各 DU 的 ID (CU 侧标识)、小区 ID (全局标识)、物理小区 ID (供 UE 识别)、频率(OAI UE 自身限制)和 IP 地址均需互异。
启动 gNB-CU:
$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf --telnetsrv --telnetsrv.shrmod ci
启动 gNB-DU0:
$ sudo ./nr-softmodem --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf --rfsimulator.[0].serveraddr 127.0.0.1
gNB-DU0 启动后,屏幕会循环输出 [HW] connect() to 127.0.0.1:4043 failed, errno(111),这是正常现象。为了实施切换,RF Simulator 模式将 nrUE 作为 server,启动 nrUE 完成连接后该告警即消失。
启动 nrUE:
$ sudo ./nr-uesoftmodem -C 3450720000 -r 106 --numerology 1 --ssb 516 -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --rfsim --rfsimulator.[0].serveraddr server
nrUE 完成注册、鉴权、建立 PDU 会话后,此时 CU 和 DU-0 的日志:


启动 gNB-DU1:
$ sudo ./nr-softmodem --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf --rfsimulator.[0].serveraddr 127.0.0.1
此时 5GC AMF 日志如下。在 CU-DU 分离的场景下,DU 信息不体现在 5GC 中。

完成以上部署后,再另起一 terminal,执行以下命令以发起切换:
$ echo ci trigger_f1_ho | nc 127.0.0.1 9090 && echo
上述切换指令也可以分步执行:
首先登录进 telnet:
$ telnet 127.0.0.1 9090
然后再执行:
$ ci trigger_f1_ho <cu_ue_id>
其中,cu-ue-id 是可选参数。如果 RRC 中只有一个 UE 上下文,则会以轮询(round‑robin)方式在所有 DU 间为该 UE 触发切换;如果只有一个 DU,切换请求将被拒绝。而如果 RRC 中存在多个 UE 上下文,切换也会被拒绝,此时必须手动输入 cu-ue-id,可以在 CU 工作目录下的 nrRRC_stats.log 文件中查看所有 UE 的列表。
执行切换后,nrUE、DU0、DU1的日志分别如下:



注意:
DU0 和 DU1 应使用不同的 SSB,即确保在 DU0(例如设为 1)和 DU1(例如设为 2)的配置文件中,将 ssb_PositionsInBurst_Bitmap 设置为在不同的时隙发送 SSB;
务必按顺序启动 DU0、UE、DU1,并在启动 DU1 之前让 UE 先连接到 DU0。这是因为在上述场景中没有进行信道仿真,UE 可能无法解码 DU0 的 SIB1,从而无法连接;
通常,gNB 侧的 RFsim 作为服务器,UE 作为客户端。但 RFsim 限制为一台服务器对应多个客户端。由于 UE 需要能够同时连接到两个 DU,因此 UE 必须作为服务器,而两个 DU 作为客户端;
如果出现
could not open a socket和/或Could not start the RF device的错误,这表示 RF Simulator 未能启动,将无法实施切换,通过使 UE 作为 RF Simulator 服务器运行来解决上述问题;在某些情况下,RF Simulator 服务器位于 UE 端时可能会导致整个系统发生阻塞,这时需要停止 UE 和所有 DU,然后重新启动之(CU 可以保持运行状态)。
7.3.2 基于 N2 接口的切换(失败)
本小节使用的配置文件:
gNB0:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf;gNB1:
targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf;nrUE:
targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf。
须注意,如果在同一服务器上部署多部 gNB,则至少需要与 gNB 数量等同的网卡,通过为不同 gNB 指定不同的 IP 来避免网络冲突。执行以下指令以手动为网卡指定 IP 地址:
$ sudo ip addr add IP_ADDR dev NIC_NAME
启动源 gNB(gNB-PCI0):
$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci0.rfsim.conf --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.serveraddr 127.0.0.1
启动 nrUE:
$ sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --rfsimulator.serveraddr server
启动目标 gNB(gNB-PCI1):
$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf --rfsim --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsimulator.serveraddr 127.0.0.1
注意:官方教程中提到,如果在同一服务器上运行两部 gNB,则需要在启动目标 gNB 的指令中添加如下的网络接口选项:
--gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF 192.168.71.180 --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 192.168.71.180
此时 5GC AMF 日志如下。

执行如下命令以实施切换:
$ echo ci trigger_n2_ho 1,1 | nc 127.0.0.1 9090 && echo
其中,trigger_n2_ho 后跟的第一个 1 表示实施切换的目标小区的 PCI,第二个 1 表示 UE 的 RRC ID。
遇到问题:执行切换指令后,AMF 日志查看会被终止,且 nrUE 并未切换至目标 gNB。AMF 日志刷新终止前的部分日志如下:
n2_handover_error.png根据内容,初步判定是切换请求被拒绝,导致该现象的成因未知,待后续查看和解决。
8. 5G NR RF Simulator 模式 NTN 场景系统启动和运行
本节参考 How to run a NTN configuration。
NTN 场景可通过以下两种方式实现配置:
- 使用 SDR 板和专用 NTN 信道模拟器;
- 为 RF Simulator 配置模拟 NTN 信道。
在 RF Simulator 模式下,要实现对 GEO 卫星场景的简单模拟,只需将以下参数添加到启动 gNB 和 UE 的命令行中:
--rfsimulator.prop_delay 238.74
对于 LEO 卫星场景的仿真,RF Simulator 中已经预置了两类信道模型(但从源码实现来看,目前两类信道模型的处理方式完全相同):
- SAT_LEO_TRANS:LEO 星载透明载荷;
- SAT_LEO_REGEN:LEO 星载再生载荷。
上述信道模型都根据 Matlab 函数 dopplerShiftCircularOrbit 模拟了高度为 600 公里的圆形轨道的时延和多普勒效应。使用 RF Simulator 模拟透明的低地球轨道卫星的示例配置如下:
channelmod = {
max_chan = 10;
modellist = "modellist_rfsimu_1";
modellist_rfsimu_1 = (
{
model_name = "rfsimu_channel_enB0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
},
{
model_name = "rfsimu_channel_ue0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
}
);
};
该配置在文件 targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf 中提供。
在此基础上,必须对 RF Simulator 进行配置以应用信道模型,这可以通过在 conf 文件的 RF Simulator 部分添加以下行来完成:
options = ("chanmod");
或在命令行中指定如下参数:
--rfsimulator.options chanmod
在 gNB 侧,与大 NTN 传播延迟相关的主要参数是 cellSpecificKoffset、ta-Common、ta-CommonDrift 以及星历数据(卫星的位置和速度矢量)。
参数 ntn-UlSyncValidityDuration-r17 表示从纪元时间开始到 UE 可以在未获取新辅助信息的情况下应用已有辅助信息的最长持续时间。即,这允许 UE 可以在具有 ulSyncValidityDuration 值的定时器超时之前重新获取 SIB19。该字段的单位为秒。GEO 的示例值为 240 秒,MEO 为 20 秒,LEO 为 5 秒。由于当前纪元时间尚未实现,UE 将从接收到带有 ntn-UlSyncValidityDuration-r17 IE 的 SIB19 的 TTI 开始计时。
参数 cellSpecificKoffset_r17 用于为 NTN 适配的时序关系的调度偏移 (见 TS 38.213)。Koffset 字段的单位为给定的15 kHz子载波间隔下的时隙数。
参数 ta-Common-r17 用于提供参考点与卫星之间的传播延迟。ta-Common 的粒度为 4.072 × 10^(-3) 微秒。
参数 ta-CommonDrift-r17 表示公共 TA 的漂移速率。ta-CommonDrift 的粒度为 0.2 × 10^(-3) 微秒/秒。
卫星的位置和速度矢量由以下参数提供:
positionX-r17,positionY-r17,positionZ-r17:卫星位置状态向量在 ECEF 坐标系中的X、Y、Z坐标。步长为1.3,即实际值 = 字段值 * 1.3,单位为米。velocityVX-r17,velocityVY-r17,velocityVZ-r17:卫星速度状态向量在 ECEF 坐标系中的 X、Y、Z 坐标。步长为 0.06 m/s,即实际值 = 字段值 * 0.06,单位为 m/s。
以上参数都在配置文件的 servingCellConfigCommon 小节中提供给 gNB:
# GEO satellite
cellSpecificKoffset_r17 = 478;
ta-Common-r17 = 58629666; # 238.74 ms
positionX-r17 = 0;
positionY-r17 = 0;
positionZ-r17 = 32433846;
velocityVX-r17 = 0;
velocityVY-r17 = 0;
velocityVZ-r17 = 0;
# LEO satellite
# cellSpecificKoffset_r17 = 40;
# ta-Common-r17 = 4634000; # 18.87 ms
# ta-CommonDrift-r17 = -230000; # -46 µs/s
# positionX-r17 = 0;
# positionY-r17 = -2166908; # -2816980.4 m
# positionZ-r17 = 4910784; # 6384019.2 m
# velocityVX-r17 = 0;
# velocityVY-r17 = 115246; # 6914.76 m/s
# velocityVZ-r17 = 50853; # 3051.18 m/s
此外,一些位于配置文件 gNBs.[0].TIMERS 小节中的定时器,例如 sr_ProhibitTimer_v1700, t300, t301 和 t319,可能需要在 GEO 卫星仿真的场景下额外指定其数值:
TIMERS :
{
sr_ProhibitTimer = 0;
sr_TransMax = 64;
sr_ProhibitTimer_v1700 = 512;
t300 = 2000;
t301 = 2000;
t319 = 2000;
};
为了在大时延(尤其是 GEO 卫星)条件下提高上行和下行吞吐量,R17 中定义了一个功能来禁用 HARQ 反馈,该功能允许立即重用 HARQ 进程,但会导致与不支持 R17 的 UE 不兼容。要启用此功能,必须在 gNB 配置文件的 gNBs.[0] 部分添加 disable_harq 标志。
···
sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1; // <--
servingCellConfigCommon = (
{
···
如果要在上下行配置具有 32 个 HARQ 进程 的 NTN gNB,需要在配置文件的 gNBs.[0] 部分添加以下配置:
num_dlharq = 32;
num_ulharq = 32;
要使用 RF Simulator 在上行链路模拟 LEO 卫星信道模型(下行链路在 UE 端模拟),必须将先前所述的 channelmod 部分添加到 gNB 配置文件中,或者以如下方式 include 一个 channelmod 配置文件:
@include "channelmod_rfsimu_LEO_satellite.conf"
在 nrUE 侧,只需提供少量参数,因为 UE 通过 SIB19 从 gNB 接收大部分参数,但由于要计算 UE-specific TA,因此必须在 ue.conf 文件中提供 UE 位置信息。此外,还必须配置 LEO 信道模型,例如使用 @include 语句:
position0 = {
x = 0.0;
y = 0.0;
z = 6377900.0;
}
@include "channelmod_rfsimu_LEO_satellite.conf"
针对 LEO 卫星场景,必须通过命令行提供参数 --ntn-initial-time-drift,因为 UE 在接收到 SIB19 之前,需要该值来补偿初始同步期间的时间漂移。该参数提供完整下行链路(包括馈送链路和服务链路)时序的漂移率,单位为 µs/s。此外,在 LEO 卫星场景下,如果需要根据下行链路漂移执行自主 TA 更新,还应添加布尔参数 --autonomous-ta。
在 LEO 卫星场景,假设本地振荡器(LO)非常精确,主要的频偏(FO)贡献来自多普勒效应。因此,使用命令行参数 --cont-fo-comp 2 来持续补偿下行链路的多普勒效应,并预补偿上行链路的多普勒效应。初始多普勒频偏必须通过命令行参数 --initial-fo 提供。
8.1 单 UE 在透明转发卫星场景下的全链路双向通信
透明载荷 GEO 卫星场景的设置已经在文件 ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf 中提供。在 5GC 已启动的前提下,使用该配置文件,启动 FDD、5 MHz 带宽、15 kHz 子载波间隔的 5G NR NTN gNB 示例命令如下:
$ cd <OAI directory>/cmake_targets/ran_build/build
$ sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf --rfsim
相应启动 nrUE 的命令如下:
$ cd <OAI directory>/cmake_targets/ran_build/build
$ sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74
系统运行情况如下所示:

透明载荷 LEO 卫星场景的配置已在文件 ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf 中提供。使用该配置文件,启用 FDD、5 MHz 带宽、15 kHz 子载波间隔的 5G NR NTN gNB 示例命令如下:
$ cd <OAI directory>/cmake_targets/ran_build/build
$ sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf --rfsim
相应启动 nrUE 的命令如下:
cd cmake_targets
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2
系统运行情况如下所示:

gNB 侧定时更新卫星轨道参数,包括 ECEF 坐标系下的位置和速度矢量、单程时延、nrUE 相对于卫星的多普勒频偏、卫星相对于位于地面的 gNB 的速度和加速度等;nrUE 侧也有相关的部分参数实时计算,如定时提前量、定时提前漂移、定时提前漂移变化量等。
9. 疑难问题及排除方法
9.1 构建项目时使用 ninja 工具构建失败
大概率为先前是否在构建时没有指定 --ninja 选项。可在先迁出 cmake_targets/ran_build/build/ 目录下的必要文件后,在 cmake_targets/ 目录下执行
$ sudo ./build_oai -C
清除所有已构建的接入网实例,再执行
$ sudo ./build_oai -w SIMU --nrUE --gNB --ninja
重新构建,并在之后的每次构建中都指定 --ninja 选项。
9.2 将 gNB 和 nrUE 的启动命令写入 bash 文件但运行时提示权限不足
具体体现为,即使使用管理员权限(sudo)执行 .sh 文件,依旧提示 Permission Denied。造成该问题的原因应为 .sh 文件不具备执行权限,可通过以下两种方式之一解决:
右击 .sh 文件“属性”的“权限”选项卡,检查“允许作为程序执行文件”设置项是否勾选,若未勾选则勾选之;
执行
chmod +x xxx.sh为 .sh 文件赋予执行权限,具体可参考 Linux chmod 命令详解。
修订历史
| 修订时间 | 版本号 | 说明 |
|---|---|---|
| 2026.3.3 | v0.9 | 完成 RF Simulator 模式下 gNB 与 nrUE 的连接,完成文档初稿 |
| 2026.7.21 | v1.0 | 构建 RF Simulator 模式下 5GC、gNB 与 nrUE 之间的双向通信链路,完成业务测试,使用 markdown 改写文档并进一步完善 |
| 2026.7.22 | v1.0.1 | 新增在单台服务器部署多部 nrUE 的内容(7.2节) |
| 2026.7.31 | v1.0.2 | 新增切换(7.3节)及 NTN 场景(第8节)的部署过程 |

