Merge remote-tracking branch 'origin/kpm-rc-cleanup' into integration_2024_w12
This commit is contained in:
@@ -1,43 +1,49 @@
|
||||
add_library(e2_ran_func_cuup STATIC
|
||||
init_ran_func.c
|
||||
read_setup_ran.c
|
||||
../flexric/test/rnd/fill_rnd_data_e2_setup_req.c # this is not rnd data; it is used to fill E2 Node Component Configuration Addition List in E2 Setup Request message
|
||||
CUSTOMIZED/ran_func_gtp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
|
||||
CUSTOMIZED/ran_func_pdcp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
|
||||
O-RAN/ran_e2sm_ue_id.c
|
||||
O-RAN/ran_func_kpm.c
|
||||
O-RAN/ran_func_kpm_subs.c
|
||||
O-RAN/ran_func_rc.c
|
||||
O-RAN/ran_func_rc_subs.c
|
||||
CUSTOMIZED/ran_func_gtp.c # GTP SM not yet implemented in CU-UP
|
||||
CUSTOMIZED/ran_func_pdcp.c
|
||||
CUSTOMIZED/ran_func_tc.c # currently, not implemented; therefore, filling rnd data
|
||||
../flexric/test/rnd/fill_rnd_data_tc.c
|
||||
O-RAN/ran_func_kpm.c # this file should only contain PDCP-U/GTP; to be done in the future
|
||||
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
O-RAN/ran_func_rc.c # this file should only contain PDCP-U/GTP; to be done in the future
|
||||
O-RAN/ran_func_rc_subs.c
|
||||
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
)
|
||||
|
||||
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj)
|
||||
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj sm_common_ie_obj)
|
||||
target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP)
|
||||
|
||||
|
||||
add_library(e2_ran_func_du_cucp_cuup STATIC
|
||||
init_ran_func.c
|
||||
read_setup_ran.c
|
||||
../flexric/test/rnd/fill_rnd_data_e2_setup_req.c # this is not rnd data; it is used to fill E2 Node Component Configuration Addition List in E2 Setup Request message
|
||||
CUSTOMIZED/ran_func_gtp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
|
||||
CUSTOMIZED/ran_func_pdcp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
|
||||
O-RAN/ran_func_kpm.c # this file should only contain RRC/PDCP-C; to be done in the future
|
||||
# when nr-softmodem is divided in separate executables
|
||||
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
O-RAN/ran_func_rc.c # this file should only contain RRC/PDCP-C; to be done in the future
|
||||
# when nr-softmodem is divided in separate executables
|
||||
O-RAN/ran_e2sm_ue_id.c
|
||||
O-RAN/ran_func_kpm.c
|
||||
O-RAN/ran_func_kpm_subs.c
|
||||
O-RAN/ran_func_rc.c
|
||||
O-RAN/ran_func_rc_subs.c
|
||||
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
../flexric/src/sm/rc_sm/ie/rc_data_ie.c
|
||||
CUSTOMIZED/ran_func_gtp.c
|
||||
CUSTOMIZED/ran_func_pdcp.c
|
||||
CUSTOMIZED/ran_func_mac.c
|
||||
CUSTOMIZED/ran_func_rlc.c
|
||||
CUSTOMIZED/ran_func_slice.c
|
||||
CUSTOMIZED/ran_func_tc.c
|
||||
../flexric/test/rnd/fill_rnd_data_tc.c
|
||||
CUSTOMIZED/ran_func_slice.c # currently, not implemented; therefore, filling rnd data
|
||||
../flexric/test/rnd/fill_rnd_data_slice.c
|
||||
CUSTOMIZED/ran_func_tc.c # currently, not implemented; therefore, filling rnd data
|
||||
../flexric/test/rnd/fill_rnd_data_tc.c
|
||||
)
|
||||
|
||||
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj e2_agent)
|
||||
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
|
||||
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj)
|
||||
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
|
||||
|
||||
# Current implementation:
|
||||
# - we only have one executable nr-softmodem for 4 node types: DU, CU, gNB-mono, CU-CP
|
||||
|
||||
# In the future, when nr-softmodem is separated, linking should be done as following:
|
||||
# - DU: e2_ran_func_du
|
||||
# - CU-CP : e2_ran_func_cucp
|
||||
# - CU-UP: e2_ran_func_cuup (this is available at the moment, executable nr-cuup)
|
||||
# - CU: e2_ran_func_cucp + e2_ran_func_cuup
|
||||
# - gNB-mono: e2_ran_func_du + e2_ran_func_cucp + e2_ran_func_cuup
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "ran_e2sm_ue_id.h"
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, __attribute__((unused))const uint32_t rrc_ue_id, __attribute__((unused))const ue_id_t cucp_ue_id)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = {0};
|
||||
|
||||
ue_id.type = GNB_UE_ID_E2SM;
|
||||
|
||||
// 6.2.3.16
|
||||
// Mandatory
|
||||
// AMF UE NGAP ID
|
||||
ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->amf_ue_ngap_id;
|
||||
|
||||
// Mandatory
|
||||
//GUAMI 6.2.3.17
|
||||
ue_id.gnb.guami.plmn_id = (e2sm_plmn_t) {
|
||||
.mcc = rrc_ue_context->ue_guami.mcc,
|
||||
.mnc = rrc_ue_context->ue_guami.mnc,
|
||||
.mnc_digit_len = rrc_ue_context->ue_guami.mnc_len
|
||||
};
|
||||
|
||||
ue_id.gnb.guami.amf_region_id = rrc_ue_context->ue_guami.amf_region_id;
|
||||
ue_id.gnb.guami.amf_set_id = rrc_ue_context->ue_guami.amf_set_id;
|
||||
ue_id.gnb.guami.amf_ptr = rrc_ue_context->ue_guami.amf_pointer;
|
||||
|
||||
// RAN UE ID
|
||||
// Optional
|
||||
// 6.2.3.25
|
||||
// OCTET STRING (SIZE (8))
|
||||
// Defined in TS 38.473 (F1AP)
|
||||
// clause 9.2.2.1
|
||||
// UE CONTEXT SETUP REQUEST
|
||||
ue_id.gnb.ran_ue_id = calloc(1, sizeof(uint64_t));
|
||||
assert(ue_id.gnb.ran_ue_id != NULL);
|
||||
*ue_id.gnb.ran_ue_id = rrc_ue_context->rrc_ue_id;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cu_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = fill_e2sm_gnb_ue_id_data(rrc_ue_context, rrc_ue_id, cucp_ue_id);
|
||||
|
||||
// gNB-CU UE F1AP ID List
|
||||
// C-ifCUDUseparated
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst = calloc(ue_id.gnb.gnb_cu_ue_f1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_ue_f1ap_lst != NULL && "Memory exhausted");
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst[0] = rrc_ue_context->rrc_ue_id;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_du_ue_id_data(__attribute__((unused))const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, __attribute__((unused))const ue_id_t cucp_ue_id)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = {0};
|
||||
|
||||
ue_id.type = GNB_DU_UE_ID_E2SM;
|
||||
|
||||
// 6.2.3.21
|
||||
// gNB CU UE F1AP
|
||||
// Mandatory
|
||||
ue_id.gnb_du.gnb_cu_ue_f1ap = rrc_ue_id;
|
||||
|
||||
// 6.2.3.25
|
||||
// RAN UE ID
|
||||
// Optional
|
||||
ue_id.gnb_du.ran_ue_id = calloc(1, sizeof(uint64_t));
|
||||
assert(ue_id.gnb_du.ran_ue_id != NULL);
|
||||
*ue_id.gnb_du.ran_ue_id = rrc_ue_id;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cucp_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = fill_e2sm_gnb_ue_id_data(rrc_ue_context, rrc_ue_id, cucp_ue_id);
|
||||
|
||||
//gNB-CU-CP UE E1AP ID List
|
||||
//C-ifCPUPseparated
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst = calloc(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst != NULL && "Memory exhausted");
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst[0] = rrc_ue_context->rrc_ue_id;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cuup_ue_id_data(__attribute__((unused))const gNB_RRC_UE_t *rrc_ue_context, __attribute__((unused))const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = {0};
|
||||
|
||||
ue_id.type = GNB_CU_UP_UE_ID_E2SM;
|
||||
|
||||
// 6.2.3.20
|
||||
// Mandatory
|
||||
ue_id.gnb_cu_up.gnb_cu_cp_ue_e1ap = cucp_ue_id; // RAN UE NGAP ID = gNB UE NGAP ID = rrc_ue_id
|
||||
|
||||
// 6.2.3.25
|
||||
// RAN UE ID
|
||||
// Optional
|
||||
ue_id.gnb_cu_up.ran_ue_id = calloc(1, sizeof(uint64_t));
|
||||
assert(ue_id.gnb_cu_up.ran_ue_id != NULL);
|
||||
*ue_id.gnb_cu_up.ran_ue_id = cucp_ue_id; // RAN UE NGAP ID = gNB UE NGAP ID = rrc_ue_id
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
get_ue_id fill_ue_id_data[END_NGRAN_NODE_TYPE] =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
fill_e2sm_gnb_ue_id_data,
|
||||
NULL,
|
||||
NULL,
|
||||
fill_e2sm_cu_ue_id_data,
|
||||
NULL,
|
||||
fill_e2sm_du_ue_id_data,
|
||||
NULL,
|
||||
fill_e2sm_cucp_ue_id_data,
|
||||
fill_e2sm_cuup_ue_id_data,
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef RAN_E2SM_UE_ID_H
|
||||
#define RAN_E2SM_UE_ID_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/../sm/sm_io.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cu_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_du_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cucp_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
ue_id_e2sm_t fill_e2sm_cuup_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
typedef ue_id_e2sm_t (*get_ue_id)(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
|
||||
|
||||
extern get_ue_id fill_ue_id_data[END_NGRAN_NODE_TYPE];
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "ran_func_kpm_subs.h"
|
||||
|
||||
#include <search.h>
|
||||
|
||||
/* measurements that need to store values from previous reporting period have a limitation
|
||||
when it comes to multiple subscriptions to the same UEs; ric_req_id is unique per subscription */
|
||||
typedef struct uldlcounter {
|
||||
uint32_t dl;
|
||||
uint32_t ul;
|
||||
} uldlcounter_t;
|
||||
|
||||
static uldlcounter_t last_pdcp_sdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
|
||||
static nr_pdcp_statistics_t get_pdcp_stats_per_drb(const uint32_t rrc_ue_id, const int rb_id)
|
||||
{
|
||||
nr_pdcp_statistics_t pdcp = {0};
|
||||
const int srb_flag = 0;
|
||||
|
||||
// Get PDCP stats for specific DRB
|
||||
const bool rc = nr_pdcp_get_statistics(rrc_ue_id, srb_flag, rb_id, &pdcp);
|
||||
assert(rc == true && "Cannot get PDCP stats\n");
|
||||
|
||||
return pdcp;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.2.1.1.1
|
||||
note: this measurement is calculated as per spec */
|
||||
static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
// Get PDCP stats per DRB
|
||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||
nr_pdcp_statistics_t pdcp = get_pdcp_stats_per_drb(ue_info.rrc_ue_id, rb_id);
|
||||
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get DL data volume delivered to PDCP layer
|
||||
meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000; // [kb]
|
||||
last_pdcp_sdu_total_bytes[ue_idx].dl = pdcp.rxsdu_bytes;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.2.1.2.1
|
||||
note: this measurement is calculated as per spec */
|
||||
static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
// Get PDCP stats per DRB
|
||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||
nr_pdcp_statistics_t pdcp = get_pdcp_stats_per_drb(ue_info.rrc_ue_id, rb_id);
|
||||
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get UL data volume delivered from PDCP layer
|
||||
meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000; // [kb]
|
||||
last_pdcp_sdu_total_bytes[ue_idx].ul = pdcp.txsdu_bytes;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
#if defined (NGRAN_GNB_DU)
|
||||
static uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
static uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0};
|
||||
|
||||
static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb_id)
|
||||
{
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
|
||||
// Get RLC stats for specific DRB
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rlc);
|
||||
assert(rc == true && "Cannot get RLC stats\n");
|
||||
|
||||
// Activate average sojourn time at the RLC buffer for specific DRB
|
||||
nr_rlc_activate_avg_time_to_tx(rnti, rb_id+3, 1);
|
||||
|
||||
return rlc;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.3.3.3
|
||||
note: by default this measurement is calculated for previous 100ms (openair2/LAYER2/nr_rlc/nr_rlc_entity.c:118, 173, 213); please, update according to your needs */
|
||||
static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
// Get RLC stats per DRB
|
||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
|
||||
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Get the value of sojourn time at the RLC buffer
|
||||
meas_record.real_val = rlc.txsdu_avg_time_to_tx; // [μs]
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.1.3.1
|
||||
note: per spec, average UE throughput in DL (taken into consideration values from all UEs, and averaged)
|
||||
here calculated as: UE specific throughput in DL */
|
||||
static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
// Get RLC stats per DRB
|
||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate DL Thp
|
||||
meas_record.real_val = (double)(rlc.txpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].dl)*8/gran_period_ms; // [kbps]
|
||||
last_rlc_pdu_total_bytes[ue_idx].dl = rlc.txpdu_bytes;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.1.3.3
|
||||
note: per spec, average UE throughput in UL (taken into consideration values from all UEs, and averaged)
|
||||
here calculated as: UE specific throughput in UL */
|
||||
static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
// Get RLC stats per DRB
|
||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
|
||||
|
||||
meas_record.value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate UL Thp
|
||||
meas_record.real_val = (double)(rlc.rxpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].ul)*8/gran_period_ms; // [kbps]
|
||||
last_rlc_pdu_total_bytes[ue_idx].ul = rlc.rxpdu_bytes;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.1.2.1
|
||||
note: per spec, DL PRB usage [%] = (total used PRBs for DL traffic / total available PRBs for DL traffic) * 100
|
||||
here calculated as: aggregated DL PRBs (t) - aggregated DL PRBs (t-gran_period) */
|
||||
static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get the number of DL PRBs
|
||||
meas_record.int_val = ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl; // [PRBs]
|
||||
last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
|
||||
/* 3GPP TS 28.522 - section 5.1.1.2.2
|
||||
note: per spec, UL PRB usage [%] = (total used PRBs for UL traffic / total available PRBs for UL traffic) * 100
|
||||
here calculated as: aggregated UL PRBs (t) - aggregated UL PRBs (t-gran_period) */
|
||||
static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
meas_record_lst_t meas_record = {0};
|
||||
|
||||
meas_record.value = INTEGER_MEAS_VALUE;
|
||||
|
||||
// Get the number of UL PRBs
|
||||
meas_record.int_val = ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul; // [PRBs]
|
||||
last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs;
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
#endif
|
||||
|
||||
static kv_measure_t lst_measure[] = {
|
||||
{.key = "DRB.PdcpSduVolumeDL", .value = fill_DRB_PdcpSduVolumeDL },
|
||||
{.key = "DRB.PdcpSduVolumeUL", .value = fill_DRB_PdcpSduVolumeUL },
|
||||
#if defined (NGRAN_GNB_DU)
|
||||
{.key = "DRB.RlcSduDelayDl", .value = fill_DRB_RlcSduDelayDl },
|
||||
{.key = "DRB.UEThpDl", .value = fill_DRB_UEThpDl },
|
||||
{.key = "DRB.UEThpUl", .value = fill_DRB_UEThpUl },
|
||||
{.key = "RRU.PrbTotDl", .value = fill_RRU_PrbTotDl },
|
||||
{.key = "RRU.PrbTotUl", .value = fill_RRU_PrbTotUl },
|
||||
#endif
|
||||
};
|
||||
|
||||
void init_kpm_subs_data(void)
|
||||
{
|
||||
const size_t ht_len = sizeof(lst_measure) / sizeof(lst_measure[0]);
|
||||
hcreate(ht_len);
|
||||
|
||||
ENTRY kv_pair;
|
||||
|
||||
for (size_t i = 0; i < ht_len; i++) {
|
||||
kv_pair.key = lst_measure[i].key;
|
||||
kv_pair.data = &lst_measure[i];
|
||||
hsearch(kv_pair, ENTER);
|
||||
}
|
||||
}
|
||||
|
||||
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
|
||||
{
|
||||
assert(kpm_meas_name != NULL);
|
||||
|
||||
ENTRY search_entry = {.key = kpm_meas_name};
|
||||
ENTRY *found_entry = hsearch(search_entry, FIND);
|
||||
assert(found_entry != NULL && "Unsupported KPM measurement name");
|
||||
|
||||
kv_measure_t *kv_found = (kv_measure_t *)found_entry->data;
|
||||
meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx);
|
||||
|
||||
return meas_record;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef RAN_FUNC_SM_KPM_SUBSCRIPTION_AGENT_H
|
||||
#define RAN_FUNC_SM_KPM_SUBSCRIPTION_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/sm/kpm_sm/kpm_data_ie_wrapper.h"
|
||||
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t rrc_ue_id;
|
||||
NR_UE_info_t* ue;
|
||||
|
||||
} cudu_ue_info_pair_t;
|
||||
|
||||
typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
|
||||
|
||||
typedef struct{
|
||||
char* key;
|
||||
kpm_meas_fp value;
|
||||
} kv_measure_t;
|
||||
|
||||
|
||||
void init_kpm_subs_data(void);
|
||||
|
||||
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
|
||||
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "ran_func_rc.h"
|
||||
#include "ran_func_rc_subs.h"
|
||||
#include "ran_func_rc_extern.h"
|
||||
#include "../../flexric/test/rnd/fill_rnd_data_rc.h" // this dependancy will be taken out once RAN Function Definition is implemented
|
||||
#include "ran_e2sm_ue_id.h"
|
||||
#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
|
||||
#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h"
|
||||
#include "../../flexric/src/agent/e2_agent_api.h"
|
||||
@@ -35,17 +35,440 @@ static pthread_once_t once_rc_mutex = PTHREAD_ONCE_INIT;
|
||||
static rc_subs_data_t rc_subs_data = {0};
|
||||
static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static ngran_node_t get_e2_node_type(void)
|
||||
{
|
||||
ngran_node_t node_type = 0;
|
||||
|
||||
#if defined(NGRAN_GNB_DU) && defined(NGRAN_GNB_CUUP) && defined(NGRAN_GNB_CUCP)
|
||||
node_type = RC.nrrrc[0]->node_type;
|
||||
#elif defined (NGRAN_GNB_CUUP)
|
||||
node_type = ngran_gNB_CUUP;
|
||||
#endif
|
||||
|
||||
return node_type;
|
||||
}
|
||||
|
||||
static void init_once_rc(void)
|
||||
{
|
||||
init_rc_subs_data(&rc_subs_data);
|
||||
}
|
||||
|
||||
static void fill_rc_ev_trig(ran_func_def_ev_trig_t* ev_trig)
|
||||
{
|
||||
// Sequence of EVENT TRIGGER styles
|
||||
// [1 - 63]
|
||||
ev_trig->sz_seq_ev_trg_style = 1;
|
||||
ev_trig->seq_ev_trg_style = calloc(ev_trig->sz_seq_ev_trg_style, sizeof(seq_ev_trg_style_t));
|
||||
assert(ev_trig->seq_ev_trg_style != NULL && "Memory exhausted");
|
||||
|
||||
seq_ev_trg_style_t* ev_trig_style = &ev_trig->seq_ev_trg_style[0];
|
||||
|
||||
// RIC Event Trigger Style Type
|
||||
// Mandatory
|
||||
// 9.3.3
|
||||
// 6.2.2.2.
|
||||
// INTEGER
|
||||
ev_trig_style->style = 4;
|
||||
|
||||
// RIC Event Trigger Style Name
|
||||
// Mandatory
|
||||
// 9.3.4
|
||||
// 6.2.2.3
|
||||
//PrintableString(SIZE(1..150,...))
|
||||
const char ev_style_name[] = "UE Information Change";
|
||||
ev_trig_style->name = cp_str_to_ba(ev_style_name);
|
||||
|
||||
// RIC Event Trigger Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
// 6.2.2.4.
|
||||
// INTEGER
|
||||
ev_trig_style->format = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT;
|
||||
|
||||
// Sequence of RAN Parameters for L2 Variables
|
||||
// [0 - 65535]
|
||||
ev_trig->sz_seq_ran_param_l2_var = 0;
|
||||
ev_trig->seq_ran_param_l2_var = NULL;
|
||||
|
||||
//Sequence of Call Process Types
|
||||
// [0-65535]
|
||||
ev_trig->sz_seq_call_proc_type = 0;
|
||||
ev_trig->seq_call_proc_type = NULL;
|
||||
|
||||
// Sequence of RAN Parameters for Identifying UEs
|
||||
// 0-65535
|
||||
ev_trig->sz_seq_ran_param_id_ue = 0;
|
||||
ev_trig->seq_ran_param_id_ue = NULL;
|
||||
|
||||
// Sequence of RAN Parameters for Identifying Cells
|
||||
// 0-65535
|
||||
ev_trig->sz_seq_ran_param_id_cell = 0;
|
||||
ev_trig->seq_ran_param_id_cell = NULL;
|
||||
}
|
||||
|
||||
static void fill_rc_report(ran_func_def_report_t* report)
|
||||
{
|
||||
// Sequence of REPORT styles
|
||||
// [1 - 63]
|
||||
report->sz_seq_report_sty = 1;
|
||||
report->seq_report_sty = calloc(report->sz_seq_report_sty, sizeof(seq_report_sty_t));
|
||||
assert(report->seq_report_sty != NULL && "Memory exhausted");
|
||||
|
||||
seq_report_sty_t* report_style = &report->seq_report_sty[0];
|
||||
|
||||
// RIC Report Style Type
|
||||
// Mandatory
|
||||
// 9.3.3
|
||||
// 6.2.2.2.
|
||||
// INTEGER
|
||||
report_style->report_type = 4;
|
||||
|
||||
// RIC Report Style Name
|
||||
// Mandatory
|
||||
// 9.3.4
|
||||
// 6.2.2.3.
|
||||
// PrintableString(SIZE(1..150,...))
|
||||
const char report_name[] = "UE Information";
|
||||
report_style->name = cp_str_to_ba(report_name);
|
||||
|
||||
// Supported RIC Event Trigger Style Type
|
||||
// Mandatory
|
||||
// 9.3.3
|
||||
// 6.2.2.2.
|
||||
// INTEGER
|
||||
report_style->ev_trig_type = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT;
|
||||
|
||||
// RIC Report Action Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
// 6.2.2.4.
|
||||
// INTEGER
|
||||
report_style->act_frmt_type = FORMAT_1_E2SM_RC_ACT_DEF;
|
||||
|
||||
// RIC Indication Header Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
// 6.2.2.4.
|
||||
// INTEGER
|
||||
report_style->ind_hdr_type = FORMAT_1_E2SM_RC_IND_HDR;
|
||||
|
||||
// RIC Indication Message Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
// 6.2.2.4.
|
||||
// INTEGER
|
||||
report_style->ind_msg_type = FORMAT_2_E2SM_RC_IND_MSG;
|
||||
|
||||
// Sequence of RAN Parameters Supported
|
||||
// [0 - 65535]
|
||||
report_style->sz_seq_ran_param = 1;
|
||||
report_style->ran_param = calloc(report_style->sz_seq_ran_param, sizeof(seq_ran_param_3_t));
|
||||
assert(report_style->ran_param != NULL && "Memory exhausted");
|
||||
|
||||
// RAN Parameter ID
|
||||
// Mandatory
|
||||
// 9.3.8
|
||||
// [1- 4294967295]
|
||||
report_style->ran_param[0].id = RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID;
|
||||
|
||||
// RAN Parameter Name
|
||||
// Mandatory
|
||||
// 9.3.9
|
||||
// [1-150]
|
||||
const char ran_param_name[] = "RRC State";
|
||||
report_style->ran_param[0].name = cp_str_to_ba(ran_param_name);
|
||||
|
||||
// RAN Parameter Definition
|
||||
// Optional
|
||||
// 9.3.51
|
||||
report_style->ran_param[0].def = NULL;
|
||||
}
|
||||
|
||||
static void fill_rc_control(ran_func_def_ctrl_t* ctrl)
|
||||
{
|
||||
// Sequence of CONTROL styles
|
||||
// [1 - 63]
|
||||
ctrl->sz_seq_ctrl_style = 1;
|
||||
ctrl->seq_ctrl_style = calloc(ctrl->sz_seq_ctrl_style, sizeof(seq_ctrl_style_t));
|
||||
assert(ctrl->seq_ctrl_style != NULL && "Memory exhausted");
|
||||
|
||||
seq_ctrl_style_t* ctrl_style = &ctrl->seq_ctrl_style[0];
|
||||
|
||||
// RIC Control Style Type
|
||||
// Mandatory
|
||||
// 9.3.3
|
||||
// 6.2.2.2
|
||||
ctrl_style->style_type = 1;
|
||||
|
||||
//RIC Control Style Name
|
||||
//Mandatory
|
||||
//9.3.4
|
||||
// [1 -150]
|
||||
const char control_name[] = "Radio Bearer Control";
|
||||
ctrl_style->name = cp_str_to_ba(control_name);
|
||||
|
||||
// RIC Control Header Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
ctrl_style->hdr = FORMAT_1_E2SM_RC_CTRL_HDR;
|
||||
|
||||
// RIC Control Message Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
ctrl_style->msg = FORMAT_1_E2SM_RC_CTRL_MSG;
|
||||
|
||||
// RIC Call Process ID Format Type
|
||||
// Optional
|
||||
ctrl_style->call_proc_id_type = NULL;
|
||||
|
||||
// RIC Control Outcome Format Type
|
||||
// Mandatory
|
||||
// 9.3.5
|
||||
ctrl_style->out_frmt = FORMAT_1_E2SM_RC_CTRL_OUT;
|
||||
|
||||
// Sequence of Control Actions
|
||||
// [0-65535]
|
||||
ctrl_style->sz_seq_ctrl_act = 1;
|
||||
ctrl_style->seq_ctrl_act = calloc(ctrl_style->sz_seq_ctrl_act, sizeof(seq_ctrl_act_2_t));
|
||||
assert(ctrl_style->seq_ctrl_act != NULL && "Memory exhausted");
|
||||
|
||||
seq_ctrl_act_2_t* ctrl_act = &ctrl_style->seq_ctrl_act[0];
|
||||
|
||||
// Control Action ID
|
||||
// Mandatory
|
||||
// 9.3.6
|
||||
// [1-65535]
|
||||
ctrl_act->id = 2;
|
||||
|
||||
// Control Action Name
|
||||
// Mandatory
|
||||
// 9.3.7
|
||||
// [1-150]
|
||||
const char control_act_name[] = "QoS flow mapping configuration";
|
||||
ctrl_act->name = cp_str_to_ba(control_act_name);
|
||||
|
||||
// Sequence of Associated RAN Parameters
|
||||
// [0-65535]
|
||||
ctrl_act->sz_seq_assoc_ran_param = 2;
|
||||
ctrl_act->assoc_ran_param = calloc(ctrl_act->sz_seq_assoc_ran_param, sizeof(seq_ran_param_3_t));
|
||||
assert(ctrl_act->assoc_ran_param != NULL && "Memory exhausted");
|
||||
|
||||
seq_ran_param_3_t* assoc_ran_param = ctrl_act->assoc_ran_param;
|
||||
|
||||
// DRB ID
|
||||
assoc_ran_param[0].id = 1;
|
||||
const char ran_param_drb_id[] = "DRB ID";
|
||||
assoc_ran_param[0].name = cp_str_to_ba(ran_param_drb_id);
|
||||
assoc_ran_param[0].def = NULL;
|
||||
|
||||
// List of QoS Flows to be modified in DRB
|
||||
assoc_ran_param[1].id = 2;
|
||||
const char ran_param_list_qos_flow[] = "List of QoS Flows to be modified in DRB";
|
||||
assoc_ran_param[1].name = cp_str_to_ba(ran_param_list_qos_flow);
|
||||
assoc_ran_param[1].def = calloc(1, sizeof(ran_param_def_t));
|
||||
assert(assoc_ran_param[1].def != NULL && "Memory exhausted");
|
||||
|
||||
assoc_ran_param[1].def->type = LIST_RAN_PARAMETER_DEF_TYPE;
|
||||
assoc_ran_param[1].def->lst = calloc(1, sizeof(ran_param_type_t));
|
||||
assert(assoc_ran_param[1].def->lst != NULL && "Memory exhausted");
|
||||
|
||||
ran_param_type_t* lst = assoc_ran_param[1].def->lst;
|
||||
lst->sz_ran_param = 2;
|
||||
lst->ran_param = calloc(lst->sz_ran_param, sizeof(ran_param_lst_struct_t));
|
||||
assert(lst->ran_param != NULL && "Memory exhausted");
|
||||
|
||||
// QoS Flow Identifier
|
||||
lst->ran_param[0].ran_param_id = 4;
|
||||
const char ran_param_qos_flow_id[] = "QoS Flow Identifier";
|
||||
lst->ran_param[0].ran_param_name = cp_str_to_ba(ran_param_qos_flow_id);
|
||||
lst->ran_param[0].ran_param_def = NULL;
|
||||
|
||||
// QoS Flow Mapping Indication
|
||||
lst->ran_param[1].ran_param_id = 5;
|
||||
const char ran_param_qos_flow_mapping_ind[] = "QoS Flow Mapping Indication";
|
||||
lst->ran_param[1].ran_param_name = cp_str_to_ba(ran_param_qos_flow_mapping_ind);
|
||||
lst->ran_param[1].ran_param_def = NULL;
|
||||
|
||||
// Sequence of Associated RAN
|
||||
// Parameters for Control Outcome
|
||||
// [0- 255]
|
||||
ctrl_style->sz_ran_param_ctrl_out = 0;
|
||||
ctrl_style->ran_param_ctrl_out = NULL;
|
||||
}
|
||||
|
||||
e2sm_rc_func_def_t fill_rc_ran_def_gnb(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
def.ev_trig = calloc(1, sizeof(ran_func_def_ev_trig_t));
|
||||
assert(def.ev_trig != NULL && "Memory exhausted");
|
||||
fill_rc_ev_trig(def.ev_trig);
|
||||
|
||||
// RAN Function Definition for REPORT
|
||||
// Optional
|
||||
// 9.2.2.3
|
||||
def.report = calloc(1, sizeof(ran_func_def_report_t));
|
||||
assert(def.report != NULL && "Memory exhausted");
|
||||
fill_rc_report(def.report);
|
||||
|
||||
// RAN Function Definition for INSERT
|
||||
// Optional
|
||||
// 9.2.2.4
|
||||
def.insert = NULL;
|
||||
|
||||
// RAN Function Definition for CONTROL
|
||||
// Optional
|
||||
// 9.2.2.5
|
||||
def.ctrl = calloc(1, sizeof(ran_func_def_ctrl_t));
|
||||
assert(def.ctrl != NULL && "Memory exhausted");
|
||||
fill_rc_control(def.ctrl);
|
||||
|
||||
// RAN Function Definition for POLICY
|
||||
// Optional
|
||||
// 9.2.2.6
|
||||
def.policy = NULL;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static e2sm_rc_func_def_t fill_rc_ran_def_cu(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
def.ev_trig = calloc(1, sizeof(ran_func_def_ev_trig_t));
|
||||
assert(def.ev_trig != NULL && "Memory exhausted");
|
||||
fill_rc_ev_trig(def.ev_trig);
|
||||
|
||||
// RAN Function Definition for REPORT
|
||||
// Optional
|
||||
// 9.2.2.3
|
||||
def.report = calloc(1, sizeof(ran_func_def_report_t));
|
||||
assert(def.report != NULL && "Memory exhausted");
|
||||
fill_rc_report(def.report);
|
||||
|
||||
// RAN Function Definition for INSERT
|
||||
// Optional
|
||||
// 9.2.2.4
|
||||
def.insert = NULL;
|
||||
|
||||
// RAN Function Definition for CONTROL
|
||||
// Optional
|
||||
// 9.2.2.5
|
||||
def.ctrl = calloc(1, sizeof(ran_func_def_ctrl_t));
|
||||
assert(def.ctrl != NULL && "Memory exhausted");
|
||||
fill_rc_control(def.ctrl);
|
||||
|
||||
// RAN Function Definition for POLICY
|
||||
// Optional
|
||||
// 9.2.2.6
|
||||
def.policy = NULL;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static e2sm_rc_func_def_t fill_rc_ran_def_null(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
def.ev_trig = NULL;
|
||||
|
||||
// RAN Function Definition for REPORT
|
||||
// Optional
|
||||
// 9.2.2.3
|
||||
def.report = NULL;
|
||||
|
||||
// RAN Function Definition for INSERT
|
||||
// Optional
|
||||
// 9.2.2.4
|
||||
def.insert = NULL;
|
||||
|
||||
// RAN Function Definition for CONTROL
|
||||
// Optional
|
||||
// 9.2.2.5
|
||||
def.ctrl = NULL;
|
||||
|
||||
// RAN Function Definition for POLICY
|
||||
// Optional
|
||||
// 9.2.2.6
|
||||
def.policy = NULL;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static e2sm_rc_func_def_t fill_rc_ran_def_cucp(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
def.ev_trig = calloc(1, sizeof(ran_func_def_ev_trig_t));
|
||||
assert(def.ev_trig != NULL && "Memory exhausted");
|
||||
fill_rc_ev_trig(def.ev_trig);
|
||||
|
||||
// RAN Function Definition for REPORT
|
||||
// Optional
|
||||
// 9.2.2.3
|
||||
def.report = calloc(1, sizeof(ran_func_def_report_t));
|
||||
assert(def.report != NULL && "Memory exhausted");
|
||||
fill_rc_report(def.report);
|
||||
|
||||
// RAN Function Definition for INSERT
|
||||
// Optional
|
||||
// 9.2.2.4
|
||||
def.insert = NULL;
|
||||
|
||||
// RAN Function Definition for CONTROL
|
||||
// Optional
|
||||
// 9.2.2.5
|
||||
def.ctrl = NULL;
|
||||
|
||||
// RAN Function Definition for POLICY
|
||||
// Optional
|
||||
// 9.2.2.6
|
||||
def.policy = NULL;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
typedef e2sm_rc_func_def_t (*fp_rc_func_def)(void);
|
||||
|
||||
static const fp_rc_func_def ran_def_rc[END_NGRAN_NODE_TYPE] =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
fill_rc_ran_def_gnb,
|
||||
NULL,
|
||||
NULL,
|
||||
fill_rc_ran_def_cu,
|
||||
NULL,
|
||||
fill_rc_ran_def_null, // DU - at the moment, no Service is supported
|
||||
NULL,
|
||||
fill_rc_ran_def_cucp,
|
||||
fill_rc_ran_def_null, // CU-UP - at the moment, no Service is supported
|
||||
};
|
||||
|
||||
void read_rc_setup_sm(void* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
// assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0);
|
||||
rc_e2_setup_t* rc = (rc_e2_setup_t*)data;
|
||||
rc->ran_func_def = fill_rc_ran_func_def();
|
||||
|
||||
/* Fill the RAN Function Definition with currently supported measurements */
|
||||
|
||||
// RAN Function Name is already filled in fill_ran_function_name() in rc_sm_agent.c
|
||||
|
||||
const ngran_node_t node_type = get_e2_node_type();
|
||||
rc->ran_func_def = ran_def_rc[node_type]();
|
||||
|
||||
// E2 Setup Request is sent periodically until the connection is established
|
||||
// RC subscritpion data should be initialized only once
|
||||
@@ -56,53 +479,6 @@ void read_rc_setup_sm(void* data)
|
||||
|
||||
RB_PROTOTYPE(ric_id_2_param_id_trees, ric_req_id_s, entries, cmp_ric_req_id);
|
||||
|
||||
static ue_id_e2sm_t fill_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = {0};
|
||||
|
||||
// Check the E2 node type
|
||||
#if defined (NGRAN_GNB_CUUP) && defined (NGRAN_GNB_CUCP)
|
||||
ue_id.type = GNB_UE_ID_E2SM;
|
||||
if (RC.nrrrc[0]->node_type == ngran_gNB_CU) {
|
||||
// gNB-CU UE F1AP ID List
|
||||
// C-ifCUDUseparated
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst = calloc(ue_id.gnb.gnb_cu_ue_f1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_ue_f1ap_lst != NULL && "Memory exhausted");
|
||||
|
||||
for(size_t i = 0; i < ue_id.gnb.gnb_cu_ue_f1ap_lst_len; i++) {
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst[i] = rrc_ue_context->rrc_ue_id;
|
||||
}
|
||||
} else if (RC.nrrrc[0]->node_type == ngran_gNB_CUCP) {
|
||||
//gNB-CU-CP UE E1AP ID List
|
||||
//C-ifCPUPseparated
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst = calloc(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst != NULL && "Memory exhausted");
|
||||
|
||||
for(size_t i = 0; i < ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len; i++) {
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst[i] = rrc_ue_context->rrc_ue_id;
|
||||
}
|
||||
} else if (RC.nrrrc[0]->node_type == ngran_gNB_DU) {
|
||||
assert(false && "RRC state change cannot be triggered from DU\n");
|
||||
}
|
||||
|
||||
#elif defined (NGRAN_GNB_CUUP)
|
||||
assert(false && "RRC state change cannot be triggered from CU-UP\n");
|
||||
|
||||
#endif
|
||||
|
||||
ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->rrc_ue_id;
|
||||
ue_id.gnb.guami.amf_ptr = rrc_ue_context->ue_guami.amf_pointer;
|
||||
ue_id.gnb.guami.amf_region_id = rrc_ue_context->ue_guami.amf_region_id;
|
||||
ue_id.gnb.guami.amf_set_id = rrc_ue_context->ue_guami.amf_set_id;
|
||||
ue_id.gnb.guami.plmn_id.mcc = rrc_ue_context->ue_guami.mcc;
|
||||
ue_id.gnb.guami.plmn_id.mnc = rrc_ue_context->ue_guami.mnc;
|
||||
ue_id.gnb.guami.plmn_id.mnc_digit_len = rrc_ue_context->ue_guami.mnc_len;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
static seq_ran_param_t fill_rrc_state_change_seq_ran(const rc_sm_rrc_state_e rrc_state)
|
||||
{
|
||||
seq_ran_param_t seq_ran_param = {0};
|
||||
@@ -138,7 +514,8 @@ static rc_ind_data_t* fill_ue_rrc_state_change(const gNB_RRC_UE_t *rrc_ue_contex
|
||||
// UE ID
|
||||
// Mandatory
|
||||
// 9.3.10
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].ue_id = fill_ue_id_data(rrc_ue_context);
|
||||
const ngran_node_t node_type = get_e2_node_type();
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].ue_id = fill_ue_id_data[node_type](rrc_ue_context, 0, 0);
|
||||
|
||||
// Sequence of
|
||||
// RAN Parameter
|
||||
@@ -221,39 +598,45 @@ sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
|
||||
// assert(data->type == RAN_CONTROL_CTRL_V1_03 );
|
||||
|
||||
rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data;
|
||||
if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){
|
||||
if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){
|
||||
printf("QoS flow mapping configuration \n");
|
||||
e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1;
|
||||
for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){
|
||||
seq_ran_param_t const* rp = frmt_1->ran_param;
|
||||
if(rp[i].ran_param_id == 1){
|
||||
assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE );
|
||||
printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran);
|
||||
} else if(rp[i].ran_param_id == 2){
|
||||
assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE);
|
||||
printf("List of QoS Flows to be modified \n");
|
||||
for(size_t j = 0; j < ctrl->msg.frmt_1.ran_param[i].ran_param_val.lst->sz_lst_ran_param; ++j){
|
||||
lst_ran_param_t const* lrp = rp[i].ran_param_val.lst->lst_ran_param;
|
||||
// The following assertion should be true, but there is a bug in the std
|
||||
// check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984
|
||||
// assert(lrp[j].ran_param_id == 3);
|
||||
assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_id == 4) ;
|
||||
assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE);
|
||||
|
||||
int64_t qfi = lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran;
|
||||
assert(qfi > -1 && qfi < 65);
|
||||
assert(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR && "Indication Header Format received not valid");
|
||||
assert(ctrl->msg.format == FORMAT_1_E2SM_RC_CTRL_MSG && "Indication Message Format received not valid");
|
||||
assert(ctrl->hdr.frmt_1.ctrl_act_id == 2 && "Currently only QoS flow mapping configuration supported");
|
||||
|
||||
printf("QoS flow mapping configuration\n");
|
||||
|
||||
const seq_ran_param_t* ran_param = ctrl->msg.frmt_1.ran_param;
|
||||
|
||||
// DRB ID
|
||||
assert(ran_param[0].ran_param_id == 1 && "First RAN Parameter ID has to be DRB ID");
|
||||
assert(ran_param[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE);
|
||||
printf("DRB ID %ld \n", ran_param[0].ran_param_val.flag_true->int_ran);
|
||||
|
||||
|
||||
// List of QoS Flows to be modified in DRB
|
||||
assert(ran_param[1].ran_param_id == 2 && "Second RAN Parameter ID has to be List of QoS Flows");
|
||||
assert(ran_param[1].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE);
|
||||
printf("List of QoS Flows to be modified in DRB\n");
|
||||
const lst_ran_param_t* lrp = ran_param[1].ran_param_val.lst->lst_ran_param;
|
||||
|
||||
// The following assertion should be true, but there is a bug in the std
|
||||
// check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984
|
||||
// assert(lrp->ran_param_struct.ran_param_struct[0].ran_param_id == 3);
|
||||
|
||||
// QoS Flow Identifier
|
||||
assert(lrp->ran_param_struct.ran_param_struct[0].ran_param_id == 4);
|
||||
assert(lrp->ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE);
|
||||
int64_t qfi = lrp->ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran;
|
||||
assert(qfi > -1 && qfi < 65);
|
||||
|
||||
// QoS Flow Mapping Indication
|
||||
assert(lrp->ran_param_struct.ran_param_struct[1].ran_param_id == 5);
|
||||
assert(lrp->ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE);
|
||||
int64_t dir = lrp->ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran;
|
||||
assert(dir == 0 || dir == 1);
|
||||
|
||||
printf("qfi = %ld, dir %ld \n", qfi, dir);
|
||||
|
||||
assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_id == 5);
|
||||
assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE);
|
||||
int64_t dir = lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran;
|
||||
assert(dir == 0 || dir == 1);
|
||||
printf("qfi = %ld dir %ld \n", qfi, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0};
|
||||
ans.ctrl_out.type = RAN_CTRL_V1_3_AGENT_IF_CTRL_ANS_V0;
|
||||
|
||||
@@ -21,10 +21,109 @@
|
||||
|
||||
#include "read_setup_ran.h"
|
||||
#include "../../E2AP/flexric/src/lib/e2ap/e2ap_node_component_config_add_wrapper.h"
|
||||
#include "../../E2AP/flexric/test/rnd/fill_rnd_data_e2_setup_req.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(E2AP_V2) || defined(E2AP_V3)
|
||||
// NGAP
|
||||
static e2ap_node_component_config_add_t fill_ngap_e2ap_node_component_config_add(void)
|
||||
{
|
||||
e2ap_node_component_config_add_t dst = {0};
|
||||
|
||||
// Mandatory
|
||||
// 9.2.26
|
||||
dst.e2_node_comp_interface_type = NG_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
// Bug!! Optional in the standard, mandatory in ASN.1
|
||||
// 9.2.32
|
||||
dst.e2_node_comp_id.type = NG_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
|
||||
const char ng_msg[] = "Dummy message";
|
||||
dst.e2_node_comp_id.ng_amf_name = cp_str_to_ba(ng_msg);
|
||||
|
||||
// Mandatory
|
||||
// 9.2.27
|
||||
const char req[] = "NGAP Request Message sent";
|
||||
const char res[] = "NGAP Response Message reveived";
|
||||
|
||||
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
|
||||
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
|
||||
return dst;
|
||||
}
|
||||
|
||||
// F1AP
|
||||
static e2ap_node_component_config_add_t fill_f1ap_e2ap_node_component_config_add(void)
|
||||
{
|
||||
e2ap_node_component_config_add_t dst = {0};
|
||||
|
||||
// Mandatory
|
||||
// 9.2.26
|
||||
dst.e2_node_comp_interface_type = F1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
// Bug!! Optional in the standard, mandatory in ASN.1
|
||||
// 9.2.32
|
||||
dst.e2_node_comp_id.type = F1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
|
||||
dst.e2_node_comp_id.f1_gnb_du_id = 1023;
|
||||
|
||||
// Mandatory
|
||||
// 9.2.27
|
||||
const char req[] = "F1AP Request Message sent";
|
||||
const char res[] = "F1AP Response Message reveived";
|
||||
|
||||
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
|
||||
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
|
||||
return dst;
|
||||
}
|
||||
|
||||
// E1AP
|
||||
static e2ap_node_component_config_add_t fill_e1ap_e2ap_node_component_config_add(void)
|
||||
{
|
||||
e2ap_node_component_config_add_t dst = {0};
|
||||
|
||||
// Mandatory
|
||||
// 9.2.26
|
||||
dst.e2_node_comp_interface_type = E1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
// Bug!! Optional in the standard, mandatory in ASN.1
|
||||
// 9.2.32
|
||||
dst.e2_node_comp_id.type = E1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
|
||||
dst.e2_node_comp_id.e1_gnb_cu_up_id = 1025;
|
||||
|
||||
// Mandatory
|
||||
// 9.2.27
|
||||
const char req[] = "E1AP Request Message sent";
|
||||
const char res[] = "E1AP Response Message reveived";
|
||||
|
||||
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
|
||||
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
|
||||
return dst;
|
||||
}
|
||||
|
||||
// S1AP
|
||||
static e2ap_node_component_config_add_t fill_s1ap_e2ap_node_component_config_add(void)
|
||||
{
|
||||
e2ap_node_component_config_add_t dst = {0};
|
||||
|
||||
// Mandatory
|
||||
// 9.2.26
|
||||
dst.e2_node_comp_interface_type = S1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
// Bug!! Optional in the standard, mandatory in ASN.1
|
||||
// 9.2.32
|
||||
dst.e2_node_comp_id.type = S1_E2AP_NODE_COMP_INTERFACE_TYPE;
|
||||
|
||||
const char str[] = "S1 NAME";
|
||||
dst.e2_node_comp_id.s1_mme_name = cp_str_to_ba(str);
|
||||
|
||||
// Mandatory
|
||||
// 9.2.27
|
||||
const char req[] = "S1AP Request Message sent";
|
||||
const char res[] = "S1AP Response Message reveived";
|
||||
|
||||
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
|
||||
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
void read_setup_ran(void* data, const ngran_node_t node_type)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
+106
-70
@@ -13,6 +13,8 @@ Please see [NOTICE](NOTICE.md) file for third party software that is included in
|
||||
|
||||
This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent and a nearRT-RIC using O-RAN compliant FlexRIC.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# 1. Installation
|
||||
|
||||
## 1.1 Install prerequisites
|
||||
@@ -21,7 +23,7 @@ This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 a
|
||||
|
||||
On Ubuntu, you might want to use [this PPA](https://apt.kitware.com/) to install an up-to-date version.
|
||||
|
||||
- SWIG (at least v.4.0).
|
||||
- SWIG (at least v.4.1).
|
||||
|
||||
We use 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 or via the code below:
|
||||
@@ -69,17 +71,11 @@ Currently available versions:
|
||||
| E2AP v2.03 | Y | Y |
|
||||
| E2AP v3.01 | Y | Y |
|
||||
|
||||
Please note that KPM SM v2.01 is supported only in FlexRIC, but not in OAI.
|
||||
Please note that KPM SM v2.01 is supported only in FlexRIC, but not in OAI.
|
||||
|
||||
```bash
|
||||
cd cmake_targets/
|
||||
./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja
|
||||
```
|
||||
If the openair2/E2AP/flexric folder is empty, try manually the following commands
|
||||
|
||||
```bash
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
* `-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.
|
||||
@@ -89,16 +85,22 @@ git submodule update
|
||||
* `--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
|
||||
```
|
||||
|
||||
## 2.2 FlexRIC
|
||||
|
||||
- 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.
|
||||
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.
|
||||
|
||||
|
||||
### 2.2.1 Clone the FlexRIC repository
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
|
||||
cd flexric/
|
||||
git checkout 29af8408afad3da36824bd7912562202023ae924
|
||||
git checkout 34d6810f9ab435ac3a4023d5e1917669e24341da
|
||||
```
|
||||
|
||||
### 2.2.2 Build FlexRIC
|
||||
@@ -113,27 +115,47 @@ sudo make install
|
||||
|
||||
By default the service model libraries will be installed in the path `/usr/local/lib/flexric` while the configuration file in `/usr/local/etc/flexric`.
|
||||
|
||||
#### 2.2.3.1 Available Service Models
|
||||
1. KPM v02.03 and KPM v03.00 (`xapp_kpm_moni`)
|
||||
At the moment, the following measurements are supported in OAI RAN:
|
||||
* "DRB.PdcpSduVolumeDL"
|
||||
* "DRB.PdcpSduVolumeUL"
|
||||
* "DRB.RlcSduDelayDl"
|
||||
* "DRB.UEThpDl"
|
||||
* "DRB.UEThpUl"
|
||||
* "RRU.PrbTotDl"
|
||||
* "RRU.PrbTotUl"
|
||||
# 3. Service Models available in OAI RAN
|
||||
|
||||
2. RC v01.03
|
||||
Currently available RC xApps:
|
||||
* `xapp_kpm_rc` - RAN control function "QoS flow mapping configuration" support, i.e. creating a new DRB.
|
||||
* `xapp_rc_moni` - aperiodic subscription support for "UE RRC State Change"
|
||||
## 3.1 O-RAN
|
||||
|
||||
3. MAC + RLC + PDCP + GTP (`xapp_gtp_mac_rlc_pdcp_moni`)
|
||||
We assume that user is familiar with O-RAN WG3 specifications that can be found at https://orandownloadsweb.azurewebsites.net/specifications.
|
||||
|
||||
### 3.1.1 E2SM-KPM
|
||||
|
||||
As mentioned in section [2.1.2 Build OAI with E2 Agent](#212-build-oai-with-e2-agent), we support KPM v2.03/v3.00. Uses ASN.1 encoding.
|
||||
|
||||
Per O-RAN specifications, 5G measurements supported by KPM are specified in 3GPP TS 28.552.
|
||||
|
||||
From 3GPP TS 28.552, we support the following list:
|
||||
* "DRB.PdcpSduVolumeDL"
|
||||
* "DRB.PdcpSduVolumeUL"
|
||||
* "DRB.RlcSduDelayDl"
|
||||
* "DRB.UEThpDl"
|
||||
* "DRB.UEThpUl"
|
||||
* "RRU.PrbTotDl"
|
||||
* "RRU.PrbTotUl"
|
||||
|
||||
From O-RAN.WG3.E2SM-KPM-version specification, we implemented:
|
||||
* REPORT Service Style 4 ("Common condition-based, UE-level" - section 7.4.5) - fetch above measurements per each UE that matches common criteria (e.g. S-NSSAI).
|
||||
|
||||
### 3.1.2 E2SM-RC
|
||||
|
||||
We support RC v1.03. Uses ASN.1 encoding.
|
||||
|
||||
From ORAN.WG3.E2SM-RC-v01.03 specification, we implemented:
|
||||
* REPORT Service Style 4 ("UE Information" - section 7.4.5) - aperiodic subscription for "UE RRC State Change"
|
||||
* CONTROL Service Style 1 ("Radio Bearer Control" - section 7.6.2) - "QoS flow mapping configuration" (e.g creating a new DRB)
|
||||
|
||||
## 3.2 Custom Service Models
|
||||
|
||||
In addition, we support custom Service Models, such are MAC, RLC, PDCP, and GTP. Use plain encoding.
|
||||
|
||||
If you are interested in TC and SLICE SMs, please follow the instructions at https://gitlab.eurecom.fr/mosaic5g/flexric.
|
||||
|
||||
# 3. Start the process
|
||||
# 4. Start the process
|
||||
|
||||
At this point, we assume the 5G Core Network is already running in the background. For more information, please follow the tutorial at https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_OAI_CN5G.md.
|
||||
|
||||
In order to configure E2 agent, please, add the following block in OAI's configuration file:
|
||||
```bash
|
||||
@@ -142,61 +164,75 @@ e2_agent = {
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
}
|
||||
```
|
||||
* start E2 Node agents
|
||||
|
||||
* start the gNB-mono
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --rfsim --sa -E
|
||||
```
|
||||
As per O-RAN.WG3.E2SM-v02.00 specifications, UE ID (section 6.2.2.6) representation in OAI is:
|
||||
| | gNB-mono | CU | CU-CP | CU-UP | DU |
|
||||
|:----------------------|:----------------|:----------------|:----------------|:----------------------|:-------------------|
|
||||
| CHOICE UE ID case | GNB_UE_ID_E2SM | GNB_UE_ID_E2SM | GNB_UE_ID_E2SM | GNB_CU_UP_UE_ID_E2SM | GNB_DU_UE_ID_E2SM |
|
||||
| AMF UE NGAP ID | amf_ue_ngap_id | amf_ue_ngap_id | amf_ue_ngap_id | | |
|
||||
| GUAMI | guami | guami | guami | | |
|
||||
| gNB-CU UE F1AP ID | | rrc_ue_id | | | rrc_ue_id |
|
||||
| gNB-CU-CP UE E1AP ID | | | rrc_ue_id | rrc_ue_id | |
|
||||
| RAN UE ID | rrc_ue_id | rrc_ue_id | rrc_ue_id | rrc_ue_id | rrc_ue_id |
|
||||
|
||||
* if CU/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim --sa -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_conf_file> --sa
|
||||
```
|
||||
* start the gNB-mono
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --rfsim --sa -E
|
||||
```
|
||||
|
||||
* if CU-CP/CU-UP/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim --sa -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_cp_conf_file> --sa
|
||||
sudo ./nr-cuup -O <path_to_cu_up_conf_file> --sa
|
||||
```
|
||||
* if CU/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim --sa -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_conf_file> --sa
|
||||
```
|
||||
|
||||
* if CU-CP/CU-UP/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim --sa -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_cp_conf_file> --sa
|
||||
sudo ./nr-cuup -O <path_to_cu_up_conf_file> --sa
|
||||
```
|
||||
|
||||
* start the nrUE
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
```
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
```
|
||||
|
||||
* start the nearRT-RIC
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/ric/nearRT-RIC
|
||||
```
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/ric/nearRT-RIC
|
||||
```
|
||||
|
||||
* start the KPM monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_kpm_moni
|
||||
```
|
||||
* Start different xApps
|
||||
|
||||
* start the RC monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_rc_moni
|
||||
```
|
||||
* start the KPM monitor xApp - measurements stated in [3.1.1 E2SM-KPM](#311-e2sm-kpm) for each UE that matches S-NSSAI common criteria
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_kpm_moni
|
||||
```
|
||||
Note: we assume that each UE has only 1 DRB; CU-UP does not store the slices, therefore "coarse filtering" is used
|
||||
|
||||
* start the RC control xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
|
||||
```
|
||||
* 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 (MAC + RLC + PDCP + GTP) monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_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
|
||||
```
|
||||
The latency that you observe in your monitor xApp is the latency from the E2 Agent to the nearRT-RIC and xApp.
|
||||
Therefore, FlexRIC is well suited for use cases with ultra low-latency requirements.
|
||||
Additionally, all the data received in the `xapp_gtp_mac_rlc_pdcp_moni` xApp is also written to /tmp/xapp_db in case that offline data processing is wanted (e.g., Machine Learning/Artificial Intelligence applications). You can browse the data using e.g., sqlitebrowser.
|
||||
|
||||
+1
-1
Submodule openair2/E2AP/flexric updated: 7c424e882a...34d6810f9a
Reference in New Issue
Block a user