【OpenAirInterface】容器化ueransim使用方法探索

这里写目录标题

  • 1.简介
  • 2.前置过程
    • 2.1ueransim容器部分解析
      • 2.1.1 Dockerfile 剖析
      • 2.1.2 enterpoint.sh剖析
    • 2.2前置启动过程
  • 3.开始探索与问题发现
    • 3.1测试通过uesimtun0 ping百度
    • 3.2测试通过ueransimtun0 使用curl获取浏览网页:
    • 3.2测试使用nr-binder:
  • 4.问题解决探索
    • 4.1容器内临时安装与使用curl
    • 4.2创建自己的ueransim容器
      • 4.2.1使用commit方法来构建新镜像
      • 4.2.2使用Dockerfile方法来构建新镜像
        • 4.2.2.1一次错误尝试的过程
        • 4.2.2.2再次尝试
        • 4.2.2.3再再次尝试
        • 4.2.2.4前几次尝试问题总结与解决
        • 4.2.2.5官方正确启动容器内部文件汇总
        • 4.2.2.6再次尝试,不是配置文件问题
        • 4.2.2.7再次尝试,新错误点发现
        • 4.2.2.7再次尝试,新错误点发现
      • 4.2.3 使用export与import来迁移镜像
      • 4.2.4 使用shell脚本的方法来使用nr-binder
      • 4.2.5 将外部代码复制到启动的容器内部让其可执行
  • 5. 总结
  • 更新 231107

OAIueransim官网
docker版ueransim代码

1.简介

相比直接使用的ueransim,由于使用了docker进行了封装,所以以前的使用方法无法照搬,这里探索了容器化ueransim使用的方法,并最终达到使用nr-binder绑定自己的业务代码进行自定义数据的传输。

2.前置过程

2.1ueransim容器部分解析

2.1.1 Dockerfile 剖析

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设置容器启动时的进入点

2.1.2 enterpoint.sh剖析

#!/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,并指定配置文件。

执行传入脚本的任何其他命令。

2.2前置启动过程

启动核心网

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-basic-vpp-nrf.yaml up -d

【OpenAirInterface】容器化ueransim使用方法探索_第1张图片

启动docker ueransim

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-ueransim-vpp.yaml up -d

【OpenAirInterface】容器化ueransim使用方法探索_第2张图片
通过日志查看生成的ueransimtun0接口

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker logs ueransim

【OpenAirInterface】容器化ueransim使用方法探索_第3张图片

3.开始探索与问题发现

3.1测试通过uesimtun0 ping百度

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim ping -I uesimtun0 www.baidu.com

【OpenAirInterface】容器化ueransim使用方法探索_第4张图片
到此已经证明ueransim可以正常工作,通过核心网传输ping的命令,并且连上了百度连上了外网
下一步需要验证如何通过像使用非docker版ueransim使用nr-binder来绑定其他应用

3.2测试通过ueransimtun0 使用curl获取浏览网页:

【OpenAirInterface】容器化ueransim使用方法探索_第5张图片

不成功,因为容器内部没有curl这个软件:

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim curl --interface uesimtun0 www.baidu.com

在这里插入图片描述

3.2测试使用nr-binder:

【OpenAirInterface】容器化ueransim使用方法探索_第6张图片

同样是无法使用:

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ sudo docker exec ueransim ./nr-binder ping -I uesimtun0 www.baidu.com

在这里插入图片描述
那么就更谈不上使用nr-binder来进行自定义脚本的数据传输了

4.问题解决探索

进入容器内部

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

在这里插入图片描述
再使用nr-binder,发现可以ping通了:

root@0ddce360fdba:/ueransim/bin# ./nr-binder 10.45.0.2 ping www.baidu.com

在这里插入图片描述
到这里发现了为什么外部无法使用nr-binder的原因,因为内部读写权限没有开启,nr-binder不是可执行文件

4.1容器内临时安装与使用curl

#在ueransim容器内部
apt-get update
apt install -y curl

