[ORAN] FlexRIC Sevice Model (3): RIC 對應程式的修改

在完成 Service Model 的定義之後,
我們需要透過程式對所定義的 Service Model 進行操作,
考慮到 FlexRIC 的實作架構, 我們在修改 xApp 和 E2 Agent 的程式前,
要先修改 FlexRIC 相關的程式, 以提供 xApp 和 E2 Agent 串接的支援,
在此實作中, 我們以 Indication 作為開發的應用,
此應用中, xApp 負責送出訂閱 Indication 的需求,
E2 Agent 則將數值填入 Indication Message 中, 並定期發送.
在 FlexRIC 官方網站中, 提供教學的連結如下:

在 FlexRIC 中, 整體的資料交換流程如下:

在上述的流程中, 我們可以歸類於以下 5 個步驟:
  1. E2 Agent 透過 E2 Setup 向 FlexRIC 註冊 (ID, 以及所支援的服務)
  2. xApp 向 FlexRIC 進行註冊 (為自定義的 E42 介面)
  3. xApp 向 E2 Agent 註冊 Indication 服務 (Subscription Request)
  4. E2 Agent 根據訂閱的資訊以及時間間隔, 進行資料回報
  5. xApp 收到資料將數值存入 SQLite (不是標準的 O-RAN 流程, 在此先略去)
  6. xApp 向 E2 Agent 刪除 Indication 服務 (Subscription Delete Request)
在 FlexRIC 對應的 c-code 程式中, 為了加入一個新的 Service Model,
我們也要進行相對應的修改, 包含三個部分: xApp, RIC, 和 E2 Agent,
對應的資料夾位置為: ~/flexric/src/xApp/, ~/flexric/src/ric/iApps/, ~/flexric/examples/,
我們從 xApp 端要進行的修改開始, 這邊所指的 xApp 並非收值的 xApp,
而主要的修改在於 xApp 和 RIC 之間溝通的部分, 包含 FlexRIC 定義的 E42 介面:
(紅字為修改的部分, 藍字為註解)
  • ~/flexric/src/xApp/e42_xapp.c
    // 讓 RIC 平台可以看懂新建立的 Service Model
    // 需要匯入 header 檔, 並修正判斷項次

    #include "../sm/new_sm/new_sm_id.h"
    ...

    static
    bool valid_ran_func_id(uint16_t ran_func_id)

      if(ran_func_id == SM_SLICE_ID 
          ..
          || ran_func_id == SM_NEW_ID
        )
        return true;
      return false;
    }

  • ~/flexric/src/xApp/e42_xapp_api.c
    // 把 Service Model 的 ID 加入判斷式, 按照之前設定, 此數值為 148
    static inline
    bool valid_sm_id(global_e2_node_id_t* id, uint32_t sm_id)
    {
      assert(id != NULL);

      // Only for testing purposes
      assert(sm_id == 142 || sm_id == 143 || sm_id == 144 || sm_id == 145 || sm_id == 147 || sm_id == 148);

      return true;
    }

  • ~/flexric/src/xApp/msg_handler_xapp.c
    // 考慮到對應 Indication 的功能
    // 將 Indication type 中對應的型態加入新的 Service Model

    #include "../sm/new_sm/new_sm_id.h"
    // E2 -> RIC
    e2ap_msg_t e2ap_handle_indication_xapp(e42_xapp_t* xapp, const e2ap_msg_t* msg){
         ...
         assert(msg_disp.rd.type == MAC_STATS_V0 
                 ...
                 || msg_disp.rd.type == NEW_STATS_V0
               );
     }
