目录
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: ueransim
image: ueransim:latest
privileged: true
environment:
# 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=123
networks:
public_net:
ipv4_address: 192.168.70.144
public_net_access:
ipv4_address: 192.168.72.144
public_proxy_access:
ipv4_address: 192.168.62.144
healthcheck:
test: /bin/bash -c "ifconfig uesimtun0"
interval: 10s
networks:
public_net:
external:
name: demo-oai-public-net
public_net_access:
external:
name: oai-public-access
public_proxy_access:
name: public_ueransim-access
ipam:
config:
- subnet: 192.168.62.0/24
driver_opts:
com.docker.network.bridge.name: "ueransim-access"
- 网络配置
主机网卡及ip
Ueransim 对外接口 ip
ueransim-access: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.62.1 netmask 255.255.255.0 broadcast 192.168.62.255
inet6 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 0
TX 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 1500
inet 192.168.70.144 netmask 255.255.255.0 broadcast 192.168.70.255
ether 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 0
TX packets 144 bytes 12276 (12.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.72.144 netmask 255.255.255.0 broadcast 192.168.72.255
ether 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 0
TX packets 1 bytes 42 (42.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.62.144 netmask 255.255.255.0 broadcast 192.168.62.255
ether 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 0
TX packets 7 bytes 518 (518.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 3223 bytes 173462 (173.4 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3223 bytes 173462 (173.4 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
uesimtun0: flags=369<UP,POINTOPOINT,NOTRAILERS,RUNNING,PROMISC> mtu 1400
inet 12.1.1.2 netmask 255.255.255.255 destination 12.1.1.2
unspec 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 0
TX 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-10
import socket
from threading import Thread
import os
#线程2
class Proxy2Server(Thread):
#首先设置服务器连接(用_init_方法来构造)
#参考https://www.cnblogs.com/ant-colonies/p/6718388.html
def __init__(self, host, port):
super(Proxy2Server,self).__init__()
self.game = None #设置为连接用户的套接字,但是该套接字是由Game2Proxy线程创建的
self.port = port
self.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 = port
self.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)#最大数据量4k
if 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_host
self.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-10
import socket
from threading import Thread
import os
#线程2
class Proxy2Server(Thread):
#首先设置服务器连接(用_init_方法来构造)
#参考https://www.cnblogs.com/ant-colonies/p/6718388.html
def __init__(self, host, port):
super(Proxy2Server,self).__init__()
self.game = None #设置为连接用户的套接字,但是该套接字是由Game2Proxy线程创建的
self.port = port
self.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 = port
self.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)#最大数据量4k
if 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_host
self.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 Thread
def 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)
# 绑定端口和ip
tcp_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()