[ORAN] FlexRIC Sevice Model (4): Indication 的設計邏輯
在之前的說明中, 我們大致介紹了一個 Service Model (SM) 的建立,
以及所對應要進行的修改流程, 包含: SM 定義, RIC 以及 xApp 部分,
在這篇文章中, 我們會介紹一下其對應的流程以及背後參數設定原因,
首先, 我們先回顧一下在 O-RAN 架構中的 Indication 資料結構,
如下圖所示:
來自: Polese, Michele, et al. "Understanding O-RAN: Architecture, interfaces, algorithms, security, and research challenges." IEEE Communications Surveys & Tutorials (2023).
在 O-RAN 的框架下, 其 Indication (其他型態也是) 傳送的資料結構分成兩層:
- E2 AP (Application Protocal): 可以視為信封, 標記了識別資訊與註冊流程
- E2 SM (Service Model): 可以視為信紙, 收送雙方定義的資料結構
在 FlexRIC 中, 可以找到 xApp 的範例程式如下:
https://gitlab.eurecom.fr/mosaic5g/flexric/-/blob/master/examples/xApp/c/monitor/xapp_kpm_moni.c
我們接下來會大略介紹一下程式碼, 並對應於 FlexRIC 的流程圖:
以下是 xApp 接收 Indication 的程式 (稱為 monitor),
我們取最簡單的 xapp_kpm_moni.c 作為範例, 並以藍字為註解:
我們取最簡單的 xapp_kpm_moni.c 作為範例, 並以藍字為註解:
- examples/xApp/c/monitor/xapp_kpm_moni.c
#include "../../../../src/xApp/e42_xapp_api.h" // FlexRIC 的 API
#include "../../../../src/util/alg_ds/alg/defer.h"
#include "../../../../src/util/time_now_us.h"
#include "../../../../src/sm/kpm_sm_v2.02/kpm_sm_id.h"
//// 引入對應的 Service Model
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
//// callback function 處理 SM 中的資訊
//// 此處只簡單地拿出時間並比較差值, 類似 O-RAN SC 中的 bouncer 範例
//// 如果需要存入 SQL 或是進行運算, 也實作於 callback 中
static void sm_cb_kpm(sm_ag_if_rd_t const* rd)
{
assert(rd != NULL);
assert(rd->type == KPM_STATS_V0); //// 可以此對應多組 SM 處理
int64_t now = time_now_us();
// KPM has 1 second resolution in its indication header, while 'now' is in microseconds
int64_t diff = now/1000000 - (int64_t)rd->kpm_stats.hdr.collectStartTime;
if (diff > 1)
printf("KPM ind_msg latency = %lu seconds\n", diff);
else
printf("KPM ind_msg latency < 1 seconds\n");
}
int main(int argc, char *argv[])
{
fr_args_t args = init_fr_args(argc, argv);
//// 對應流程圖的 initialize, E42 Setup Request/ Response
//Init the xApp
init_xapp_api(&args);
sleep(1);
e2_node_arr_t nodes = e2_nodes_xapp_api();
defer({ free_e2_node_arr(&nodes); });
assert(nodes.len > 0);
//// 對應於流程圖的 E2 Setup Request/ Response
//// E2 Node 透過 SCTP 建立連線, 每條連線對應一個 E2 Node
//// 此處是指 RIC 回報連線的 E2 Node 給 xApp
//// 真正的連線建立先於 xApp 執行
printf("Connected E2 nodes = %d\n", nodes.len);
//// 設定 E2AP 中的參數
// KPM indication
inter_xapp_e i_0 = ms_5;
//// 對應於 Indication 回報的間隔, E2 Node 據此設定回報的 timer
sm_ans_xapp_t* kpm_handle = NULL;
if(nodes.len > 0){
kpm_handle = calloc( nodes.len, sizeof(sm_ans_xapp_t) );
assert(kpm_handle != NULL);
}
//// 對應於流程圖的 Subscription request
for (int i = 0; i < nodes.len; i++) {
e2_node_connected_t* n = &nodes.n[i];
for (size_t j = 0; j < n->len_rf; j++)
printf("Registered node %d ran func id = %d \n ", i, n->ack_rf[j].id);
kpm_handle[i] = report_sm_xapp_api(&nodes.n[i].id, SM_KPM_ID, i_0, sm_cb_kpm);
//// 回報 Subscription request 是否成功
//// 成功條件: SM ID (SM_KPM_ID), 回報間隔 (i_0) E2 Node 皆支援
//// 並將 Indication 回報對應到 callback function (sm_cb_kpm)
assert(kpm_handle[i].success == true);
}
//// 對應於流程圖中的 Indication (綠框)
//// 在 sleep 的 10 秒中, E2 Node 根據 timer 進行回報, 收到回報由 callback 處理
sleep(10);
//// 對應於流程圖的 Subscription delete
for(int i = 0; i < nodes.len; ++i){
// Remove the handle previously returned
rm_report_sm_xapp_api(kpm_handle[i].u.handle);
}
if(nodes.len > 0){
free(kpm_handle);
}
//Stop the xApp
while(try_stop_xapp_api() == false)
usleep(1000);
printf("Test xApp run SUCCESSFULLY\n");
}
我們可以看到在 Indication 的設計邏輯中,
xApp 是被動的資料接收者, 透過 E2AP 中的回報區間 (inter_xapp_e),
來驅動 E2 Node 進行定時的回報, 並在接收資料後, 以 callback 處理.
值得注意的是, SM 在其中的定位,
理論上, xApp 只需匯入使用的 SM (../src/sm/kpm_sm_v2.02/kpm_sm_id.h),
此資訊必須在 RIC, xApp 和 E2 Node 上皆一致, 才可以成功進行資料傳輸,
在此架構下, 若需要更改傳送間隔, 則需刪除舊有訂閱 (subscription),
並以新的傳送間隔設定, 傳送至 E2 Node, 建立一條新的訂閱.
留言
張貼留言