【OpenAirInterface】容器化ueransim使用方法探索_第7张图片
使用curl:

./nr-binder 10.45.0.2 curl www.baidu.com

【OpenAirInterface】容器化ueransim使用方法探索_第8张图片
成功了!

4.2创建自己的ueransim容器

想要不进入容器内部,而是启动后就可以使用ueransim的nr-binder以及curl等,需要在原来的ueransim基础上构建自己的ueransim,有如下三种方式:

  1. 将容器里面运行的程序及运行环境打包生成新的镜像
docker commit [选项] 容器ID/名称 仓库名称:[标签]
-m:说明信息
-a:作者信息
-p:生成过程中停止容器的运行
  1. 重新创建Dockerfile运行自定义ueransim
  2. 使用export与import进行容器与镜像的迁移

4.2.1使用commit方法来构建新镜像

第一次尝试

查看容器id

lab@lab-virtual-machine:~$ docker ps -l

【OpenAirInterface】容器化ueransim使用方法探索_第9张图片
将容器通过commit保存为一个新的镜像ueransim1

 docker commit  
 docker commit 0ddce360fdba ueransim1

在这里插入图片描述
如上图已经生成了新的镜像:ueransim1 它的id为:040c63421d89

现在我们关掉之前的ueransim并接入新的ueransim1,测试其是否可以使用nr-binder以及curl

docker-compose -f docker-compose-ueransim-vpp.yaml down

【OpenAirInterface】容器化ueransim使用方法探索_第10张图片
打开ueransim启动的yaml文件,将其中启动的image由ueransim修改为ueransim1

sudo vim docker-compose-ueransim-vpp.yaml

【OpenAirInterface】容器化ueransim使用方法探索_第11张图片
再次启动

docker-compose -f docker-compose-ueransim-vpp.yaml up -d

【OpenAirInterface】容器化ueransim使用方法探索_第12张图片
发现容器启动不了
【OpenAirInterface】容器化ueransim使用方法探索_第13张图片
第二次尝试
第一次由于在里面进行了很多测试,比如ping以及使用curl等,这一次进入只下载curl以及更改nr-binder的权限,然后exit退出
然后使用commit提交为ueransim2
然后再次进行尝试
【OpenAirInterface】容器化ueransim使用方法探索_第14张图片
依旧不行
在这里插入图片描述
第三次尝试
这次只进行chmod 777 nr-binder ,但是依旧失败

综上,暂时放弃使用commit方法了固件ueransim镜像。

4.2.2使用Dockerfile方法来构建新镜像

4.2.2.1一次错误尝试的过程

先从网上下载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代码时都需要网络

【OpenAirInterface】容器化ueransim使用方法探索_第15张图片
在这里插入图片描述
再对启动ueransim的yaml文件进行修改,使用新构建的ueransim:1.1
【OpenAirInterface】容器化ueransim使用方法探索_第16张图片
然后再启动ueransim:

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker-compose -f docker-compose-ueransim-vpp.yaml up -d

依旧是失败:
在这里插入图片描述

这里对Dockerfile不作修改镜像build,看是否可以成功启动接入:
依旧是失败在这里插入图片描述

4.2.2.2再次尝试

刚刚发现官方的命令如下:

$ 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【OpenAirInterface】容器化ueransim使用方法探索_第17张图片
而我之前clone的是master里的内容,进行的操作也全是基于此代码,因此可能代码有错,这里后面clone正确的分支进行尝试
再次构建镜像:

$  docker build --target ueransim --tag ueransim:latest -f docker/Dockerfile.ubuntu.18.04 .

【OpenAirInterface】容器化ueransim使用方法探索_第18张图片
还是失败:
在这里插入图片描述
容器启动后会立即退出

4.2.2.3再再次尝试

在网上搜索错误原因后经过尝试找到了进入容器的方法:

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM/docker$ docker run -it ueransim /bin/bash