接下來, 我們要修改 RIC 平台中的 iApp, 
在 FlexRIC 中, iApp 可以想像成 RIC 平台的管理介面,
負責將運作過程中的 log 與資料記錄下來或顯示 (我們之後會解釋),
提供 RIC 平台管理, 或是 xApp 除錯的對應功能.
  • ~/flexric/src/ric/iApps/influx.c
    #include "ric/iApps/../../sm/new_sm/ie/new_data_ie.h"    // for new_ind_msg_t

    void notify_influx_listener(sm_ag_if_rd_t const* data){
      assert(data->type == MAC_STATS_V0 ... || data->type == NEW_STATS_V0);
     
      if(data->type == MAC_STATS_V0){
      ...
      } else if (data->type == NEW_STATS_V0){
        new_ind_msg_t const* new = &data->new_stats.msg;

        char stats[1024] = {0};
        to_string_new_ngut(&new->ngut, new->tstamp, stats, 1024);

         int const rc = sendto(sockfd, stats, strlen(stats),  MSG_CONFIRM, (const struct sockaddr *)
    &servaddr, sizeof(servaddr));
         assert(rc != -1);
      }
    else {
        assert(0 != 0 || "invalid data type ");
      }
    }

  • ~/flexric/src/ric/iApps/redis.c
    void notify_redis_listener(sm_ag_if_rd_t const* data){
      assert(data->type == MAC_STATS_V0 ... || data->type == NEW_STATS_V0);
    }

  • ~/flexric/src/ric/iApps/stdout.c
    // 當收到新的 Service Model 時, 將數值印出來
    // 注意: 資料型態為自定義格式 (new_ng_u_tunnel_stats_t)
    #include "ric/iApps/../../sm/new_sm/ie/new_data_ie.h"

    static
    void print_new_stats(new_ng_u_tunnel_stats_t const* new)
    {
      assert(new != NULL);

      if(fp == NULL)
        init_fp(&fp, file_path);

      
      char stats[1024] = {0};
      to_string_new_ngut(&new->ngut, new->tstamp , stats , 1024);

      int const rc = fputs(stats , fp);
      assert(rc > -1);
      
    }


    void notify_stdout_listener(sm_ag_if_r    d_t const* data)
    {
      assert(data != NULL);
      if(data->type == MAC_STATS_V0) 
        ...
      else if (data->type == NEW_STATS_V0)
        print_new_stats(&data->new_stats.msg);
      else
        assert(0!= 0);
    }

  • ~/flexric/src/ric/iApps/string_parser.c
    // 把 Service Model 的數值轉換成 String 的格式,
    // 這邊請參照之前 Indication Message 定義的格式填入
    // 注意: 資料型態為自定義格式 (new_ng_u_tunnel_stats_t)
    #include "ric/iApps/../../sm/new_sm/ie/new_data_ie.h"

    void to_string_new_ngut(new_ng_u_tunnel_stats_t* ngut, int64_t tstamp , char* out, size_t out_len)
    {
      assert(new != NULL);
      assert(out != NULL);
      const size_t max = 1024;
      assert(out_len >= max);
     
      int const rc = snprintf(out, max,
            "new_stats: tstamp=%ld,"
            "data1=%ld,"
            "data2=%ld,"
            "data3=%ld,"
            "data4=%ld"
            "\n"
            , tstamp 
            , new->data1
            , new->data2
            , new->data3
            , new->data4
            );
      assert(rc < (int)max && "Not enough space in the char array to write all the data");
    }


  • ~/flexric/src/ric/iApps/string_parser.h

    #include "../../sm/new_sm/ie/new_data_ie.h"

    void to_string_new_ngut(new_ng_u_tunnel_stats_t* ngut, int64_t tstamp, char* out, size_t out_len);


  • ~/flexric/src/ric/msg_handler_ric.c

    e2ap_msg_t e2ap_handle_indication_ric(near_ric_t* ric, const e2ap_msg_t* msg){
        ...
        assert(d.type == MAC_STATS_V0 
         ...   
         || d.type == NEW_STATS_V0);
    }
在修改完上述部分的程式後, FlexRIC 才算真的能夠了解新定義的 Service Model,
幸好, 多數的程式定義都和 Service Model 的內容格式無關,
因此, 建立 Sevice Model 的程式修改主要是出現在第一次建立的時候,
之後, 若是修改或是擴充自定義的 Service Model, 只需修改 stdout 的 iApp 就好,
在確定好 FlexRIC 對定義的 Service Model 支援後, 
我們修改測試的 E2 Agent 程式, 引入定義的 Service Model 資訊:
  • ~/flexric/examples/xApp/c/monitor/CMakeLists.txt
    // 編譯路徑的修改
    add_executable(xapp_new_moni 
                    xapp_new_moni.c
                    //... 如果有其他相關的 SM
                    ../../../../src/sm/new_sm/ie/new_data_ie.c
                    )

         
    target_link_libraries(xapp_new_moni
                            PUBLIC
                            e42_xapp
                            -pthread
                            -lsctp
                            -ldl
                            )


  • ~/flexric/examples/emulator/agent/test_agent.c
    // 將填值對應程式放入 read_RAN 的程式中,
    // 真實填值的程式位於: ~/flexric/test/sm/common/fill_ind_data.c
    // 我們將在之後說明此部分程式

    static
    void read_RAN(sm_ag_if_rd_t* data)
    {
      assert(data->type == MAC_STATS_V0 ...
             data->type == NEW_STATS_V0);

      if(data->type == MAC_STATS_V0 ){
        ...
      } else if(data->type == NEW_STATS_V0){
        fill_new_ind_data(&data->new_stats);
      }
    else {
        assert("Invalid data type");
      }
    }

  • ~/flexric/examples/ric/near_ric.c
    // 加入 Service Model 的 ID
    const uint16_t NEW_ran_func_id = 148; //
以上大致完成 FlexRIC 架構中, 加入一個新的 Service Model 所需的修改,
接下來我們會繼續介紹 E2 Agent 和 xApp 所要做的對應修正.

留言

熱門文章

LTE筆記: RSRP, RSSI and RSRQ

[WiFi] WiFi 網路的識別: BSS, ESS, SSID, ESSID, BSSID

LTE筆記: 5G NR Measurement Events