---
# System prepended metadata

title: 'Open5Gs, OAI gNB, and FlexRIC intergration.'
tags: [teep]

---

# Open5Gs, OAI gNB, and FlexRIC intergration.


>[name=Muhammad Surya Danendra Pabana]
## Table of Contents
>[TOC]
>
![arsitektur5g_RIC.drawio (1)](https://stingy-knee-8a5.notion.site/image/attachment%3Af29f1c9b-b9cb-4cf4-8cd0-1f9479dc1aef%3Aarsitektur5g_RIC.drawio.png?table=block&id=1b4176c0-8585-804b-b392-e85b71cae3a1&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)


We use proxmox for the vms with specifications bellow:

VM1 core network:

- Ubuntu 22.04
- 4 Core
- 4 RAM
- 50 GB storage

VM gNB:

- Ubuntu 22.04
- 4 Core
- 4 RAM
- 50 GB storage

*note:* 

- *I already tried using Free5GC as the core network for the OAI gNB, but Free5GC is not compatible with the OAI gNB.*
- ***UERANSIM is not compatible for flexric because it doesn’t have E2 support**.*

## 1. Getting Open5GS

### 1.1 Installing GO

```bash
wget https://dl.google.com/go/go1.18.10.linux-amd64.tar.gz
sudo tar -C /usr/local -zxvf go1.18.10.linux-amd64.tar.gz
mkdir -p ~/go/{bin,pkg,src}
#The following assume that your shell is bash:
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export GOROOT=/usr/local/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin:$GOROOT/bin' >> ~/.bashrc
echo 'export GO111MODULE=auto' >> ~/.bashrc
source ~/.bashrc
```

### 1.2 Installing MongoDB

```bash
sudo apt -y update
sudo apt -y install mongodb wget git
sudo systemctl start mongodb
```

### 1.3 Installing Open5GS

*Ubuntu* makes it easy to install Open5GS as shown below.

```bash
sudo add-apt-repository ppa:open5gs/latest
sudo apt update
sudo apt install open5gs
```

note: you can see tutorial for other OS [here](https://open5gs.org/open5gs/docs/guide/01-quickstart/).

### 1.4 Installing Open5GS webUI

The WebUI allows you to interactively edit subscriber data. While it is not essential to use this, it makes things easier when you are just starting out on your Open5GS adventure. (A [command line tool](https://github.com/open5gs/open5gs/blob/main/misc/db/open5gs-dbctl) is available for advanced users).

1. Installing Node.js for Ubuntu and Debian:
    
    ```bash
    # Download and import the Nodesource GPG key
    sudo apt update
    sudo apt install -y ca-certificates curl gnupg
    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
    
    # Create deb repository
    NODE_MAJOR=20
    echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
    
    # Run Update and Install
    sudo apt update
    sudo apt install nodejs -y
    ```
    
2. To install [Node.js](https://nodejs.org/) on *openSUSE*, run the following:
    
    ```bash
    sudo zypper install nodejs8
    ```
    

You can now install WebUI of Open5G

```bash
curl -fsSL https://open5gs.org/open5gs/assets/webui/install | sudo -E bash -
```

## 1.5 Setup 5G Core

Since we are using a private environment, there is no need to modify the PLMN in NRF and AMF.

If you are aiming to connect an external gNB to your core, you will also need to change the NGAP bind address of the AMF **and** the GTPU bind address of the UPF. If you are running an gNB stack locally, you will not need to make these changes.

Modify [/etc/open5gs/amf.yaml](https://github.com/open5gs/open5gs/blob/main/configs/open5gs/amf.yaml.in) to set the NGAP IP address. 

```bash
ngap:
       server:
-        - address: 127.0.0.5
+        - address: 192.168.1.160
     metrics:
       server:
         - address: 127.0.0.5
           port: 9090
     guami:
```

Modify [/etc/open5gs/upf.yaml](https://github.com/open5gs/open5gs/blob/main/configs/open5gs/upf.yaml.in) to set the GTP-U address.

```bash
     gtpu:
       server:
-        - address: 127.0.0.7
+        - address: 192.168.1.160
     session:
       - subnet: 10.45.0.1/16
       - subnet: 2001:db8:cafe::1/48
```

After changing config files, please restart Open5GS daemons.

```bash
sudo systemctl restart open5gs-nrfd
sudo systemctl restart open5gs-amfd
sudo systemctl restart open5gs-upfd
```

### Register Subscriber information

Connect to `http://localhost:9999` and login with **admin** account.

Username : admin

Password : 1423

**Tip:** You can change the password in *Account* Menu.

To add subscriber information, you can do WebUI operations in the following order:

1. Go to `Subscriber` Menu.
2. Click `+` Button to add a new subscriber.
3. Fill the IMSI.
    
    ![](https://stingy-knee-8a5.notion.site/image/attachment%3A65c1f0e3-ab82-4510-9f13-f516df0fb956%3Aimage.png?table=block&id=1b4176c0-8585-801a-8467-c9985d1e7f06&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1360&userId=&cache=v2)

    
4. Click `SAVE` Button

### **Adding a route for the UE to have WAN connectivity**

in order to bridge between the PGWU/UPF and WAN (Internet), you must enable IP forwarding and add a NAT rule to your IP Tables.To enable forwarding and add the NAT rule, enter

```bash
### Enable IPv4/IPv6 Forwarding
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1

### Add NAT Rule
sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
sudo ip6tables -t nat -A POSTROUTING -s 2001:db8:cafe::/48 ! -o ogstun -j MASQUERADE
```

Configure the firewall correctly. Some operating systems (Ubuntu) by default enable firewall rules to block traffic.

```bash
sudo ufw status
> Status: active
sudo ufw disable
> Firewall stopped and disabled on system startup
sudo ufw status
> Status: inactive
```

### **1.6 Starting and Stopping Open5GS**

When you install the software using the package manager, it is setup to run as a systemd service. You can stop and restart the components and network functions as follows:

```bash
$ sudo systemctl stop open5gs-mmed
$ sudo systemctl stop open5gs-sgwcd
$ sudo systemctl stop open5gs-smfd
$ sudo systemctl stop open5gs-amfd
$ sudo systemctl stop open5gs-sgwud
$ sudo systemctl stop open5gs-upfd
$ sudo systemctl stop open5gs-hssd
$ sudo systemctl stop open5gs-pcrfd
$ sudo systemctl stop open5gs-nrfd
$ sudo systemctl stop open5gs-scpd
$ sudo systemctl stop open5gs-seppd
$ sudo systemctl stop open5gs-ausfd
$ sudo systemctl stop open5gs-udmd
$ sudo systemctl stop open5gs-pcfd
$ sudo systemctl stop open5gs-nssfd
$ sudo systemctl stop open5gs-bsfd
$ sudo systemctl stop open5gs-udrd
$ sudo systemctl stop open5gs-webui
```

```bash
$ sudo systemctl restart open5gs-mmed
$ sudo systemctl restart open5gs-sgwcd
$ sudo systemctl restart open5gs-smfd
$ sudo systemctl restart open5gs-amfd
$ sudo systemctl restart open5gs-sgwud
$ sudo systemctl restart open5gs-upfd
$ sudo systemctl restart open5gs-hssd
$ sudo systemctl restart open5gs-pcrfd
$ sudo systemctl restart open5gs-nrfd
$ sudo systemctl restart open5gs-scpd
$ sudo systemctl restart open5gs-seppd
$ sudo systemctl restart open5gs-ausfd
$ sudo systemctl restart open5gs-udmd
$ sudo systemctl restart open5gs-pcfd
$ sudo systemctl restart open5gs-nssfd
$ sudo systemctl restart open5gs-bsfd
$ sudo systemctl restart open5gs-udrd
$ sudo systemctl restart open5gs-webui
```

## 2. Installing OAI gNB & UE

### 2.1 OAI pre-requisites

- A *recent* CMake (at least v3.15).
    
    ```bash
    sudo apt-get update
    sudo apt-get install ca-certificates gpg wget
    
    test -f /usr/share/doc/kitware-archive-keyring/copyright ||
    wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
    
    ## For Ubuntu Noble Numbat (24.04):
    echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ noble main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
    sudo apt-get update
    
    ## For Ubuntu Jammy Jellyfish (22.04):
    echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ jammy main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
    sudo apt-get update
    
    ## For Ubuntu Focal Fossa (20.04):
    echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
    sudo apt-get update
    
    sudo apt-get install kitware-archive-keyring
    ```
    
- SWIG (at least  v.4.1).
SWIG as an interface generator to enable the multi-language feature (i.e., C/C++ and Python) for the xApps. Please, check your SWIG version (i.e, `swig -version`) and install it from scratch if necessary as described here: [https://swig.org/svn.html](https://swig.org/svn.html) or via the code below:
    
    ```bash
    git clone https://github.com/swig/swig.git
    cd swig
    git checkout release-4.1
    ./autogen.sh
    ./configure --prefix=/usr/
    make -j8make install
    ```
    

### 2.2 Download the required dependencies.

```bash
sudo apt install libsctp-dev python3.8 cmake-curses-gui libpcre2-dev python-dev
```

### 2.3 Deployment

```bash
git clone https://gitlab.eurecom.fr/oai/openairinterface5g oai
cd oai/
cd cmake_targets/
./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja

```

- `I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed.
- `w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using `w SIMU` option, but is also built during any softmodem build.
- `-gNB` is to build the `nr-softmodem` and `nr-cuup` executables and all required shared libraries
- `-nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries
- `-ninja` is to use the ninja build tool, which speeds up compilation
- `-build-e2` option is to use the E2 agent, integrated within RAN.

If the openair2/E2AP/flexric folder is empty, try manually the following commands:

```bash
git submodule init
git submodule update
```
><div style="background-color: #5c2b2b; border-left: 4px solid #f87171; padding: 10px; border-radius: 6px; color: #fee2e2;">
>Because I changed the FlexRIC E2AP and KPM version to version 3, I need to do the following:

<div style="background-color: #052e16; border-left: 4px solid #22c55e; padding: 10px; border-radius: 6px; color: #bbf7d0;">
  <p><strong style="color: #22c55e;">Solution (This step is for upgrading not for installing, if you want to install it automatically to Version 3 then fo to the step 3 instead):</strong><br>
  1.Remove the CMakeCache.txt:</p>

```bash 
cd /oai
rm /cmake_targets/ran_build/build/CMakeCache.txt
```
  2. Choose the correct version in CmakeLists.txt:  
    
```bash
cd /oai
nano CmakeLists.txt
```
![image](https://hackmd.io/_uploads/S1WlXEslge.png)
    
 3. Rebuild the OAI:
```bash    
./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja
```
![WhatsApp Image 2025-05-09 at 13.41.48_ab26834c](https://hackmd.io/_uploads/Sk9IQNilxg.jpg)

</div>




### 2.4 Configure OAI gNB and UE

2.4.1 Configure CU

modify  oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf. Change the MCC and MNC according to the core network PLMN.

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3Ac2607e73-4149-4db9-b75c-b1350cbb3851%3Aimage.png?table=block&id=1b4176c0-8585-8053-9710-d9f65f448c60&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)


And change the IP address to match the AMF and the IP of the VM.

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A7cae153b-eca1-4e45-9abc-639aa06ba12f%3Aimage.png?table=block&id=1b4176c0-8585-80ac-8655-e522e2ec8319&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

Add this code to the configuration:

```bash
e2_agent = {
  near_ric_ip_addr = "127.0.0.1";
  sm_dir = "/usr/local/lib/flexric/"
}
```

2.4.2 Configure DU

modify  oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf. Change the MCC and MNC according to the core network PLMN.

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A23359458-989b-4e41-9cb1-810e0f464a5b%3Aimage.png?table=block&id=1b4176c0-8585-8012-b0b5-fa9ed781f179&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

Add this code to the configuration:

```bash
e2_agent = {
  near_ric_ip_addr = "127.0.0.1";
  sm_dir = "/usr/local/lib/flexric/"
}
```

2.4.3 Configure UE

modify  oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf. Change the IMSI and key , OPC, dnn, and nssai.

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A34493141-d125-4797-a715-c60090cb401e%3Aimage.png?table=block&id=1b4176c0-8585-80cf-a7ff-c8bd18832b4a&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=790&userId=&cache=v2)

## Installing Flexric

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3Aac2176d3-f58a-4e96-b797-d05bd2fe5720%3Aimage.png?table=block&id=1b4176c0-8585-80fa-b85d-d6c09ecc0724&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

By default, FlexRIC will build the nearRT-RIC with E2AP v2 and KPM v2. If you want a different version, edit the variable E2AP_VERSION and KPM_VERSION at FlexRIC's CMakeLists.txt file. Note that OAI's and FlexRIC's E2AP_VERSION and KPM_VERSION need to match due to O-RAN incompatibilities among versions.

### 3.1 Clone FlexRIC repository

```bash
git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
cd flexric/
git checkout f1c08ed2b9b1eceeda7941dd7bf435db0168dd56
```
><div style="background-color: #5c2b2b; border-left: 4px solid #f87171; padding: 10px; border-radius: 6px; color: #fee2e2;">
>I used a specific checkout version, but it was already outdated, which caused many errors.
    
<div style="background-color: #052e16; border-left: 4px solid #22c55e; padding: 10px; border-radius: 6px; color: #bbf7d0;">
  <p><strong style="color: #22c55e;">Solution:</strong><br>
  Use the latest commit instead of an outdated one:</p>

```bash
git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
cd flexric/
git checkout dev
git pull
```
</div>


### 3.2 Build FlexRIC

```bash
mkdir build && cd build && cmake .. && make -j8
```
I tried using the default version of E2AP V2 and KPM_V2.03, but it caused more errors.

    
<div style="background-color: #052e16; border-left: 4px solid #22c55e; padding: 10px; border-radius: 6px; color: #bbf7d0;">   <p><strong style="color: #22c55e;">Solution:</strong><br>
    so i upgraded it with the following command</p>

```bash 
mkdir build && cd build && cmake -DE2AP_VERSION=E2AP_V3_00 -DKPM_VERSION=KPM_V3 .. && make -j8
```
![WhatsApp Image 2025-05-09 at 13.39.36_e19f7b37](https://hackmd.io/_uploads/B1P91Ejxlx.jpg)
</div>
### 3.3 Installation of Service Model (SMs)

```bash
sudo make install
```

## 4. Demo

### 4.1 Start FlexRIC Near RT RIC

```bash
./flexric/build/examples/ric/nearRT-RIC
```

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A9aacd0bc-07a1-4bdb-89d9-76a7350ffe1f%3Aimage.png?table=block&id=1b4176c0-8585-80fd-8121-d1ab2c81ed65&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

### 4.2 Start CU, DU, and UE

```bash
sudo ./nr-softmodem -O oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf --rfsim
sudo ./nr-softmodem -O oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf --rfsim -E
cd oai/cmake_targets/ran_build/build
sudo .oai/cmake_targets/ran_build/build/nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 127.0.0.1

```

#### 4.2.1 CU ouput:

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A68c2eccb-95a4-45a5-8553-171d76cba723%3Aimage.png?table=block&id=1b4176c0-8585-80f3-8fa2-d9122225e48e&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

Here, it shows that the AMF NG request was successful, as well as the E2 agent setup response, meaning the CU is connected to the RIC.

#### 4.2.2 DU output:

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3Afea75b3e-4eca-4b6e-b4c7-de3918965603%3Aimage.png?table=block&id=1b4176c0-8585-8019-9394-d05c50452e4f&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

here, it shows the GTP connection successful.

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A556da453-fe4e-4ace-91d4-ffba0c140350%3Aimage.png?table=block&id=1b4176c0-8585-8028-998d-efc9952b8e3f&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

here, it shows that DU is connected to the RIC.

#### 4.2.3 UE output:

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A1944dbba-47e3-41bc-b059-b7d1541e9a39%3Aimage.png?table=block&id=1b4176c0-8585-800a-8887-c278ad48cf1a&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

the UE is successfully connected to the RU simulation.

#### 4.2.4 RIC output:

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A87762349-17b6-4ee2-a25a-c898d81f3735%3Aimage.png?table=block&id=1b4176c0-8585-80af-be2e-fde6e3053415&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

#### 4.2.4 UE connectivity test:

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3Af4fc48c6-0b7d-4b83-b241-47f4637ed272%3Aimage.png?table=block&id=1b4176c0-8585-80c4-979c-ee701e5af8c0&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

```bash
ping -I oaitun_ue1 8.8.8.8
```

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A0f8f0216-b858-497a-a7a9-1483bfc2acaf%3Aimage.png?table=block&id=1b4176c0-8585-80b5-9652-fc222220a517&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

#### 4.2.5 xApps

```bash
cd flexric 
.build/examples/xApp/c/monitor/xapp_kpm_moni
```

![image.png](https://stingy-knee-8a5.notion.site/image/attachment%3A9e1a79b9-f22c-45c7-a3ac-e58f007c976c%3Aimage.png?table=block&id=1b4176c0-8585-80dd-a1c0-ea226d8609c6&spaceId=148e99b0-39e5-494f-8e74-4343e8d63517&width=1420&userId=&cache=v2)

Start different xApps

- start the RC monitor xApp - aperiodic subscription for "UE RRC State Change"
    
    ```bash
    cd flexric 
    ./build/examples/xApp/c/monitor/xapp_rc_moni
    ```
    
- start the RC control xApp - RAN control function "QoS flow mapping configuration" (e.g. creating a new DRB)
    
    ```bash
    cd flexric
    ./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
    ```
    
- start the (MAC + RLC + PDCP + GTP) monitor xApp
    
    ```bash
    cd flexric
    ./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni
    ```
## 5 GTPU Monitoring XApps:
```bash!
cd flexric
./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni
```
![image](https://hackmd.io/_uploads/BJjoEEsexl.png)
![image](https://hackmd.io/_uploads/rk_nVVogxx.png)

read the data using sqlitebrowser

```bash!
sudo apt install sqlitebrowser
sqlitebrowser /tmp/xapp_db_1746777138419252
```

![WhatsApp Image 2025-05-09 at 14.57.02_e5323aba](https://hackmd.io/_uploads/B1jIH4ixge.jpg)

### Explanation of GTPU monitoring
GTP-U (GPRS Tunneling Protocol - User Plane) is a protocol used to transport user data (like video, web traffic, etc.) between the gNB and the UPF (User Plane Function) in 5G and LTE networks.

In the RAN (Radio Access Network), monitoring GTP-U helps:
*   Track data usage per UE
*   Measure uplink/downlink throughput
*   Analyze user-plane latency
*   Detect performance bottlenecks

FlexRIC uses modular Service Models (SMs).

For GTP-U monitoring:

*    The GTP SM (e.g., `gtp_sm.c`) collects user-plane metrics inside the E2 Agent (e.g., gNB/DU)
*    The xApp subscribes to these metrics via the E2 interface
*    The xApp processes and logs or stores the data

![SJX-D4sxex](https://hackmd.io/_uploads/rJTWZrixxl.png)

Flow Explanation (in English)
1. Initialization Phase

    * The xApp, NEAR-Real-time RIC (NEAR-RIC), and E2 Node (RAN Function) are initialized.

    * NEAR-RIC sends an E2 Setup Request to the E2 Node to establish the E2 interface.

    * The E2 Node responds with an E2 Setup Response, confirming the interface setup.

    * xApp sends an E42 Setup Request to NEAR-RIC (internal FlexRIC-specific step) and receives an E42 Setup Response.

2. Subscription Phase

    * The xApp queries the list of connected E2 nodes (e2_nodes_xapp_api()).

    * For each node, it checks the RAN function types and sets up monitoring subscriptions for:

        * MAC (id 142)
        * RLC (id 143)
        * PDCP (id 144)
        * GTP (id 148)

    * The xApp calls report_sm_xapp_api(...) with appropriate callback handlers for each function type.

    * This triggers a Subscription Request from the xApp to NEAR-RIC, which forwards it to the E2 Node.

3. Reporting Phase

    * After the subscription is active, the E2 Node starts reporting statistics periodically (e.g., every 1_ms) as Indication Messages.

    * These messages are handled by specific callback functions like `sm_cb_gtp()`which:

        * Calculate latency between message timestamp and current time

        * Print the latency for every 1024 messages

4. Unsubscription Phase

    * After sleeping for 10 seconds (to allow stats collection), the xApp removes all subscriptions via rm_report_sm_xapp_api(...).

    * This triggers a Subscription Delete Request and Response sequence to clean up each subscription.

5. Termination Phase

    The xApp then checks for safe shutdown using try_stop_xapp_api() in a loop and terminates after successful de-initialization.
## next ====> multi ue https://hackmd.io/@XyMSKk5ZRU6mrKfDrEH9Vg/ByzQwVjxex