在这里插入图片描述
然后进行测试curl:
【OpenAirInterface】容器化ueransim使用方法探索_第19张图片
发现安装的curl可以正常使用,容器立刻退出的原因是容器启动后没有任务,entrypoint里的脚本没有正确执行,使用如下方法也可以使用curl

lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose/ueransim/UERANSIM/docker$ docker run -it ueransim /bin/bash

【OpenAirInterface】容器化ueransim使用方法探索_第20张图片
查看容器日志:
【OpenAirInterface】容器化ueransim使用方法探索_第21张图片

可以发现与之前的容器日志完全不同,没有启动gnb也没有启动ue。

4.2.2.4前几次尝试问题总结与解决

前面几次尝试可以确定通过更改dockerfile确实可以成功安装软件以及修改文件权限,而没有最终成功容器总是秒退的原因是容器内没有持续运行的程序,也就是gnb与ue没有成功启动(可以说没有尝试过启动),需要探索entrypoint让脚本正常运行。

尝试直接启动entrypoint.sh,但是失败

sudo docker run -it ueransim:yz bash /ueransim/bin/entrypoint.sh


根据报错信息可以发现sh脚本中传递参数时出错了
查看之前正确的日志:
【OpenAirInterface】容器化ueransim使用方法探索_第22张图片

【OpenAirInterface】容器化ueransim使用方法探索_第23张图片
发现使用的参数文件与oai的参数挺不一样的
【OpenAirInterface】容器化ueransim使用方法探索_第24张图片
进入官方正确的容器内部查看配置文件等,来看是否有差异
先启动官方的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容器中的配置文件如下:

gnb配置:
【OpenAirInterface】容器化ueransim使用方法探索_第25张图片

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

ue配置:
【OpenAirInterface】容器化ueransim使用方法探索_第26张图片

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'

然后发现entrypoint.sh脚本也不一样:
【OpenAirInterface】容器化ueransim使用方法探索_第27张图片

#!/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 .

【OpenAirInterface】容器化ueransim使用方法探索_第28张图片
将启动文件依赖镜像更改:

【OpenAirInterface】容器化ueransim使用方法探索_第29张图片
启动更改后的ueransim:
依旧报错…
【OpenAirInterface】容器化ueransim使用方法探索_第30张图片
查找原因:
在这里插入图片描述

4.2.2.5官方正确启动容器内部文件汇总

这里汇总了官方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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
custom-gnb.yaml

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 $@

4.2.2.6再次尝试,不是配置文件问题

使用如下方法在运行docker时忽视dockerfile设置好的entrypoint,指定新的进入点为/bin/bash

docker run -it --entrypoint="/bin/bash"  your_image_id

打开错位的容器内部,查看其内部配置文件如何:
当进入最开始构建的ueransim:1.1时,发现其中的配置文件没有错误,与官方的配置文件一样,比如custom_gnb.yaml文件,在构建前参数虽然未定,但构建完后其中的参数是改变为正确了的,所以或许不需要在开始改变配置文件。

4.2.2.7再次尝试,新错误点发现

单独运行自己构建的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

无法启动:
在这里插入图片描述
尝试连接如网桥,是无法连接通的:
【OpenAirInterface】容器化ueransim使用方法探索_第31张图片

4.2.2.7再次尝试,新错误点发现

4.2.3 使用export与import来迁移镜像

export与import主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。

4.2.4 使用shell脚本的方法来使用nr-binder

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就会停止执行,只有退出后才会继续执行
在这里插入图片描述

4.2.5 将外部代码复制到启动的容器内部让其可执行

创建了一个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

成功执行
在这里插入图片描述

5. 总结

目前的容器版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

更新 231107

通过docker build构建镜像完成后运行却不能正常运行的原因可能是构建镜像使用的设备性能较低,使用性能更强的机器构建镜像教易成功,另外,构建镜像是主要工作的是cpu而不是显卡。

你可能感兴趣的:(5G,docker,容器,OAI,ueransim)