UE-Ueransim-5GC全链路开发记录
目录
1. 系统配置
1.1 Ueransim配置
1.2 UE配置
2. 启动
3. 实际演示
附录
代理1:ueransim-5gc
代理2 ue-ueransim
TCPclient
TCPserver
1. 系统配置
1.1 Ueransim配置
- ueransim的yaml文件如下
version: '3.8'
services:ueransim2:container_name: ueransimimage: ueransim:latestprivileged: trueenvironment:# GNB Congig Parameters- MCC=208- MNC=95- NCI=0x000000020- TAC=0xa000- LINK_IP=192.168.70.144- NGAP_IP=192.168.70.144- GTP_IP=192.168.72.144- NGAP_PEER_IP=192.168.70.132- SST=222- SD=123- IGNORE_STREAM_IDS=true# UE Config Parameters- NUMBER_OF_UE=1- IMSI=208950000000042- KEY=0C0A34601D4F07677303652C0462535B- OP=63bfa50ee6523365ff14c1f45f88737d- OP_TYPE=OPC- AMF_VALUE=8000- IMEI=356938035643803- IMEI_SV=0035609204079514- GNB_IP_ADDRESS=192.168.70.144- PDU_TYPE=IPv4- APN=default- SST_0=222- SD_0=123- SST_C=222- SD_C=123- SST_D=222- SD_D=123networks:public_net:ipv4_address: 192.168.70.144public_net_access:ipv4_address: 192.168.72.144public_proxy_access: ipv4_address: 192.168.62.144healthcheck:test: /bin/bash -c "ifconfig uesimtun0"interval: 10s
networks:public_net:external:name: demo-oai-public-netpublic_net_access:external:name: oai-public-accesspublic_proxy_access:name: public_ueransim-accessipam:config:- subnet: 192.168.62.0/24driver_opts:com.docker.network.bridge.name: "ueransim-access"
- 网络配置
主机网卡及ip
Ueransim 对外接口 ip
ueransim-access: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.62.1 netmask 255.255.255.0 broadcast 192.168.62.255inet6 fe80::42:5eff:fe85:8b1 prefixlen 64 scopeid 0x20<link>ether 02:42:5e:85:08:b1 txqueuelen 0 (Ethernet)RX packets 931 bytes 47056 (47.0 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 998 bytes 73591 (73.5 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Ueransim 容器内部ip
docker exec -it ueransim /bin/bash
root@1dacc8a170b6:/ueransim/bin# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.70.144 netmask 255.255.255.0 broadcast 192.168.70.255ether 02:42:c0:a8:46:90 txqueuelen 0 (Ethernet)RX packets 186 bytes 20087 (20.0 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 144 bytes 12276 (12.2 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.72.144 netmask 255.255.255.0 broadcast 192.168.72.255ether 02:42:c0:a8:48:90 txqueuelen 0 (Ethernet)RX packets 37 bytes 5321 (5.3 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 1 bytes 42 (42.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.62.144 netmask 255.255.255.0 broadcast 192.168.62.255ether 02:42:c0:a8:3e:90 txqueuelen 0 (Ethernet)RX packets 99 bytes 14346 (14.3 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 7 bytes 518 (518.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 3223 bytes 173462 (173.4 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 3223 bytes 173462 (173.4 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0uesimtun0: flags=369<UP,POINTOPOINT,NOTRAILERS,RUNNING,PROMISC> mtu 1400inet 12.1.1.2 netmask 255.255.255.255 destination 12.1.1.2unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1.2 UE配置
- 网络配置
工控机网卡及ip
路由设置
工控机添加路由(在power shell中添加)
route -p add 192.168.62.1 MASK 255.255.255.1 192.168.12.33
2. 启动
docker-compose -f docker-compose-basic-vpp-nrf.yaml up -d
docker-compose -f ueransim-yzk-test.yaml up -d
lab@lab-virtual-machine:~/oai-cn5g-fed/docker-compose$ docker ps -a
WARNING: Error loading config file: /home/lab/.docker/config.json: open /home/lab/.docker/config.json: permission denied
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1dacc8a170b6 ueransim:latest "/ueransim/bin/entry…" 27 minutes ago Up 27 minutes (healthy) ueransim
8b2ef5fa8d12 oaisoftwarealliance/oai-smf:v1.5.0 "python3 /openair-sm…" 29 minutes ago Up 29 minutes (healthy) 80/tcp, 8080/tcp, 8805/udp oai-smf
133b33b85363 oaisoftwarealliance/oai-amf:v1.5.0 "python3 /openair-am…" 29 minutes ago Up 29 minutes (healthy) 80/tcp, 9090/tcp, 38412/sctp oai-amf
b4c318f3ead3 oaisoftwarealliance/oai-ausf:v1.5.0 "python3 /openair-au…" 29 minutes ago Up 29 minutes (healthy) 80/tcp oai-ausf
431965a1ecce oaisoftwarealliance/oai-udm:v1.5.0 "python3 /openair-ud…" 29 minutes ago Up 29 minutes (healthy) 80/tcp oai-udm
1a4d2d61dfba oaisoftwarealliance/oai-udr:v1.5.0 "python3 /openair-ud…" 29 minutes ago Up 29 minutes (healthy) 80/tcp oai-udr
b771d01a8186 oaisoftwarealliance/oai-upf-vpp:v1.5.0 "/openair-upf/bin/en…" 29 minutes ago Up 29 minutes (healthy) 2152/udp, 8085/udp vpp-upf
58de55946ec2 mysql:8.0 "docker-entrypoint.s…" 29 minutes ago Up 29 minutes (healthy) 3306/tcp, 33060/tcp mysql
17a5c3649796 oaisoftwarealliance/trf-gen-cn5g:latest "/bin/bash -c ' ipta…" 29 minutes ago Up 29 minutes (healthy) oai-ext-dn
d29065bc29b2 oaisoftwarealliance/oai-nrf:v1.5.0 "python3 /openair-nr…" 29 minutes ago Up 29 minutes (healthy) 80/tcp, 9090/tcp oai-nrf
将ueransim-5gc-proxy传输进Ueransim容器中
docker cp /home/lab/oai-cn5g-fed/docker-compose/gNB/ueransim-5gc-proxy.py 1dacc8a170b6:/ueransim/bin
- Ueransim容器内部命令:
chmod 777 nr-binder
apt-get update
apt-get install -y python3
apt install -y python3-pip
./nr-binder 12.1.1.2 python3 ueransim-5gc-proxy.py
- 外部命令
python3 ue-ueransim-proxy.py
python3 TCPserve.py
- 用户侧命令
python TCPclient.py
3. 实际演示
- 主机
- 工控机
- 运行状况
附录
-
代理1:ueransim-5gc
#https://www.youtube.com/watch?v=iApNzWZG-10import socket
from threading import Thread
import os
#线程2class Proxy2Server(Thread):#首先设置服务器连接(用_init_方法来构造)#参考https://www.cnblogs.com/ant-colonies/p/6718388.htmldef __init__(self, host, port):super(Proxy2Server,self).__init__()self.game = None #设置为连接用户的套接字,但是该套接字是由Game2Proxy线程创建的self.port = portself.host = host #连接服务器的ip和端口self.server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)self.server.connect((host,port))def run(self):while True:data = self.server.recv(4096)if data:#转发所有数据到用户print("UE <------- Ueransim")self.game.sendall(data)
#线程1(监听用户是否与代理服务器连接)
class Game2Proxy(Thread):def __init__(self,host,port):super(Game2Proxy,self).__init__()self.server = None self.port = portself.host = host #连接用户的ip和端口sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)sock.bind((host,port))sock.listen(1)#这些都是上面官方文档里面调用的例程实现的#等待用户的连接 self.game ,addr = sock.accept() #sock.accept接收套接字#当客户端连接之后我们将获得代理服务器与客户端通信的套接字,并将其分配给self.game,然后在下面的线程中利用永久循环来接收用户端的数据def run(self):while True: #死循环接收用户的数据data = self.game.recv(4096)#最大数据量4kif data: #如果真的接收到了用户发送过来的数据,那麽我们会尝试将此数据转发到服务器的套接字,即另外一个线程的套接字#转发给服务器print(" UE -------> Ueransim")self.server.sendall(data)#上面的两个线程创建完毕之后,需要为每一个线程提供对另外一个套接字的引用
#为此,我创建了一个更通用的类,命名为Proxy
class Proxy(Thread):def __init__(self,from_host,to_host,port):#如果没有在__init__中初始化对应的实例变量的话,导致后续引用实例变量会出错super(Proxy, self).__init__()self.from_host = from_host self.to_host = to_hostself.port = port def run(self):while True:#print ("[proxy({})] setting up")print ("Initialized, Waitting for connecting...")#用户会连接到下面这个self.g2p = Game2Proxy(self.from_host, self.port) #运行我们创建的这个线程,它等待用户端连接到指定端口#如果代理服务器与用户建立连接之后,另外一个线程将建立到服务器的转发连接self.p2s = Proxy2Server(self.to_host, self.port)print ("proxy connection established")print ("Connected!,Sending...")#现在两个线程都创建了套接字,我们接下来要做的就是交换他们self.g2p.server = self.p2s.server #将与客户端建立的套接字转发给真实服务器self.p2s.game = self.g2p.game #将服务器传回的套接字转发到客户端#线程设置完毕,现在我们来真正启动它self.g2p.start()self.p2s.start()#写到这里的时候,唯一缺少的就是创建一个或多个代理线程,我们先从主服务器开始
master_server = Proxy('192.168.62.144', '192.168.70.1', 8088)
#监听自己所有本机端口3333,并将它转发到真实的服务器ip 192.168.178.54
master_server.start() #启动
-
代理2 ue-ueransim
#https://www.youtube.com/watch?v=iApNzWZG-10import socket
from threading import Thread
import os
#线程2class Proxy2Server(Thread):#首先设置服务器连接(用_init_方法来构造)#参考https://www.cnblogs.com/ant-colonies/p/6718388.htmldef __init__(self, host, port):super(Proxy2Server,self).__init__()self.game = None #设置为连接用户的套接字,但是该套接字是由Game2Proxy线程创建的self.port = portself.host = host #连接服务器的ip和端口self.server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)self.server.connect((host,port))def run(self):while True:data = self.server.recv(4096)if data:#转发所有数据到用户print("UE <------- Ueransim")self.game.sendall(data)
#线程1(监听用户是否与代理服务器连接)
class Game2Proxy(Thread):def __init__(self,host,port):super(Game2Proxy,self).__init__()self.server = None self.port = portself.host = host #连接用户的ip和端口sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)sock.bind((host,port))sock.listen(1)#这些都是上面官方文档里面调用的例程实现的#等待用户的连接 self.game ,addr = sock.accept() #sock.accept接收套接字#当客户端连接之后我们将获得代理服务器与客户端通信的套接字,并将其分配给self.game,然后在下面的线程中利用永久循环来接收用户端的数据def run(self):while True: #死循环接收用户的数据data = self.game.recv(4096)#最大数据量4kif data: #如果真的接收到了用户发送过来的数据,那麽我们会尝试将此数据转发到服务器的套接字,即另外一个线程的套接字#转发给服务器print(" UE -------> Ueransim")self.server.sendall(data)#上面的两个线程创建完毕之后,需要为每一个线程提供对另外一个套接字的引用
#为此,我创建了一个更通用的类,命名为Proxy
class Proxy(Thread):def __init__(self,from_host,to_host,port):#如果没有在__init__中初始化对应的实例变量的话,导致后续引用实例变量会出错super(Proxy, self).__init__()self.from_host = from_host self.to_host = to_hostself.port = port def run(self):while True:#print ("[proxy({})] setting up")print ("Initialized, Waitting for connecting...")#用户会连接到下面这个self.g2p = Game2Proxy(self.from_host, self.port) #运行我们创建的这个线程,它等待用户端连接到指定端口#如果代理服务器与用户建立连接之后,另外一个线程将建立到服务器的转发连接self.p2s = Proxy2Server(self.to_host, self.port)print ("proxy connection established")print ("Connected!,Sending...")#现在两个线程都创建了套接字,我们接下来要做的就是交换他们self.g2p.server = self.p2s.server #将与客户端建立的套接字转发给真实服务器self.p2s.game = self.g2p.game #将服务器传回的套接字转发到客户端#线程设置完毕,现在我们来真正启动它self.g2p.start()self.p2s.start()#写到这里的时候,唯一缺少的就是创建一个或多个代理线程,我们先从主服务器开始
master_server = Proxy('192.168.62.1', '192.168.62.144', 8088)
#监听自己所有本机端口3333,并将它转发到真实的服务器ip 192.168.178.54
master_server.start() #启动
-
TCPclient
import socket
import time
# 创建套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Waitting for connecting...")
# 建立连接
tcp_client_socket.connect(("192.168.62.1", 8088))
print("Connected!")# 发送数据
print("Sending message...")
while 1:tcp_client_socket.send("你好".encode("gb2312"))time.sleep(2)
# 接收数据
recv_data = tcp_client_socket.recv(1024).decode("gb2312")
print(recv_data)# 关闭套接字
tcp_client_socket.close()
-
TCPserver
import socket
from threading import Threaddef new_client_connect(new_client_socket, client_ip_port):while True:# 收发数据recv_data = new_client_socket.recv(1024)if len(recv_data) != 0:recv_text = recv_data.decode("gb2312")print("Connected!")print(" Server from 5GC received [%s]:%s" % (str(client_ip_port), recv_text))else:print("Disconnected!")print("Waitting for connecting...")break# # 关闭连接# new_client_socket.close() # 表示断开与当前的客户端的通信def main():# 创建套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定端口和iptcp_server_socket.bind(("192.168.70.1", 8088))# 设置套接字为被动监听模式,不能主动发送数据,128为允许接收的最大连接数tcp_server_socket.listen(128)print("Waitting for connecting...")while True:# 接收客户端连接new_client_socket, client_ip_port = tcp_server_socket.accept()t1 = Thread(target=new_client_connect, args=(new_client_socket, client_ip_port))t1.start()# tcp_server_socket.close() # 表示不再接受新客户端的连接,已经连接的可以继续服务if __name__ == '__main__':main()