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: 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()

猜你喜欢

转载自blog.csdn.net/weixin_44810982/article/details/130106204