相比直接使用的ueransim,由于使用了docker进行了封装,所以以前的使用方法无法照搬,这里探索了容器化ueransim使用的方法,并最终达到使用nr-binder绑定自己的业务代码进行自定义数据的传输。
ueransim 的Dockerfile如下:
#---------------------------------------------------------------------
# BUILDER IMAGE
#---------------------------------------------------------------------
FROM ubuntu:bionic as ueransim-builder
RUN apt-get update -y && apt-get upgrade -y &&\
apt install -y make gcc g++ libsctp-dev lksctp-tools\
iproute2 wget software-properties-common git
RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null\
| gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null\
&& apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main'\
&& apt update && apt install -y cmake
RUN cmake --version
RUN git clone https://github.com/aligungr/UERANSIM.git && cd UERANSIM && git checkout -f v3.2.5
COPY docker/ /UERANSIM/docker/
RUN make -C UERANSIM
#---------------------------------------------------------------------
# TARGET IMAGE
#---------------------------------------------------------------------
FROM ubuntu:bionic as ueransim
RUN apt update && apt install -y iproute2 iputils-ping net-tools\
iperf3 libsctp-dev lksctp-tools
WORKDIR /ueransim/etc
COPY --from=ueransim-builder /UERANSIM/docker/custom*.yaml /ueransim/etc/
WORKDIR /ueransim/bin
COPY --from=ueransim-builder /UERANSIM/build/* /ueransim/bin/
COPY --from=ueransim-builder /UERANSIM/docker/entrypoint.sh .
ENTRYPOINT ["/ueransim/bin/entrypoint.sh"]
解析:
这是一个Dockerfile,它创建了两个镜像。第一个镜像名为“ueransim-builder”,基于“ubuntu:bionic”镜像。它安装了几个包和依赖项,例如make、gcc、g++、libsctp-dev、lksctp-tools、iproute2、wget、software-properties-common和git。然后它从Kitware的存储库中下载并安装最新版本的CMake。
然后,它从GitHub克隆了UERANSIM存储库,检出版本v3.2.5,并将“docker/”目录的内容复制到“/UERANSIM/docker/”目录。最后,它构建了UERANSIM项目。
第二个镜像名为“ueransim”,也基于“ubuntu:bionic”。它安装了一些包,如iproute2、iputils-ping、net-tools、iperf3、libsctp-dev和lksctp-tools。然后,它将“UERANSIM/docker/”目录中的自定义YAML配置文件复制到“/ueransim/etc/”。
接下来,它将构建好的UERANSIM二进制文件从“/UERANSIM/build/”复制到“/ueransim/bin/”。最后,它将从“/UERANSIM/docker/”复制“entrypoint.sh”脚本到“/ueransim/bin/”,将其设置为容器的入口点,并在容器启动时运行它。
ENTRYPOINT ["/ueransim/bin/entrypoint.sh"]
解析:1.ENTRYPOINT 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有其他传入值作为该命令的参数
2.ENTRYPOINT和CMD的区别:CMD # 指定这个容器启动的时候要运行的命令,不可以追加命令 而ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
#entrypoint文章 https://docker-practice.github.io/zh-cn/image/dockerfile/entrypoint.html?q=
构建容器的命令如下:
UERANSIM$ docker build --target ueransim --tag ueransim:latest -f docker/Dockerfile.ubuntu.18.04 .
#当您指定--target 选项时,您只需指定将生成的最后一个目标,这样之前的所有目标都将包含在生成过程中
知识点1:为什么有两个FROM?
使用多FROM指令可以完成多阶段编译。每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。
比如下面这种场景:
我们要构建一个c++应用程序的镜像,这个c++程序依赖了很多第三方库,那么我们的构建过程大概如下:
——————————————————————————————————————————————————————————
# c++语言环境基础镜像
FROM centos:7.0.3
#安装编译工具,gcc g++ gdb cmake ==
#安装第三方库
# 将源码拷贝到镜像中
COPY project /build/
# 指定工作目录
WORKDIR /build
# 编译镜像时,运行 make生成可执行程序
# 指定容器运行时入口程序 server
ENTRYPOINT ["/build/server"]
——————————————————————————————————————————————————————————————————————————--
这样会导致我们编译出来的镜像非常庞大,而我们最终要用的只是一个可执行程序以及它运行时依赖的动态库,不需要编译工具以及编译时依赖的第三方库的源代码。有了多FROM指令后,我们就可以这样实现这个过程:在基础镜像上安装编译工具->下载第三方库源代码->编译安装第三方库->编译自己的模块代码->将编译好的可执行文件拷贝到新的镜像中->将运行时依赖的动态库拷贝到新镜像中->修改新镜像中的环境变量,使之指向运行时依赖库的位置。dockerfile修改如下:
——————————————————————————————————————————————————————————————————————————
# c++语言环境基础镜像
FROM centos:7.0.3 AS build_base
#安装编译工具,gcc g++ gdb cmake ==
#安装第三方库
# 将源码拷贝到镜像中
COPY project /build/
# 指定工作目录
WORKDIR /build
# 编译镜像时,运行 make生成可执行程序
# 指定容器运行时入口程序 server
ENTRYPOINT ["/build/server"]
#这里重新启动一个镜像,将编译好的可执行文件和运行依赖库拷贝过来就可以了
FROM centos:7.0.3
COPY --from build_base ***.so .
COPY --from build_base /build/server .
#修改环境变量,使之指向动态库的目录
ENV LD_LIBRARY_PATH=./
——————————————————————————————————————————
我们最终用到的镜像就是最后一个FROM后生成的镜像,前边的FROM只是起到了一个辅助产生编译环境的作用。这也是多FROM特性比较常用的一个场景。
知识点2:dockerfile进一步解析
该dockerfile构建了第一个基础镜像为ueransim--builder,其中安装了编译ueransim用的应用,克隆了ueransim,然后对其进行编译,编译出来的成果供第二个镜像使用
构建的第二个镜像为ueransim,这也是最终使用的镜像,其中先安装了一些基础的应用,然后又将基础镜像中的一些文件clone到了该镜像中,最后通过ENTERPOINT设置容器启动时的进入点
#!/usr/bin/env bash
set -euo pipefail
CONFIG_DIR="/ueransim/etc"
# Default values
USE_FQDN=${USE_FQDN:-no}
SST_R=${SST_R:-$SST}
SD_R=${SD_R:-$SD}
if [[ ${USE_FQDN} == "yes" ]];then
NGAPPeerAddr=(`getent hosts $AMF_FQDN | awk '{print $1}'`)
echo -e "\nResolving AMF by FQDN : $AMF_FQDN - $NGAPPeerAddr"
fi
for c in ${CONFIG_DIR}/*.yaml; do
# grep variable names (format: ${VAR}) from template to be rendered
VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs)
echo "Now setting these variables '${VARS}'"
# create sed expressions for substituting each occurrence of ${VAR}
# with the value of the environment variable "VAR"
EXPRESSIONS=""
for v in ${VARS}; do
NEW_VAR=$(echo $v | sed -e "s#@##g")
if [[ -z ${!NEW_VAR+x} ]]; then
echo "Error: Environment variable '${NEW_VAR}' is not set." \
"Config file '$(basename $c)' requires all of $VARS."
exit 1
fi
EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g"
done
EXPRESSIONS="${EXPRESSIONS#';'}"
# render template and inline replace config file
sed -i "${EXPRESSIONS}" ${c}
done
echo "Done setting the configuration"
echo "### Running ueransim ###"
echo "Running gnb"
/ueransim/bin/nr-gnb -c /ueransim/etc/custom-gnb.yaml &
sleep 1
echo "Running ue"
/ueransim/bin/nr-ue -c /ueransim/etc/custom-ue.yaml -n $NUMBER_OF_UE
exec "$@"
这段代码是一个 Bash 脚本,具体内容如下:
设置 Shell 选项,set 命令加上选项 e、u 和 o pipefail。
e 选项会让脚本在任何命令以非零状态退出(即错误)时立即退出。
u 选项会将未设置的变量视为错误,导致脚本退出。
o pipefail 选项将管道的退出状态设置为最后一个以非零状态退出的命令的状态,以确保如果管道中的任何命令失败,则整个管道都将失败。
将 /ueransim/etc 路径赋给变量 CONFIG_DIR。
设置变量 USE_FQDN 的默认值为 "no"。
如果变量 USE_FQDN 的值为 "yes",则通过 getent 和 awk 命令解析 AMF_FQDN 的 IP 地址,并将 IP 地址存储在 NGAPPeerAddr 数组中。
遍历 ${CONFIG_DIR} 目录中的所有 YAML 文件,并针对每个文件进行以下操作:
从模板中提取变量名(格式为 ${VAR})。
为每个变量创建一个 sed 表达式,将 ${VAR} 替换为环境变量 VAR 的值。
应用 sed 表达式以生成新的配置文件。
运行 /ueransim/bin/nr-gnb 和 /ueransim/bin/nr-ue 命令启动 gNB 和 UE,并指定配置文件。
执行传入脚本的任何其他命令。
启动核心网
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-basic-vpp-nrf.yaml up -d
启动docker ueransim
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-ueransim-vpp.yaml up -d
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker logs ueransim
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim ping -I uesimtun0 www.baidu.com
到此已经证明ueransim可以正常工作,通过核心网传输ping的命令,并且连上了百度连上了外网
下一步需要验证如何通过像使用非docker版ueransim使用nr-binder来绑定其他应用
不成功,因为容器内部没有curl这个软件:
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim curl --interface uesimtun0 www.baidu.com
同样是无法使用:
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim ./nr-binder ping -I uesimtun0 www.baidu.com
那么就更谈不上使用nr-binder来进行自定义脚本的数据传输了
进入容器内部
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker exec -it ueransim /bin/bash
可以看见容器内部的文件,nr-binder 、nr-cli等都存在,但是nr-binder是白色的不是可执行的
讲nr-binder变为可执行的:
root@0ddce360fdba:/ueransim/bin# chmod 777 nr-binder
root@0ddce360fdba:/ueransim/bin# ./nr-binder 10.45.0.2 ping www.baidu.com
到这里发现了为什么外部无法使用nr-binder的原因,因为内部读写权限没有开启,nr-binder不是可执行文件
#在ueransim容器内部
apt-get update
apt install -y curl
./nr-binder 10.45.0.2 curl www.baidu.com
想要不进入容器内部,而是启动后就可以使用ueransim的nr-binder以及curl等,需要在原来的ueransim基础上构建自己的ueransim,有如下三种方式:
docker commit [选项] 容器ID/名称 仓库名称:[标签]
-m:说明信息
-a:作者信息
-p:生成过程中停止容器的运行
第一次尝试
查看容器id
lab@lab-virtual-machine:~$ docker ps -l
docker commit
docker commit 0ddce360fdba ueransim1
如上图已经生成了新的镜像:ueransim1 它的id为:040c63421d89
现在我们关掉之前的ueransim并接入新的ueransim1,测试其是否可以使用nr-binder以及curl
docker-compose -f docker-compose-ueransim-vpp.yaml down
打开ueransim启动的yaml文件,将其中启动的image由ueransim修改为ueransim1
sudo vim docker-compose-ueransim-vpp.yaml
docker-compose -f docker-compose-ueransim-vpp.yaml up -d
发现容器启动不了
第二次尝试
第一次由于在里面进行了很多测试,比如ping以及使用curl等,这一次进入只下载curl以及更改nr-binder的权限,然后exit退出
然后使用commit提交为ueransim2
然后再次进行尝试
依旧不行
第三次尝试
这次只进行chmod 777 nr-binder ,但是依旧失败
综上,暂时放弃使用commit方法了固件ueransim镜像。
先从网上下载docker版ueransim源码
https://github.com/orion-belt/UERANSIM
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim$ git clone https://github.com/orion-belt/UERANSIM.git
然后修改Dockerfile,在下载的时候多加入了一个curl
由于本机上已经存在一个ueransim:latest ,所以此次构建的为ueransim:latest1
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM$ docker build --target ueransim --tag ueransim:latest1 -f docker/Dockerfile.ubuntu.18.04 .
需要几十分钟的等待…
注意网络要好,其中下载应用程序以及clone代码时都需要网络
再对启动ueransim的yaml文件进行修改,使用新构建的ueransim:1.1
然后再启动ueransim:
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-ueransim-vpp.yaml up -d
依旧是失败:
这里对Dockerfile不作修改镜像build,看是否可以成功启动接入:
依旧是失败
刚刚发现官方的命令如下:
$ git clone -b docker_support https://github.com/orion-belt/UERANSIM.git
$ cd UERANSIM
$ docker build --target ueransim --tag ueransim:latest -f docker/Dockerfile.ubuntu.18.04 .
其中使用的clone是
git clone -b docker_support
该方法选择了分支 docker_support
而我之前clone的是master里的内容,进行的操作也全是基于此代码,因此可能代码有错,这里后面clone正确的分支进行尝试
再次构建镜像:
$ docker build --target ueransim --tag ueransim:latest -f docker/Dockerfile.ubuntu.18.04 .
在网上搜索错误原因后经过尝试找到了进入容器的方法:
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM/docker$ docker run -it ueransim /bin/bash
然后进行测试curl:
发现安装的curl可以正常使用,容器立刻退出的原因是容器启动后没有任务,entrypoint里的脚本没有正确执行,使用如下方法也可以使用curl
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM/docker$ docker run -it ueransim /bin/bash
可以发现与之前的容器日志完全不同,没有启动gnb也没有启动ue。
前面几次尝试可以确定通过更改dockerfile确实可以成功安装软件以及修改文件权限,而没有最终成功容器总是秒退的原因是容器内没有持续运行的程序,也就是gnb与ue没有成功启动(可以说没有尝试过启动),需要探索entrypoint让脚本正常运行。
尝试直接启动entrypoint.sh,但是失败
sudo docker run -it ueransim:yz bash /ueransim/bin/entrypoint.sh
根据报错信息可以发现sh脚本中传递参数时出错了
查看之前正确的日志:
发现使用的参数文件与oai的参数挺不一样的
进入官方正确的容器内部查看配置文件等,来看是否有差异
先启动官方的ueransim,再进入容器内部,下载vim查看yaml文件
#启动容器
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-ueransim-vpp.yaml up -d
#进入容器内部
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker exec -it ueransim /bin/bash
#安装vim
apt-get update
apt-get install vim
果然找到了问题的真正原因,配置文件的问题,直接下载镜像的配置文件是没有更改的,官方的ueransim容器中的配置文件如下:
mcc: '208' # Mobile Country Code value
mnc: '95' # Mobile Network Code value (2 or 3 digits)
nci: '0x000000010' # NR Cell Identity (36-bit)
idLength: 32 # NR gNB ID length in bits [22...32]
tac: 0xa000 # Tracking Area Code
linkIp: 192.168.70.141 # gNB's local IP address for Radio Link Simulation (Usually same with local IP)
ngapIp: 192.168.70.141 # gNB's local IP address for N2 Interface (Usually same with local IP)
gtpIp: 192.168.72.141 # gNB's local IP address for N3 Interface (Usually same with local IP)
# List of AMF address information
amfConfigs:
- address: 192.168.70.132
port: 38412
# List of supported S-NSSAIs by this gNB
slices:
- sst: 222
sd: 123
- sst: 1
sd: 0
- sst: 129
sd: 129
# Indicates whether or not SCTP stream number errors should be ignored.
ignoreStreamIds: true
supi: 'imsi-208950000000041'
# Mobile Country Code value of HPLMN
mcc: '208'
# Mobile Network Code value of HPLMN (2 or 3 digits)
mnc: '95'
# Permanent subscription key
key: '0C0A34601D4F07677303652C0462535B'
# Operator code (OP or OPC) of the UE
op: '63bfa50ee6523365ff14c1f45f88737d'
# 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: '0035609204079514'
# List of gNB IP addresses for Radio Link Simulation
gnbSearchList:
- 192.168.70.141
# 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: 'default'
slice:
sst: 222
sd: 123
# Configured NSSAI for this UE by HPLMN
configured-nssai:
- sst: 222
sd: 123
# Default Configured NSSAI for this UE
default-nssai:
- sst: 222
sd: 123
# 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'
#!/usr/bin/env bash
set -euo pipefail
CONFIG_DIR="/ueransim/etc"
# Default values
USE_FQDN=${USE_FQDN:-no}
SST_R=${SST_R:-$SST_0}
SD_R=${SD_R:-$SD_0}
SST_0=${SST_0:-128}
SD_0=${SD_0:-128}
SST_1=${SST_1:-1}
SD_1=${SD_1:-0}
SST_2=${SST_2:-129}
SD_2=${SD_2:-129}
if [[ ${USE_FQDN} == "yes" ]];then
NGAPPeerAddr=(`getent hosts $AMF_FQDN | awk '{print $1}'`)
echo -e "\nResolving AMF by FQDN : $AMF_FQDN - $NGAPPeerAddr"
fi
for c in ${CONFIG_DIR}/*.yaml; do
# grep variable names (format: ${VAR}) from template to be rendered
VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs)
echo "Now setting these variables '${VARS}'"
# create sed expressions for substituting each occurrence of ${VAR}
# with the value of the environment variable "VAR"
EXPRESSIONS=""
for v in ${VARS}; do
NEW_VAR=$(echo $v | sed -e "s#@##g")
if [[ -z ${!NEW_VAR+x} ]]; then
echo "Error: Environment variable '${NEW_VAR}' is not set." \
"Config file '$(basename $c)' requires all of $VARS."
exit 1
fi
EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g"
done
EXPRESSIONS="${EXPRESSIONS#';'}"
# render template and inline replace config file
sed -i "${EXPRESSIONS}" ${c}
done
echo "Done setting the configuration"
echo "### Running ueransim ###"
echo "Running gnb"
/ueransim/bin/nr-gnb -c /ueransim/etc/custom-gnb.yaml &
sleep 1
echo "Running ue"
/ueransim/bin/nr-ue -c /ueransim/etc/custom-ue.yaml -n $NUMBER_OF_UE
exec "$@"
55,1 Bot
三个配置文件都修改为正确的后,修改Dockerfile加入curl,加入更改nr-binder的命令:
#---------------------------------------------------------------------
# BUILDER IMAGE
#---------------------------------------------------------------------
FROM ubuntu:bionic as ueransim-builder
RUN apt-get update -y && apt-get upgrade -y &&\
apt install -y make gcc g++ libsctp-dev lksctp-tools\
iproute2 wget software-properties-common git
RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null\
| gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null\
&& apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main'\
&& apt update && apt install -y cmake
RUN cmake --version
RUN git clone https://github.com/aligungr/UERANSIM.git && cd UERANSIM && git checkout -f v3.2.5
COPY docker/ /UERANSIM/docker/
RUN make -C UERANSIM
#---------------------------------------------------------------------
# TARGET IMAGE
#---------------------------------------------------------------------
FROM ubuntu:bionic as ueransim
RUN apt update && apt install -y iproute2 curl iputils-ping net-tools\
iperf3 libsctp-dev lksctp-tools
WORKDIR /ueransim/etc
COPY --from=ueransim-builder /UERANSIM/docker/custom*.yaml /ueransim/etc/
WORKDIR /ueransim/bin
COPY --from=ueransim-builder /UERANSIM/build/* /ueransim/bin/
COPY --from=ueransim-builder /UERANSIM/docker/entrypoint.sh .
WORKDIR /ueransim/bin
RUN chmod 777 nr-binder
ENTRYPOINT ["/ueransim/bin/entrypoint.sh"]
再次构建:
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM$ sudo docker build --target ueransim --tag ueransim:yz -f docker/Dockerfile.ubuntu.18.04 .
这里汇总了官方ueransim容器启动后内部的文件
先启动核心网再启动ueransim,然后进入容器内部
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker-compose -f docker-compose-basic-vpp-nrf.yaml up -d
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker-compose -f docker-compose-ueransim-vpp.yaml up -d
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker exec -it ueransim /bin/bash
#安装vim用来查看文件
root@5738f315511b:/ueransim/etc# apt-get update
root@5738f315511b:/ueransim/etc# apt-get install vim
mcc: '208' # Mobile Country Code value
mnc: '95' # Mobile Network Code value (2 or 3 digits)
nci: '0x000000010' # NR Cell Identity (36-bit)
idLength: 32 # NR gNB ID length in bits [22...32]
tac: 0xa000 # Tracking Area Code
linkIp: 192.168.70.141 # gNB's local IP address for Radio Link Simulation (Usually same with local IP)
ngapIp: 192.168.70.141 # gNB's local IP address for N2 Interface (Usually same with local IP)
gtpIp: 192.168.72.141 # gNB's local IP address for N3 Interface (Usually same with local IP)
# List of AMF address information
amfConfigs:
- address: 192.168.70.132
port: 38412
# List of supported S-NSSAIs by this gNB
slices:
- sst: 222
sd: 123
- sst: 1
sd: 0
- sst: 129
sd: 129
# Indicates whether or not SCTP stream number errors should be ignored.
ignoreStreamIds: true
custom-ue.yaml
# IMSI number of the UE. IMSI = [MCC|MNC|MSISDN] (In total 15 digits)
supi: 'imsi-208950000000041'
# Mobile Country Code value of HPLMN
mcc: '208'
# Mobile Network Code value of HPLMN (2 or 3 digits)
mnc: '95'
# Permanent subscription key
key: '0C0A34601D4F07677303652C0462535B'
# Operator code (OP or OPC) of the UE
op: '63bfa50ee6523365ff14c1f45f88737d'
# 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: '0035609204079514'
# List of gNB IP addresses for Radio Link Simulation
gnbSearchList:
- 192.168.70.141
# 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: 'default'
slice:
sst: 222
sd: 123
# Configured NSSAI for this UE by HPLMN
configured-nssai:
- sst: 222
sd: 123
entrypoint.sh
#!/usr/bin/env bash
set -euo pipefail
CONFIG_DIR="/ueransim/etc"
# Default values
USE_FQDN=${USE_FQDN:-no}
SST_R=${SST_R:-$SST_0}
SD_R=${SD_R:-$SD_0}
SST_0=${SST_0:-128}
SD_0=${SD_0:-128}
SST_1=${SST_1:-1}
SD_1=${SD_1:-0}
SST_2=${SST_2:-129}
SD_2=${SD_2:-129}
if [[ ${USE_FQDN} == "yes" ]];then
NGAPPeerAddr=(`getent hosts $AMF_FQDN | awk '{print $1}'`)
echo -e "\nResolving AMF by FQDN : $AMF_FQDN - $NGAPPeerAddr"
fi
for c in ${CONFIG_DIR}/*.yaml; do
# grep variable names (format: ${VAR}) from template to be rendered
VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs)
echo "Now setting these variables '${VARS}'"
# create sed expressions for substituting each occurrence of ${VAR}
# with the value of the environment variable "VAR"
EXPRESSIONS=""
for v in ${VARS}; do
NEW_VAR=$(echo $v | sed -e "s#@##g")
if [[ -z ${!NEW_VAR+x} ]]; then
echo "Error: Environment variable '${NEW_VAR}' is not set." \
"Config file '$(basename $c)' requires all of $VARS."
exit 1
fi
EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g"
done
EXPRESSIONS="${EXPRESSIONS#';'}"
# render template and inline replace config file
sed -i "${EXPRESSIONS}" ${c}
done
echo "Done setting the configuration"
echo "### Running ueransim ###"
echo "Running gnb"
/ueransim/bin/nr-gnb -c /ueransim/etc/custom-gnb.yaml &
sleep 1
echo "Running ue"
/ueransim/bin/nr-ue -c /ueransim/etc/custom-ue.yaml -n $NUMBER_OF_UE
exec "$@"
nr-binder
#!/bin/bash
#
# This file is a part of UERANSIM open source project.
# Copyright (c) 2021 ALİ G�~\NG�~VR.
#
# The software and all associated files are licensed under GPL-3.0
# and subject to the terms and conditions defined in LICENSE file.
#
if [ -z "$1" ]
then
echo "No IP address supplied"
exit
fi
addr=$1
shift
LD_PRELOAD=./libdevbnd.so UE_BIND_ADDR=$addr $@
使用如下方法在运行docker时忽视dockerfile设置好的entrypoint,指定新的进入点为/bin/bash
docker run -it --entrypoint="/bin/bash" your_image_id
打开错位的容器内部,查看其内部配置文件如何:
当进入最开始构建的ueransim:1.1时,发现其中的配置文件没有错误,与官方的配置文件一样,比如custom_gnb.yaml文件,在构建前参数虽然未定,但构建完后其中的参数是改变为正确了的,所以或许不需要在开始改变配置文件。
单独运行自己构建的ueransim容器,是不行的无法加入核心网的网桥,必须使用docker-compose启动,在启动时加入核心网容器才行
当在自己构建的ueransim‘容器内部启动gnb时,发现因为网络原因无法接入核心网:
分析单独启动容器没有加入核心网的网桥,ueransim容器与核心网是隔离的,所以不可能启动成功,失败的结果就是直接退出了。
单独启动官方正确的ueransim容器:
#这里我把官方的容器标签改为了latest11
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker run -it --entrypoint="/bin/bash" 89d9f3a55d93
运行entrypoint,出现了和前面一样的错误
尝试启动基站gnb:
root@82290ba6a705:/ueransim/bin# /ueransim/bin/nr-gnb -c /ueransim/etc/custom-gnb.yaml
export与import主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ mkdir scripts
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ cd scripts
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/scripts$ cat > hello.sh
sudo docker-compose -f docker-compose-ueransim-vpp.yaml up -d
sleep 8s
sudo docker exec -it ueransim /bin/bash
sleep 3s
chmod 777 nr-binder
sleep 3s
exit
然后按ctrl+D退出cat并保存
#使该shell可执行
chmod u+x hello.sh
然后执行该脚本,这样启动的ueransim的nr-binder就是可执行的
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ ./hello.sh
结果发现无法成功,因为加入容器内部后shell就会停止执行,只有退出后才会继续执行
创建了一个shell脚本
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ cat > ping.sh
chmod 777 nr-binder
./nr-binder 10.45.0.2 ping www.baidu.com
sleep 3s
将其复制到ueransim内部
#docker cp 本地文件路径 容器ID/容器NAME:容器内路径
rtual-machine:~/oai-cn5g-fed/docker-compose$ #docker cp ping.sh ueransim:/ueransim/bin
sudo docker exec -it ueransim bash ping.sh
目前的容器版ueransim无法自己构建,只能使用官方提供的容器,而官方容器内的nr-binder是无法使用的,也就无法通过nr-binder使用其他自定义程序,另一方面无法通过shell自动将nr-binder变为可使用的。目前唯一的办法是启动容器后进入容器,将nr-binder变为可执行,然后退出容器,就可以使用nr-binder了。
#启动核心网
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker-compose -f docker-compose-basic-vpp-nrf.yaml up -d
#启动容器版ueransim
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$sudo docker-compose -f docker-compose-ueransim-vpp.yaml up -d
#进入容器内部
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec -it ueransim /bin/bash
#改变nr-binder权限
root@ae207f57ff0e:/ueransim/bin# chmod 777 nr-binder
#退出容器
root@ae207f57ff0e:/ueransim/bin# exit
#使用容器进行ping的操作
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec -it ueransim ./nr-binder 10.45.0.2 ping www.baidu.com
但是这是不行的,因为容器内无法执行容器外的程序,如下使用nr-binder无法使用容器curl访问百度
于是就只能使用复制代码的方法将外部代码复制到容器内部后执行
#docker cp 本地文件路径 容器ID/容器NAME:容器内路径
rtual-machine:~/oai-cn5g-fed/docker-compose$ #docker cp ping.sh ueransim:/ueransim/bin
#执行ping.sh
sudo docker exec -it ueransim bash ping.sh
通过docker build构建镜像完成后运行却不能正常运行的原因可能是构建镜像使用的设备性能较低,使用性能更强的机器构建镜像教易成功,另外,构建镜像是主要工作的是cpu而不是显卡。