diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 7e6d83f74882d437d5bf6db37d48437b4edf23ed..1feafd99541dad3cdd8a05b2df3058ebabf35d3e 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -573,6 +573,79 @@ int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) return 0; } +int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id, + const report_config_t *report_config, + Protocol__FlexUeStatsReport **ue_report, + Protocol__FlexCellStatsReport **cell_report) { + /* This function fills the GTP part of the statistics. The necessary + * information is, for our purposes, completely maintained in the RRC layer. + * It would be possible to add a GTP module that handles this, though. */ + if (report_config->nr_ue > 0) { + rnti_t rntis[report_config->nr_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, report_config->nr_ue); + for (int i = 0; i < report_config->nr_ue; i++) { + const rnti_t rnti = rntis[i]; + + /* Check flag for creation of buffer status report */ + if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS) { + + /* get number of rabs for this UE */ + const int num_e_rab = flexran_agent_rrc_gtp_num_e_rab(mod_id, rnti); + Protocol__FlexGtpStats **gtp_stats = NULL; + if (num_e_rab > 0) { + gtp_stats = calloc(num_e_rab, sizeof(Protocol__FlexGtpStats *)); + if (!gtp_stats) goto error; + for (int r = 0; r < num_e_rab; ++r) { + gtp_stats[r] = malloc(sizeof(Protocol__FlexGtpStats)); + if (!gtp_stats[r]) goto error; + protocol__flex_gtp_stats__init(gtp_stats[r]); + gtp_stats[r]->e_rab_id = flexran_agent_rrc_gtp_get_e_rab_id(mod_id, rnti, r); + gtp_stats[r]->has_e_rab_id = 1; + gtp_stats[r]->teid_enb = flexran_agent_rrc_gtp_get_teid_enb(mod_id, rnti, r); + gtp_stats[r]->has_teid_enb = 1; + gtp_stats[r]->addr_enb = NULL; + gtp_stats[r]->teid_sgw = flexran_agent_rrc_gtp_get_teid_sgw(mod_id, rnti, r); + gtp_stats[r]->has_teid_sgw = 1; + gtp_stats[r]->addr_sgw = NULL; + } + } + ue_report[i]->n_gtp_stats = num_e_rab; + ue_report[i]->gtp_stats = gtp_stats; + ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS; + } + } + } + return 0; +error: + for (int i = 0; i < report_config->nr_ue; i++) { + if (!ue_report[i]->gtp_stats) continue; + for (int r = 0; r < ue_report[i]->n_gtp_stats; ++r) { + if (ue_report[i]->gtp_stats[r]) { + free(ue_report[i]->gtp_stats[r]); + ue_report[i]->gtp_stats[r] = NULL; + } + } + free(ue_report[i]->gtp_stats); + ue_report[i]->gtp_stats = NULL; + } + return -1; +} + +int flexran_agent_rrc_gtp_destroy_stats_reply(Protocol__FlexStatsReply *reply) { + for (int i = 0; i < reply->n_ue_report; ++i) { + if (!reply->ue_report[i]->n_gtp_stats == 0) continue; + + for (int r = 0; r < reply->ue_report[i]->n_gtp_stats; ++r) { + //if (reply->ue_report[i]->gtp_stats[r]->addr_enb) + // free(reply->ue_report[i]->gtp_stats[r]->addr_enb); + //if (reply->ue_report[i]->gtp_stats[r]->addr_sgw) + // free(reply->ue_report[i]->gtp_stats[r]->addr_sgw); + free(reply->ue_report[i]->gtp_stats[r]); + } + } + return 0; +} + void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, Protocol__FlexUeConfig *ue_conf) { diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h index 4b9cec861427871ec0c4973f03062564c78e081a..fdf00ff84175ae4c3e2ccede40985be679f37ef4 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h @@ -60,6 +60,11 @@ void flexran_trigger_rrc_measurements (mid_t mod_id, LTE_MeasResults_t *); int flexran_agent_rrc_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report); int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply); +/* Statistic reply for GTP statistics which OAI stores also in the RRC layer. + * This might be moved to a separate GTP module in the future */ +int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report); +int flexran_agent_rrc_gtp_destroy_stats_reply(Protocol__FlexStatsReply *reply); + /* Fill the RRC part of a ue_config message */ void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, Protocol__FlexUeConfig *ue_conf); diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto index ee286981f52f89bf4fe979d1b165fb220b7efa4e..b56ad8eea1c01832ca61ce1e771c08ba4d4fe2cd 100644 --- a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto @@ -305,3 +305,15 @@ message flex_mac_sdus_dl { optional uint32 sdu_length = 1; optional uint32 lcid = 2; } + +// +// GTP stats +// + +message flex_gtp_stats { + optional uint32 e_rab_id = 1; + optional uint32 teid_enb = 2; + optional string addr_enb = 3; + optional uint32 teid_sgw = 4; + optional string addr_sgw = 5; +} diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto index 8eb6510de3ca0c78a3a90bdec955616a29924875..7cceb04a01cf61f020ca55f2b1b7de09d9e6a5dd 100644 --- a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto @@ -50,6 +50,7 @@ message flex_ue_stats_report { optional flex_rrc_measurements rrc_measurements = 10; optional flex_pdcp_stats pdcp_stats = 11; optional flex_mac_stats mac_stats = 12; + repeated flex_gtp_stats gtp_stats = 13; } // @@ -89,6 +90,7 @@ enum flex_ue_stats_type { FLUST_MAC_STATS = 128; FLUST_PDCP_STATS = 1024; + FLUST_GTP_STATS = 2048; FLUST_RRC_MEASUREMENTS = 65536; // To be extended with more types of stats diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 65663e20a8ae1fcbe1f0e01ebe7fd9331f4e2eab..e089675b622257c728ac948775b5c1d515322d22 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -511,7 +511,13 @@ int flexran_agent_stats_reply(mid_t enb_id, xid_t xid, const report_config_t *re goto error; } - + /* GTP reply split, currently performed through RRC module */ + if (flexran_agent_get_rrc_xface(enb_id) + && flexran_agent_rrc_gtp_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) { + err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD; + goto error; + } + stats_reply_msg->cell_report = cell_report; stats_reply_msg->ue_report = ue_report; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 1465f468548aeabc5b26aa7bc8c1336be6a5a310..9f08623aa8333d51cd2e1d732eeb4bfd13bb8fa2 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -2119,6 +2119,34 @@ int flexran_get_rrc_num_adj_cells(mid_t mod_id) { return RC.rrc[mod_id]->num_neigh_cells; } +int flexran_agent_rrc_gtp_num_e_rab(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.setup_e_rabs; +} + +int flexran_agent_rrc_gtp_get_e_rab_id(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.e_rab[index].param.e_rab_id; +} + +int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.enb_gtp_teid[index]; +} + +int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.e_rab[index].param.gtp_teid; +} + /**************************** SLICING ****************************/ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 7dd6b69b6182a5b73933340c5c171cf75da87ee3..e18c55c4bfd24bff610582e8e2867c056ba44a3a 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -638,6 +638,19 @@ int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control); /* Get number of adjacent cells via X2 interface */ int flexran_get_rrc_num_adj_cells(mid_t mod_id); + +/* Get the number of E-RABs for UE */ +int flexran_agent_rrc_gtp_num_e_rab(mid_t mod_id, rnti_t rnti); + +/* Get the e-RAB ID for UE */ +int flexran_agent_rrc_gtp_get_e_rab_id(mid_t mod_id, rnti_t rnti, int index); + +/* Get the TEID at the eNB for UE */ +int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index); + +/* Get the TEID at the SGW for UE */ +int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); + /************************** Slice configuration **************************/ /* Get the DL slice ID for a UE */