diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 8c85d49462c5c2e89235fb428880083efe52f5a3..c510a92dfda8fd2d52a0953e0f08206d0688d84f 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -885,6 +885,7 @@ add_library(FLEXRAN_AGENT ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY/flexran_agent_phy.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c + ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP/flexran_agent_pdcp.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index 2a040c8000e9d001d8d0bc586fc30d6168fe39f4..c588753ca8b8fbb42c1c32b3c7ed0163d7bde66f 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -39,6 +39,8 @@ MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_reg MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind) /* handover messages X2AP <-> RRC */ +MESSAGE_DEF(X2AP_SETUP_REQ , MESSAGE_PRIORITY_MED, x2ap_setup_req_t , x2ap_setup_req) +MESSAGE_DEF(X2AP_SETUP_RESP , MESSAGE_PRIORITY_MED, x2ap_setup_resp_t , x2ap_setup_resp) MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req) MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack) MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_handover_cancel_t , x2ap_handover_cancel) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 708430b8b2a740c7f9d848d361333e12831dc789..d284f4d0b9d8b566511c835e3bcc6645d5f5284d 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -29,6 +29,8 @@ // Defines to access message fields. #define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req +#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req +#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp #define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req #define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack #define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf @@ -41,6 +43,16 @@ // eNB application layer -> X2AP messages +typedef struct x2ap_setup_req_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; +} x2ap_setup_req_t; + +typedef struct x2ap_setup_resp_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; +} x2ap_setup_resp_t; + /* X2AP UE CONTEXT RELEASE */ typedef struct x2ap_ue_context_release_s { /* used for X2AP->RRC in source and RRC->X2AP in target */ 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 fc8a9ba337c17599c250ed78621cf821bbfabfc1..6299e101a4c28aad4be0ba60c06bfd71907e6e7f 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file flexran_agent_mac.c +/*! \file flexran_agent_rrc.c * \brief FlexRAN agent Control Module RRC * \author shahab SHARIAT BAGHERI * \date 2017 @@ -130,6 +130,18 @@ int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) { free(msg->ue_state_change_msg->header); if (msg->ue_state_change_msg->config->capabilities) free(msg->ue_state_change_msg->config->capabilities); + if (msg->ue_state_change_msg->config->info) { + if (msg->ue_state_change_msg->config->info->cell_individual_offset) { + free(msg->ue_state_change_msg->config->info->cell_individual_offset); + } + if (msg->ue_state_change_msg->config->info->event) { + if (msg->ue_state_change_msg->config->info->event->a3) { + free(msg->ue_state_change_msg->config->info->event->a3); + } + free(msg->ue_state_change_msg->config->info->event); + } + free(msg->ue_state_change_msg->config->info); + } free(msg->ue_state_change_msg->config); free(msg->ue_state_change_msg); free(msg); @@ -381,7 +393,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, /* Check flag for creation of buffer status report */ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS) { - /*Source Cell*/ + /*Source cell EUTRA Measurements*/ Protocol__FlexRrcMeasurements *rrc_measurements; rrc_measurements = malloc(sizeof(Protocol__FlexRrcMeasurements)); if (rrc_measurements == NULL) @@ -397,7 +409,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id, rnti); rrc_measurements->has_pcell_rsrq = 1 ; - /* Target Cell, Neghibouring*/ + /* Neighbouring cells EUTRA Measurements*/ Protocol__FlexNeighCellsMeasurements *neigh_meas; neigh_meas = malloc(sizeof(Protocol__FlexNeighCellsMeasurements)); if (neigh_meas == NULL) { @@ -406,14 +418,12 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, goto error; } protocol__flex_neigh_cells_measurements__init(neigh_meas); - neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, rnti); Protocol__FlexEutraMeasurements **eutra_meas = NULL; - if (neigh_meas->n_eutra_meas > 0){ - + if (neigh_meas->n_eutra_meas > 0) { eutra_meas = malloc(sizeof(Protocol__FlexEutraMeasurements) * neigh_meas->n_eutra_meas); if (eutra_meas == NULL) { free(neigh_meas); @@ -422,127 +432,138 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, goto error; } - for (int j = 0; j < neigh_meas->n_eutra_meas; j++ ){ - - eutra_meas[j] = malloc(sizeof(Protocol__FlexEutraMeasurements)); - if (eutra_meas[j] == NULL) { - for (int k = 0 ; k < j ; k++) { - free(eutra_meas[k]); - } - free(eutra_meas); - free(neigh_meas); - free(rrc_measurements); - rrc_measurements = NULL; - goto error; - } - - protocol__flex_eutra_measurements__init(eutra_meas[j]); - - eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); - eutra_meas[j]->has_phys_cell_id = 1; - - - /*TODO: Extend for CGI and PLMNID*/ - - Protocol__FlexEutraRefSignalMeas *meas_result; - meas_result = malloc(sizeof(Protocol__FlexEutraRefSignalMeas)); - - protocol__flex_eutra_ref_signal_meas__init(meas_result); - - meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, eutra_meas[j]->phys_cell_id); + for (int j = 0; j < neigh_meas->n_eutra_meas; j++ ) { + eutra_meas[j] = malloc(sizeof(Protocol__FlexEutraMeasurements)); + if (eutra_meas[j] == NULL) { + for (int k = 0 ; k < j ; k++) + free(eutra_meas[k]); + free(eutra_meas); + free(neigh_meas); + free(rrc_measurements); + rrc_measurements = NULL; + goto error; + } + protocol__flex_eutra_measurements__init(eutra_meas[j]); + + /* Fill in the physical cell identifier. */ + eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); + eutra_meas[j]->has_phys_cell_id = 1; + + /* The following is not correctly implemented */ + //if (flexran_get_rrc_neigh_cgi(mod_id, rnti, j)) { + // /* Initialize CGI measurements. */ + // Protocol__FlexEutraCgiMeasurements *cgi_meas; + // cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); + + // if (cgi_meas) { + // protocol__flex_eutra_cgi_measurements__init(cgi_meas); + + // cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); + // cgi_meas->has_tracking_area_code = 1; + + // /* EUTRA Cell Global Identity (CGI) */ + // Protocol__FlexCellGlobalEutraId *cgi; + // cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); + + // if (cgi) { + // protocol__flex_cell_global_eutra_id__init(cgi); + + // cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); + // cgi->has_cell_id = 1; + + // /* PLMN for neighbouring cell */ + // Protocol__FlexPlmnIdentity *plmn_id; + // plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); + + // if (plmn_id) { + // protocol__flex_plmn_identity__init(plmn_id); + + // plmn_id->mcc = 0; + // plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); + + // for (int m = 0; m < plmn_id->n_mcc; m++) { + // plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); + // } + + // plmn_id->mnc = 0; + // plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); + + // for (int m = 0; m < plmn_id->n_mnc; m++) { + // plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); + // } + + // cgi->plmn_id = plmn_id; + // } + // cgi_meas->cgi = cgi; + // } + // eutra_meas[j]->cgi_meas = cgi_meas; + // } + //} + + /*RSRP/RSRQ of the neighbouring cell */ + Protocol__FlexEutraRefSignalMeas *meas_result; + meas_result = malloc(sizeof(Protocol__FlexEutraRefSignalMeas)); + + if (meas_result) { + protocol__flex_eutra_ref_signal_meas__init(meas_result); + + meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, j); meas_result->has_rsrp = 1; - meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, eutra_meas[j]->phys_cell_id); + meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, j); meas_result->has_rsrq = 1; eutra_meas[j]->meas_result = meas_result; - - } + } + } - neigh_meas->eutra_meas = eutra_meas; + neigh_meas->eutra_meas = eutra_meas; - rrc_measurements->neigh_meas = neigh_meas; - + rrc_measurements->neigh_meas = neigh_meas; } else { free(neigh_meas); } - ue_report[i]->rrc_measurements = rrc_measurements; - ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS; - + ue_report[i]->rrc_measurements = rrc_measurements; + ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS; } - - } - + } } - - /* To be considered for RRC signaling of cell*/ - // if (report_config->nr_cc > 0) { - - - // // Fill in the Cell reports - // for (i = 0; i < report_config->nr_cc; i++) { - - - // /* Check flag for creation of noise and interference report */ - // if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) { - // // TODO: Fill in the actual noise and interference report for this cell - // Protocol__FlexNoiseInterferenceReport *ni_report; - // ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport)); - // if(ni_report == NULL) - // goto error; - // protocol__flex_noise_interference_report__init(ni_report); - // // Current frame and subframe number - // ni_report->sfn_sf = flexran_get_sfn_sf(enb_id); - // ni_report->has_sfn_sf = 1; - // //TODO:Received interference power in dbm - // ni_report->rip = 0; - // ni_report->has_rip = 1; - // //TODO:Thermal noise power in dbm - // ni_report->tnp = 0; - // ni_report->has_tnp = 1; - - // ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0); - // ni_report->has_p0_nominal_pucch = 1; - // cell_report[i]->noise_inter_report = ni_report; - // cell_report[i]->flags |= PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE; - // } - // } - - - - - // } - return 0; - error: - - for (int i = 0; i < report_config->nr_ue; i++){ - - if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL){ - for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++){ - - free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); - } - free(ue_report[i]->rrc_measurements->neigh_meas); + for (int i = 0; i < report_config->nr_ue; i++) { + if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL) { + for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { + free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); } + free(ue_report[i]->rrc_measurements->neigh_meas); + } } if (cell_report != NULL) - free(cell_report); + free(cell_report); if (ue_report != NULL) - free(ue_report); - + free(ue_report); return -1; } int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) { for (int i = 0; i < reply->n_ue_report; i++){ - if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas){ - for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++){ - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); + if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas) { + for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { + //if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas) { + // if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi) { + // if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->plmn_id) { + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi->plmn_id); + // } + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi); + // } + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); + //} + if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result) { + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); + } free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); } free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas); @@ -553,6 +574,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) { @@ -651,6 +745,76 @@ void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, ue_conf->has_extended_bsr_size = 1; ue_conf->extended_bsr_size = flexran_get_extended_bsr_size(mod_id, rnti); + + Protocol__FlexMeasurementInfo *meas_info; + meas_info = malloc(sizeof(Protocol__FlexMeasurementInfo)); + + if (meas_info) { + protocol__flex_measurement_info__init(meas_info); + + meas_info->has_offset_freq_serving = 1; + meas_info->offset_freq_serving = flexran_get_rrc_ofp(mod_id, rnti); + + meas_info->has_offset_freq_neighbouring = 1; + meas_info->offset_freq_neighbouring = flexran_get_rrc_ofn(mod_id, rnti); + + int num_adj_cells = flexran_get_rrc_num_adj_cells(mod_id); + meas_info->n_cell_individual_offset = num_adj_cells + 1; + + int64_t *cell_individual_offset; + if (num_adj_cells > 0) { + cell_individual_offset = malloc(sizeof(int64_t)*(num_adj_cells+1)); + if (cell_individual_offset) { + cell_individual_offset[0] = flexran_get_rrc_ocp(mod_id, rnti); + for (int i=0; i < num_adj_cells; i++) { + cell_individual_offset[i+1] = flexran_get_rrc_ocn(mod_id, rnti,i); + } + meas_info->cell_individual_offset = cell_individual_offset; + } + } + else { + cell_individual_offset = malloc(sizeof(int64_t)); + if (cell_individual_offset) { + *cell_individual_offset = flexran_get_rrc_ocp(mod_id, rnti); + meas_info->cell_individual_offset = cell_individual_offset; + } + } + + meas_info->has_filter_coefficient_rsrp = 1; + meas_info->filter_coefficient_rsrp = flexran_get_filter_coeff_rsrp(mod_id, rnti); + + meas_info->has_filter_coefficient_rsrq = 1; + meas_info->filter_coefficient_rsrq = flexran_get_filter_coeff_rsrq(mod_id, rnti); + + Protocol__FlexMeasurementEvent *event; + event = malloc(sizeof(Protocol__FlexMeasurementEvent)); + + if (event) { + protocol__flex_measurement_event__init(event); + Protocol__FlexA3Event *a3_event; + a3_event = malloc(sizeof(Protocol__FlexA3Event)); + if (a3_event) { + protocol__flex_a3_event__init(a3_event); + a3_event->has_a3_offset = 1; + a3_event->a3_offset = flexran_get_rrc_a3_event_a3_offset(mod_id, rnti); + + a3_event->has_report_on_leave = 1; + a3_event->report_on_leave = flexran_get_rrc_a3_event_reportOnLeave(mod_id, rnti); + + a3_event->has_hysteresis = 1; + a3_event->hysteresis = flexran_get_rrc_a3_event_hysteresis(mod_id, rnti); + + a3_event->has_time_to_trigger = 1; + a3_event->time_to_trigger = flexran_get_rrc_a3_event_timeToTrigger(mod_id, rnti); + + a3_event->has_max_report_cells = 1; + a3_event->max_report_cells = flexran_get_rrc_a3_event_maxReportCells(mod_id, rnti); + event->a3 = a3_event; + } + meas_info->event = event; + } + ue_conf->info = meas_info; + } } int flexran_agent_register_rrc_xface(mid_t mod_id) @@ -742,6 +906,9 @@ void flexran_agent_fill_rrc_cell_config(mid_t mod_id, uint8_t cc_id, } else { conf->n_plmn_id = 0; } + + conf->x2_ho_net_control = flexran_get_x2_ho_net_control(mod_id); + conf->has_x2_ho_net_control = 1; } int flexran_agent_unregister_rrc_xface(mid_t mod_id) 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/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..e8bbd13af48f6c28fd95e0fba4ef68bc39601198 --- /dev/null +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c @@ -0,0 +1,147 @@ +/* + * 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 "flexran_agent_rrc_internal.h" +#include "flexran_agent_ran_api.h" + +int update_rrc_reconfig(mid_t mod_id, rnti_t rnti, Protocol__FlexRrcTriggering *trigg) { + + // Measurement info reconfiguration + + if (trigg->meas_info) { + + /* Set serving cell frequency offset */ + if (trigg->meas_info->has_offset_freq_serving) { + if (flexran_set_rrc_ofp(mod_id, rnti, trigg->meas_info->offset_freq_serving) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Serving cell frequency offset\n"); + return -1; + } + } + + /* Set neighbouring cell frequency offset */ + if (trigg->meas_info->has_offset_freq_neighbouring) { + if (flexran_set_rrc_ofn(mod_id, rnti, trigg->meas_info->offset_freq_neighbouring) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell frequency offset\n"); + return -1; + } + } + + if (trigg->meas_info->n_cell_individual_offset > 0) { + /* Set the serving cell offset */ + if (flexran_set_rrc_ocp(mod_id, rnti, trigg->meas_info->cell_individual_offset[0]) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Serving cell offset\n"); + return -1; + } + + /* Set the neighbouring cell offset */ + for (int i=0; i<(trigg->meas_info->n_cell_individual_offset-1); i++) { + if (flexran_set_rrc_ocn(mod_id, rnti, i, trigg->meas_info->cell_individual_offset[i+1]) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell offset\n"); + return -1; + } + } + } + + if (trigg->meas_info->has_offset_freq_neighbouring) { + if (flexran_set_rrc_ofn(mod_id, rnti, trigg->meas_info->offset_freq_neighbouring) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell frequency offset\n"); + return -1; + } + } + + + /* Set rsrp filter coefficient */ + if (trigg->meas_info->has_filter_coefficient_rsrp) { + if (flexran_set_filter_coeff_rsrp(mod_id, rnti, trigg->meas_info->filter_coefficient_rsrp) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set RSRP filter coefficient\n"); + return -1; + } + } + + /* Set rsrq filter coefficient */ + if (trigg->meas_info->has_filter_coefficient_rsrq) { + if (flexran_set_filter_coeff_rsrq(mod_id, rnti, trigg->meas_info->filter_coefficient_rsrq) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set RSRQ filter coefficient\n"); + return -1; + } + } + + if (trigg->meas_info->event) { + + /* Set Periodic event parameters */ + if (trigg->meas_info->event->periodical) { + + /* Set Periodic event maximum number of reported cells */ + if (trigg->meas_info->event->periodical->has_max_report_cells) { + if (flexran_set_rrc_per_event_maxReportCells(mod_id, rnti, trigg->meas_info->event->periodical->max_report_cells) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Periodic event max\n"); + return -1; + } + } + } + + /* Set A3 event parameters */ + if (trigg->meas_info->event->a3) { + + /* Set A3 event a3 offset */ + if (trigg->meas_info->event->a3->has_a3_offset) { + if (flexran_set_rrc_a3_event_a3_offset(mod_id, rnti, trigg->meas_info->event->a3->a3_offset) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event offset\n"); + return -1; + } + } + + /* Set A3 event report on leave */ + if (trigg->meas_info->event->a3->has_report_on_leave) { + if (flexran_set_rrc_a3_event_reportOnLeave(mod_id, rnti, trigg->meas_info->event->a3->report_on_leave) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event report on leave\n"); + return -1; + } + } + + /* Set A3 event hysteresis */ + if (trigg->meas_info->event->a3->has_hysteresis) { + if (flexran_set_rrc_a3_event_hysteresis(mod_id, rnti, trigg->meas_info->event->a3->hysteresis) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event hysteresis\n"); + return -1; + } + } + + /* Set A3 event time to trigger */ + if (trigg->meas_info->event->a3->has_time_to_trigger) { + if (flexran_set_rrc_a3_event_timeToTrigger(mod_id, rnti, trigg->meas_info->event->a3->time_to_trigger) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event time to trigger\n"); + return -1; + } + } + + /* Set A3 event maximum number of reported cells */ + if (trigg->meas_info->event->a3->has_max_report_cells) { + if (flexran_set_rrc_a3_event_maxReportCells(mod_id, rnti, trigg->meas_info->event->a3->max_report_cells) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event max report cells\n"); + return -1; + } + } + } + } + } + return 0; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..3987cb8f3f09c7ffc55a9f21c4bf76f3cc89985a --- /dev/null +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h @@ -0,0 +1,31 @@ +/* + * 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 FLEXRAN_AGENT_RRC_INTERNAL_H_ +#define FLEXRAN_AGENT_RRC_INTERNAL_H_ + +#include "flexran_agent_rrc_internal.h" +#include "flexran_agent_ran_api.h" + +int update_rrc_reconfig(mid_t mod_id, rnti_t rnti, Protocol__FlexRrcTriggering *trigg); + +#endif /*FLEXRAN_AGENT_RRC_INTERNAL_H_*/ + diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index 695d7bcdb1f07378779a674b3d29a3001dfc2544..4958cdb27bfcd96f11baf2a99ee0b401f8aa550a 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -268,3 +268,71 @@ message flex_plmn { optional uint32 mnc = 2; optional uint32 mnc_length = 3; } + +// +// UE-related RRC configuration + +message flex_measurement_info { + // arbitrary offset OFS, from TS + optional int64 offset_freq_serving = 1; + // arbitrary offset OFN + optional int64 offset_freq_neighbouring = 2; + // arbitrary offset OCS + OCN + repeated int64 cell_individual_offset = 3; + // Parameter k for exponential moving average calculation coefficient + // a = 1/2^(k/4) of all measured RSRPs + optional int64 filter_coefficient_rsrp = 4; + // Parameter k for RSRQ filtering + optional int64 filter_coefficient_rsrq = 5; + optional flex_measurement_event event = 6; +} + +message flex_measurement_event { + optional flex_per_event periodical = 1; + optional flex_a1_event a1 = 2; + optional flex_a2_event a2 = 3; + optional flex_a3_event a3 = 4; + optional flex_a4_event a4 = 5; + optional flex_a5_event a5 = 6; +} + +message flex_per_event { + optional int64 max_report_cells = 1; +} + +message flex_a1_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a2_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a3_event { + optional int64 a3_offset = 1; + optional int32 report_on_leave = 2; + optional int64 hysteresis = 3; + optional int64 time_to_trigger = 4; + optional int64 max_report_cells = 5; +} + +message flex_a4_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a5_event { + optional int64 threshold_rsrp_1 = 1; + optional int64 threshold_rsrp_2 = 2; + optional int64 hysteresis = 3; + optional int64 time_to_trigger = 4; + optional int64 max_report_cells = 5; +} diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index dd983aa09c700f82931834b70a003ee091280d77..6d24e5a0ac3a7ed56b28c5179f7abfead69d0eba 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -45,6 +45,7 @@ message flex_cell_config { repeated flex_plmn plmn_id = 40; // The PLMN cell id of this cell optional flex_slice_config slice_config = 42; + optional bool x2_ho_net_control = 43; } message flex_slice_config { @@ -97,6 +98,8 @@ message flex_ue_config { optional uint64 imsi = 30; optional uint32 dl_slice_id = 31; optional uint32 ul_slice_id = 32; + // Configuration about RRC measurements + optional flex_measurement_info info = 33; } message flex_lc_ue_config { diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index b1702f949e4af2204a546975387da8913ca71de0..86f2e9329f685af56e0471d21a85a69131a91991 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -7,7 +7,7 @@ import "time_common.proto"; import "config_messages.proto"; import "controller_commands.proto"; import "control_delegation.proto"; - +import "config_common.proto"; message flexran_message { optional flexran_direction msg_dir = 100; @@ -32,6 +32,7 @@ message flexran_message { flex_rrc_triggering rrc_triggering = 18; flex_ul_mac_config ul_mac_config_msg = 19; flex_disconnect disconnect_msg = 20; + flex_ho_command ho_command_msg = 21; } } @@ -188,7 +189,14 @@ message flex_ul_mac_config { message flex_rrc_triggering { optional flex_header header = 1; - optional string rrc_trigger = 2; + optional string rrc_trigger = 2; + optional flex_measurement_info meas_info = 3; +} + +message flex_ho_command { + optional flex_header header = 1; + optional uint32 rnti = 2; + optional uint32 target_phy_cell_id = 3; } // diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto index c91d2e2c09929f83545fb057e22d570ebdc22e0e..41b2b37f7a6e00ab8bfa24e2df36686b5d8cfa58 100644 --- a/openair2/ENB_APP/MESSAGES/V2/header.proto +++ b/openair2/ENB_APP/MESSAGES/V2/header.proto @@ -34,6 +34,7 @@ enum flex_type { //Controller command messages FLPT_DL_MAC_CONFIG = 13; + FLPT_HO_COMMAND = 21; // UE state change messages FLPT_UE_STATE_CHANGE = 14; 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_common.c b/openair2/ENB_APP/flexran_agent_common.c index 5cbcee370a8cd71a86ff630b8633527ad0b38127..ac18f160697d8b5ba69e971187a2efe181d3369b 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -41,6 +41,7 @@ //#include "PHY/extern.h" #include "common/utils/LOG/log.h" #include "flexran_agent_mac_internal.h" +#include "flexran_agent_rrc_internal.h" //#include "SCHED/defs.h" #include "RRC/LTE/rrc_extern.h" @@ -804,27 +805,91 @@ error: } -int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { - protocol_ctxt_t ctxt; +int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexRrcTriggering *triggering = input->rrc_triggering; - agent_reconf_rrc *reconf_param = malloc(sizeof(agent_reconf_rrc)); - reconf_param->trigger_policy = triggering->rrc_trigger; - reconf_param->report_interval = 0; - reconf_param->report_amount = 0; - struct rrc_eNB_ue_context_s *ue_context_p = NULL; - RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[mod_id]->rrc_ue_head)) { - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); - flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0, reconf_param); + // Set the proper values using FlexRAN API (protected with mutex ?) + if (!flexran_agent_get_rrc_xface(mod_id)) { + LOG_E(FLEXRAN_AGENT, "%s(): no RRC present, aborting\n", __func__); + return -1; + } + + int num_ue = flexran_get_rrc_num_ues(mod_id); + if (num_ue == 0) + return 0; + + rnti_t rntis[num_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); + for (int i = 0; i < num_ue; i++) { + const rnti_t rnti = rntis[i]; + const int error = update_rrc_reconfig(mod_id, rnti, triggering); + if (error < 0) { + LOG_E(FLEXRAN_AGENT, "Error in updating user %d\n", i); + continue; + } + // Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_reconfiguration (mod_id, rnti) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in reconfiguring user %d\n", i); + } + } + + *msg = NULL; + return 0; +} + +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { + Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; + Protocol__FlexHoCommand *ho_command = input->ho_command_msg; + + int rnti_found = 0; + + // Set the proper values using FlexRAN API (protected with mutex ?) + if (!flexran_agent_get_rrc_xface(mod_id)) { + LOG_E(FLEXRAN_AGENT, "%s(): no RRC present, aborting\n", __func__); + return -1; + } + + int num_ue = flexran_get_rrc_num_ues(mod_id); + if (num_ue == 0) + return 0; + + if (!ho_command->has_rnti) { + LOG_E(FLEXRAN_AGENT, "%s(): no UE rnti is present, aborting\n", __func__); + return -1; + } + + if (!ho_command->has_target_phy_cell_id) { + LOG_E(FLEXRAN_AGENT, "%s(): no target physical cell id is present, aborting\n", __func__); + return -1; + } + + rnti_t rntis[num_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); + for (int i = 0; i < num_ue; i++) { + const rnti_t rnti = rntis[i]; + if (ho_command->rnti == rnti) { + rnti_found = 1; + // Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_trigger_handover(mod_id, ho_command->rnti, ho_command->target_phy_cell_id) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in handovering user %d/RNTI %x\n", i, rnti); + } + break; + } } + + if (!rnti_found) + return -1; + *msg = NULL; - free(reconf_param); - reconf_param = NULL; return 0; } +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg) { + // TODO + return 0; +} -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg) { +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg) { // TODO return 0; } @@ -849,6 +914,12 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot // initiate_soft_restart(mod_id, enb_config->cell_config[0]); } + if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->has_x2_ho_net_control) { + if (flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + } + } + *msg = NULL; return 0; } diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index 8419dae62d1a69c7a748d8aaa7aa3999c8fb5434..f116eb6591074c7eba9c05eb1ffe2a98cb98cae0 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -137,9 +137,12 @@ int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__Fl int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); /* rrc triggering measurement message constructor and destructor */ -int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg); +int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); +/* rrc triggering handover command message constructor and destructor */ +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg); /* FlexRAN protocol message dispatcher function */ Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id, diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 6c2e6429eb5ec4f73eaa954f621ef2b3867f2a88..e089675b622257c728ac948775b5c1d515322d22 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -55,7 +55,10 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = { {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/ {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/ {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/ - {flexran_agent_rrc_measurement, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ + {flexran_agent_rrc_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DISCONNECT_MSG*/ + {flexran_agent_rrc_trigger_handover, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HO_COMMAND_MSG*/ }; flexran_agent_message_destruction_callback message_destruction_callback[] = { @@ -508,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 500f4f1f3a146cdab816d697efc9a71da2c5098d..bb81c2c2d2dbec3971ce234b6534c327bd5f2af2 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -71,19 +71,10 @@ sub_frame_t flexran_get_current_subframe(mid_t mod_id) return RC.mac[mod_id]->subframe; } -/* Why uint16_t, frame_t and sub_frame_t are defined as uint32_t? */ -uint16_t flexran_get_sfn_sf(mid_t mod_id) +uint32_t flexran_get_sfn_sf(mid_t mod_id) { if (!mac_is_present(mod_id)) return 0; - frame_t frame = flexran_get_current_system_frame_num(mod_id); - sub_frame_t subframe = flexran_get_current_subframe(mod_id); - uint16_t sfn_sf, frame_mask, sf_mask; - - frame_mask = (1 << 12) - 1; - sf_mask = (1 << 4) - 1; - sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4); - - return sfn_sf; + return flexran_get_current_frame(mod_id) * 10 + flexran_get_current_subframe(mod_id); } uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time) @@ -1434,9 +1425,31 @@ uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid) } /******************** RRC *****************************/ +/* RRC Wrappers */ +int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(ctxt)); + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); + flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0); + return 0; +} -LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) -{ +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id) { + if (!rrc_is_present(mod_id)) return -1; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(ctxt)); + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); + return flexran_rrc_eNB_trigger_handover(mod_id, &ctxt, ue_context_p, target_cell_id); +} + +/* RRC Getters */ + +LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; @@ -1444,97 +1457,687 @@ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) return ue_context_p->ue_context.measResults->measId; } -float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti) -{ +float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; - return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult]; + #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult]; + #else + return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultServCell.rsrpResult]; + #endif } -float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti) -{ +float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; - return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult]; + #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult]; + #else + return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultServCell.rsrqResult]; + #endif } /*Number of neighbouring cells for specific UE*/ -int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) -{ +int flexran_get_rrc_num_ncell(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; if (!ue_context_p->ue_context.measResults) return 0; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count; } -long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) -{ +long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->physCellId; } -float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) -{ +int flexran_get_rrc_neigh_cgi(mid_t mod_id, rnti_t rnti, long cell_id) { + 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; + if (!ue_context_p->ue_context.measResults) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return 0; + return (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info)?0:1; +} + +uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + uint8_t *cId = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.cellIdentity.buf; + return ((cId[0] << 20) + (cId[1] << 12) + (cId[2] << 4) + (cId[3] >> 4)); +} + +uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + uint8_t *tac = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->trackingAreaCode.buf; + return (tac[0] << 8) + (tac[1]); +} + +int flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; +} + +int flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; +} + +uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + int num_mnc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; + return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.array[mnc_id]) * + ((uint32_t) pow(10, num_mnc - mnc_id - 1)); +} + +uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + + int num_mcc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; + return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.array[mcc_id]) * + ((uint32_t) pow(10, num_mcc - mcc_id - 1)); +} + +float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return -1; return RSRP_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult)]; } -float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) -{ +float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return -1; return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)]; } -uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) -{ +/* Measurement offsets */ + +long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->offsetFreq; +} + +long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->offsetFreq; +} + +long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]) { + case LTE_Q_OffsetRange_dB_24: return -24; + case LTE_Q_OffsetRange_dB_22: return -22; + case LTE_Q_OffsetRange_dB_20: return -20; + case LTE_Q_OffsetRange_dB_18: return -18; + case LTE_Q_OffsetRange_dB_16: return -16; + case LTE_Q_OffsetRange_dB_14: return -14; + case LTE_Q_OffsetRange_dB_12: return -12; + case LTE_Q_OffsetRange_dB_10: return -10; + case LTE_Q_OffsetRange_dB_8: return -8; + case LTE_Q_OffsetRange_dB_6: return -6; + case LTE_Q_OffsetRange_dB_5: return -5; + case LTE_Q_OffsetRange_dB_4: return -4; + case LTE_Q_OffsetRange_dB_3: return -3; + case LTE_Q_OffsetRange_dB_2: return -2; + case LTE_Q_OffsetRange_dB_1: return -1; + case LTE_Q_OffsetRange_dB0: return 0; + case LTE_Q_OffsetRange_dB1: return 1; + case LTE_Q_OffsetRange_dB2: return 2; + case LTE_Q_OffsetRange_dB3: return 3; + case LTE_Q_OffsetRange_dB4: return 4; + case LTE_Q_OffsetRange_dB5: return 5; + case LTE_Q_OffsetRange_dB6: return 6; + case LTE_Q_OffsetRange_dB8: return 8; + case LTE_Q_OffsetRange_dB10: return 10; + case LTE_Q_OffsetRange_dB12: return 12; + case LTE_Q_OffsetRange_dB14: return 14; + case LTE_Q_OffsetRange_dB16: return 16; + case LTE_Q_OffsetRange_dB18: return 18; + case LTE_Q_OffsetRange_dB20: return 20; + case LTE_Q_OffsetRange_dB22: return 22; + case LTE_Q_OffsetRange_dB24: return 24; + default: return -99; + } +} + +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]) { + case LTE_Q_OffsetRange_dB_24: return -24; + case LTE_Q_OffsetRange_dB_22: return -22; + case LTE_Q_OffsetRange_dB_20: return -20; + case LTE_Q_OffsetRange_dB_18: return -18; + case LTE_Q_OffsetRange_dB_16: return -16; + case LTE_Q_OffsetRange_dB_14: return -14; + case LTE_Q_OffsetRange_dB_12: return -12; + case LTE_Q_OffsetRange_dB_10: return -10; + case LTE_Q_OffsetRange_dB_8: return -8; + case LTE_Q_OffsetRange_dB_6: return -6; + case LTE_Q_OffsetRange_dB_5: return -5; + case LTE_Q_OffsetRange_dB_4: return -4; + case LTE_Q_OffsetRange_dB_3: return -3; + case LTE_Q_OffsetRange_dB_2: return -2; + case LTE_Q_OffsetRange_dB_1: return -1; + case LTE_Q_OffsetRange_dB0: return 0; + case LTE_Q_OffsetRange_dB1: return 1; + case LTE_Q_OffsetRange_dB2: return 2; + case LTE_Q_OffsetRange_dB3: return 3; + case LTE_Q_OffsetRange_dB4: return 4; + case LTE_Q_OffsetRange_dB5: return 5; + case LTE_Q_OffsetRange_dB6: return 6; + case LTE_Q_OffsetRange_dB8: return 8; + case LTE_Q_OffsetRange_dB10: return 10; + case LTE_Q_OffsetRange_dB12: return 12; + case LTE_Q_OffsetRange_dB14: return 14; + case LTE_Q_OffsetRange_dB16: return 16; + case LTE_Q_OffsetRange_dB18: return 18; + case LTE_Q_OffsetRange_dB20: return 20; + case LTE_Q_OffsetRange_dB22: return 22; + case LTE_Q_OffsetRange_dB24: return 24; + default: return -99; + } +} + +long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRP) { + case LTE_FilterCoefficient_fc0: return 0; + case LTE_FilterCoefficient_fc1: return 1; + case LTE_FilterCoefficient_fc2: return 2; + case LTE_FilterCoefficient_fc3: return 3; + case LTE_FilterCoefficient_fc4: return 4; + case LTE_FilterCoefficient_fc5: return 5; + case LTE_FilterCoefficient_fc6: return 6; + case LTE_FilterCoefficient_fc7: return 7; + case LTE_FilterCoefficient_fc8: return 8; + case LTE_FilterCoefficient_fc9: return 9; + case LTE_FilterCoefficient_fc11: return 11; + case LTE_FilterCoefficient_fc13: return 13; + case LTE_FilterCoefficient_fc15: return 15; + case LTE_FilterCoefficient_fc17: return 17; + case LTE_FilterCoefficient_fc19: return 19; + case LTE_FilterCoefficient_spare1: return -1; /* spare means no coefficient */ + default: return -1; + } +} + +long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ) { + case LTE_FilterCoefficient_fc0: return 0; + case LTE_FilterCoefficient_fc1: return 1; + case LTE_FilterCoefficient_fc2: return 2; + case LTE_FilterCoefficient_fc3: return 3; + case LTE_FilterCoefficient_fc4: return 4; + case LTE_FilterCoefficient_fc5: return 5; + case LTE_FilterCoefficient_fc6: return 6; + case LTE_FilterCoefficient_fc7: return 7; + case LTE_FilterCoefficient_fc8: return 8; + case LTE_FilterCoefficient_fc9: return 9; + case LTE_FilterCoefficient_fc11: return 11; + case LTE_FilterCoefficient_fc13: return 13; + case LTE_FilterCoefficient_fc15: return 15; + case LTE_FilterCoefficient_fc17: return 17; + case LTE_FilterCoefficient_fc19: return 19; + case LTE_FilterCoefficient_spare1: return -1; /* spare means no coefficient */ + default: return -1; + } +} + +/* Periodic event */ + +long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1; + return ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells; +} + +/* A3 event */ + +long flexran_get_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis; +} + +long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + switch (ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger) { + case LTE_TimeToTrigger_ms0: return 0; + case LTE_TimeToTrigger_ms40: return 40; + case LTE_TimeToTrigger_ms64: return 64; + case LTE_TimeToTrigger_ms80: return 80; + case LTE_TimeToTrigger_ms100: return 100; + case LTE_TimeToTrigger_ms128: return 128; + case LTE_TimeToTrigger_ms160: return 160; + case LTE_TimeToTrigger_ms256: return 256; + case LTE_TimeToTrigger_ms320: return 320; + case LTE_TimeToTrigger_ms480: return 480; + case LTE_TimeToTrigger_ms512: return 512; + case LTE_TimeToTrigger_ms640: return 640; + case LTE_TimeToTrigger_ms1024: return 1024; + case LTE_TimeToTrigger_ms1280: return 1280; + case LTE_TimeToTrigger_ms2560: return 2560; + case LTE_TimeToTrigger_ms5120: return 5120; + default: return -1; + } +} + +long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells; +} + +long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset; +} + +int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave; +} + +/* RRC Setters */ + +/* Measurement offsets */ + +int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1; + ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; + return 0; +} + +int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1; + ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; + return 0; +} + +int flexran_set_rrc_ocp(mid_t mod_id, rnti_t rnti, long cellIndividualOffset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]; + switch (cellIndividualOffset) { + case -24: *cio = LTE_Q_OffsetRange_dB_24; break; + case -22: *cio = LTE_Q_OffsetRange_dB_22; break; + case -20: *cio = LTE_Q_OffsetRange_dB_20; break; + case -18: *cio = LTE_Q_OffsetRange_dB_18; break; + case -16: *cio = LTE_Q_OffsetRange_dB_16; break; + case -14: *cio = LTE_Q_OffsetRange_dB_14; break; + case -12: *cio = LTE_Q_OffsetRange_dB_12; break; + case -10: *cio = LTE_Q_OffsetRange_dB_10; break; + case -8: *cio = LTE_Q_OffsetRange_dB_8; break; + case -6: *cio = LTE_Q_OffsetRange_dB_6; break; + case -5: *cio = LTE_Q_OffsetRange_dB_5; break; + case -4: *cio = LTE_Q_OffsetRange_dB_4; break; + case -3: *cio = LTE_Q_OffsetRange_dB_3; break; + case -2: *cio = LTE_Q_OffsetRange_dB_2; break; + case -1: *cio = LTE_Q_OffsetRange_dB_1; break; + case 0: *cio = LTE_Q_OffsetRange_dB0; break; + case 1: *cio = LTE_Q_OffsetRange_dB1; break; + case 2: *cio = LTE_Q_OffsetRange_dB2; break; + case 3: *cio = LTE_Q_OffsetRange_dB3; break; + case 4: *cio = LTE_Q_OffsetRange_dB4; break; + case 5: *cio = LTE_Q_OffsetRange_dB5; break; + case 6: *cio = LTE_Q_OffsetRange_dB6; break; + case 8: *cio = LTE_Q_OffsetRange_dB8; break; + case 10: *cio = LTE_Q_OffsetRange_dB10; break; + case 12: *cio = LTE_Q_OffsetRange_dB12; break; + case 14: *cio = LTE_Q_OffsetRange_dB14; break; + case 16: *cio = LTE_Q_OffsetRange_dB16; break; + case 18: *cio = LTE_Q_OffsetRange_dB18; break; + case 20: *cio = LTE_Q_OffsetRange_dB20; break; + case 22: *cio = LTE_Q_OffsetRange_dB22; break; + case 24: *cio = LTE_Q_OffsetRange_dB24; break; + default: return -1; + } + return 0; +} + +int flexran_set_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id, long cellIndividualOffset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]; + switch (cellIndividualOffset) { + case -24: *cio = LTE_Q_OffsetRange_dB_24; break; + case -22: *cio = LTE_Q_OffsetRange_dB_22; break; + case -20: *cio = LTE_Q_OffsetRange_dB_20; break; + case -18: *cio = LTE_Q_OffsetRange_dB_18; break; + case -16: *cio = LTE_Q_OffsetRange_dB_16; break; + case -14: *cio = LTE_Q_OffsetRange_dB_14; break; + case -12: *cio = LTE_Q_OffsetRange_dB_12; break; + case -10: *cio = LTE_Q_OffsetRange_dB_10; break; + case -8: *cio = LTE_Q_OffsetRange_dB_8; break; + case -6: *cio = LTE_Q_OffsetRange_dB_6; break; + case -5: *cio = LTE_Q_OffsetRange_dB_5; break; + case -4: *cio = LTE_Q_OffsetRange_dB_4; break; + case -3: *cio = LTE_Q_OffsetRange_dB_3; break; + case -2: *cio = LTE_Q_OffsetRange_dB_2; break; + case -1: *cio = LTE_Q_OffsetRange_dB_1; break; + case 0: *cio = LTE_Q_OffsetRange_dB0; break; + case 1: *cio = LTE_Q_OffsetRange_dB1; break; + case 2: *cio = LTE_Q_OffsetRange_dB2; break; + case 3: *cio = LTE_Q_OffsetRange_dB3; break; + case 4: *cio = LTE_Q_OffsetRange_dB4; break; + case 5: *cio = LTE_Q_OffsetRange_dB5; break; + case 6: *cio = LTE_Q_OffsetRange_dB6; break; + case 8: *cio = LTE_Q_OffsetRange_dB8; break; + case 10: *cio = LTE_Q_OffsetRange_dB10; break; + case 12: *cio = LTE_Q_OffsetRange_dB12; break; + case 14: *cio = LTE_Q_OffsetRange_dB14; break; + case 16: *cio = LTE_Q_OffsetRange_dB16; break; + case 18: *cio = LTE_Q_OffsetRange_dB18; break; + case 20: *cio = LTE_Q_OffsetRange_dB20; break; + case 22: *cio = LTE_Q_OffsetRange_dB22; break; + case 24: *cio = LTE_Q_OffsetRange_dB24; break; + default: return -1; + } + return 0; +} + +int flexran_set_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRP) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRP; + switch (filterCoefficientRSRP) { + case 0: *fc = LTE_FilterCoefficient_fc0; break; + case 1: *fc = LTE_FilterCoefficient_fc1; break; + case 2: *fc = LTE_FilterCoefficient_fc2; break; + case 3: *fc = LTE_FilterCoefficient_fc3; break; + case 4: *fc = LTE_FilterCoefficient_fc4; break; + case 5: *fc = LTE_FilterCoefficient_fc5; break; + case 6: *fc = LTE_FilterCoefficient_fc6; break; + case 7: *fc = LTE_FilterCoefficient_fc7; break; + case 8: *fc = LTE_FilterCoefficient_fc8; break; + case 9: *fc = LTE_FilterCoefficient_fc9; break; + case 11: *fc = LTE_FilterCoefficient_fc11; break; + case 13: *fc = LTE_FilterCoefficient_fc13; break; + case 15: *fc = LTE_FilterCoefficient_fc15; break; + case 17: *fc = LTE_FilterCoefficient_fc17; break; + case 19: *fc = LTE_FilterCoefficient_fc19; break; + case -1: *fc = LTE_FilterCoefficient_spare1; break; + default: return -1; + } + return 0; +} + +int flexran_set_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRQ) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ; + switch (filterCoefficientRSRQ) { + case 0: *fc = LTE_FilterCoefficient_fc0; break; + case 1: *fc = LTE_FilterCoefficient_fc1; break; + case 2: *fc = LTE_FilterCoefficient_fc2; break; + case 3: *fc = LTE_FilterCoefficient_fc3; break; + case 4: *fc = LTE_FilterCoefficient_fc4; break; + case 5: *fc = LTE_FilterCoefficient_fc5; break; + case 6: *fc = LTE_FilterCoefficient_fc6; break; + case 7: *fc = LTE_FilterCoefficient_fc7; break; + case 8: *fc = LTE_FilterCoefficient_fc8; break; + case 9: *fc = LTE_FilterCoefficient_fc9; break; + case 11: *fc = LTE_FilterCoefficient_fc11; break; + case 13: *fc = LTE_FilterCoefficient_fc13; break; + case 15: *fc = LTE_FilterCoefficient_fc15; break; + case 17: *fc = LTE_FilterCoefficient_fc17; break; + case 19: *fc = LTE_FilterCoefficient_fc19; break; + case -1: *fc = LTE_FilterCoefficient_spare1; break; + default: return -1; + } + return 0; +} + +/* Periodic event */ + +int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1; + if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1; + ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells = maxReportCells; + return 0; +} + +/* A3 event */ + +int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteresis) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((hysteresis >=0) && (hysteresis <= 30))) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis = hysteresis; + return 0; +} + +int flexran_set_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti, long timeToTrigger) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + LTE_TimeToTrigger_t *ttt = &ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger; + switch (timeToTrigger) { + case 0: *ttt = LTE_TimeToTrigger_ms0; break; + case 40: *ttt = LTE_TimeToTrigger_ms40; break; + case 64: *ttt = LTE_TimeToTrigger_ms64; break; + case 80: *ttt = LTE_TimeToTrigger_ms80; break; + case 100: *ttt = LTE_TimeToTrigger_ms100; break; + case 128: *ttt = LTE_TimeToTrigger_ms128; break; + case 160: *ttt = LTE_TimeToTrigger_ms160; break; + case 256: *ttt = LTE_TimeToTrigger_ms256; break; + case 320: *ttt = LTE_TimeToTrigger_ms320; break; + case 480: *ttt = LTE_TimeToTrigger_ms480; break; + case 512: *ttt = LTE_TimeToTrigger_ms512; break; + case 640: *ttt = LTE_TimeToTrigger_ms640; break; + case 1024: *ttt = LTE_TimeToTrigger_ms1024; break; + case 1280: *ttt = LTE_TimeToTrigger_ms1280; break; + case 2560: *ttt = LTE_TimeToTrigger_ms2560; break; + case 5120: *ttt = LTE_TimeToTrigger_ms5120; break; + default: return -1; + } + return 0; +} + +int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells = maxReportCells; + return 0; +} + +int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((a3_offset >= -30) && (a3_offset <= 30))) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset = a3_offset; + return 0; +} + +int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int reportOnLeave) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((reportOnLeave == 0) || (reportOnLeave == 1))) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave = reportOnLeave; + return 0; +} + +int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control) { + if (!rrc_is_present(mod_id)) return -1; + if (!((x2_ho_net_control == 0) || (x2_ho_net_control == 1))) return -1; + RC.rrc[mod_id]->x2_ho_net_control = x2_ho_net_control; + return 0; +} + +int flexran_get_x2_ho_net_control(mid_t mod_id) { + if (!rrc_is_present(mod_id)) return -1; + return RC.rrc[mod_id]->x2_ho_net_control; +} + +uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.num_plmn; } -uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index) -{ +uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mcc[index]; } -uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index) -{ +uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mnc[index]; } -uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) -{ +uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mnc_digit_length[index]; } +int flexran_get_rrc_num_adj_cells(mid_t mod_id) { + if (!rrc_is_present(mod_id)) return 0; + 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 a60cdeb994cb0f7c0f25af76b01d8b5d8a30178e..f9d0d9740561649577f4795b77280845fe9a7496 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -63,7 +63,7 @@ sub_frame_t flexran_get_current_subframe(mid_t mod_id); /*Return the frame and subframe number in compact 16-bit format. Bits 0-3 subframe, rest for frame. Required by FlexRAN protocol*/ -uint16_t flexran_get_sfn_sf(mid_t mod_id); +uint32_t flexran_get_sfn_sf(mid_t mod_id); /* Return a future frame and subframe number that is ahead_of_time subframes later in compact 16-bit format. Bits 0-3 subframe, @@ -498,6 +498,12 @@ uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid); uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid); /*********************RRC**********************/ +/* Call RRC Reconfiguration wrapper function */ +int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti); + +/* Call RRC to trigger handover wrapper function */ +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id); + /*Get primary cell measuremeant id flexRAN*/ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti); @@ -510,22 +516,107 @@ float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti); /* Get RRC neighbouring measurement */ int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti); -/* Get physical cell id */ +/* Get neighbouring physical cell id */ long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); +/* Get neighbouring cgi */ +int flexran_get_rrc_neigh_cgi(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get neighbouring cgi info cell id */ +uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get neighbouring cgi info tac */ +uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get the number of neighbouring cgi mnc */ +int flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get the number of neighbouring cgi mcc */ +int flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get neighbouring cgi mnc */ +uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id); + +/* Get neighbouring cgi mcc */ +uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id); + /* Get RSRP of neighbouring Cell */ float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id); /* Get RSRQ of neighbouring Cell */ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id); -/*Get MCC PLMN identity neighbouring Cell*/ -/* currently not implemented -int flexran_get_rrc_neigh_plmn_mcc(mid_t mod_id, rnti_t rnti, int cell_id); */ +/* Get ofp offset */ +long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti); + +/* Get ofn offset */ +long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti); + +/* Get ocp offset */ +long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti); + +/* Get ocn offset */ +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get Periodic Event max reported cells */ +long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event hysteresis */ +long flexran_get_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event time to trigger */ +long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event max reported cells */ +long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event a3 offset */ +long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event report on leave */ +int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti); + +/* Get filter coefficient for rsrp */ +long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti); -/*Get MNC PLMN identity neighbouring Cell*/ -/* currently not implemented -int flexran_get_rrc_neigh_plmn_mnc(mid_t mod_id, mid_t ue_id, int cell_id); */ +/* Get filter coefficient for rsrq */ +long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti); + +/* Set ofp offset */ +int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq); + +/* Set ofn offset */ +int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq); + +/* Set ocp offset */ +int flexran_set_rrc_ocp(mid_t mod_id, rnti_t rnti, long cellIndividualOffset); + +/* Set ocn offset */ +int flexran_set_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id, long cellIndividualOffset); + +/* Set Periodic Event max reported cells */ +int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells); + +/* Set A3 Event hysteresis */ +int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteresis); + +/* Set A3 Event time to trigger */ +int flexran_set_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti, long timeToTrigger); + +/* Set A3 Event max reported cells */ +int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells); + +/* Set A3 Event a3 offset */ +int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset); + +/* Set A3 Event report on leave */ +int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int reportOnLeave); + +/* Set filter coefficient for rsrp */ +int flexran_set_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRP); + +/* Set filter coefficient for rsrq */ +int flexran_set_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRQ); /* Get number of PLMNs that is broadcasted in SIB1 */ uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id); @@ -539,6 +630,27 @@ uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index); /* Get index'th MNC's digit length broadcasted in SIB1 */ uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index); +/* Get X2 handover controlled by network */ +int flexran_get_x2_ho_net_control(mid_t mod_id); + +/* Set X2 handover controlled by network */ +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 */ diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 2f3f6799355b6f69e024c3338a5395b0dccdb2e4..ef0598a40a78de8ccc5c9bb99462493238738cfd 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -61,6 +61,8 @@ #define MAX_PAYLOAD 1024 /* maximum payload size*/ +#define MAX_NUM_NEIGH_CELLs 6 /* maximum neighbouring cells number */ + #define UE_STATE_NOTIFICATION_INTERVAL 50 #define IPV4_ADDR "%u.%u.%u.%u" @@ -477,6 +479,73 @@ typedef struct HANDOVER_INFO_s { int x2_id; /* X2AP UE ID in the target eNB */ } HANDOVER_INFO; +typedef struct PER_EVENT_s { + long maxReportCells; +} PER_EVENT_t; + +typedef struct A1_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A1_EVENT_t; + +typedef struct A2_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A2_EVENT_t; + +typedef struct A3_EVENT_s { + long a3_offset; + int reportOnLeave; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A3_EVENT_t; + + +typedef struct A4_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A4_EVENT_t; + +typedef struct A5_EVENT_s { + long threshold_RSRP_1; + long threshold_RSRP_2; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A5_EVENT_t; + +typedef struct EVENTS_s { + PER_EVENT_t *per_event; + + A1_EVENT_t *a1_event; + + A2_EVENT_t *a2_event; + + A3_EVENT_t *a3_event; + + A4_EVENT_t *a4_event; + + A5_EVENT_t *a5_event; +} EVENTS_t; + +typedef struct MEASUREMENT_INFO_s { + //TODO: Extend to multiple meas objects for OFP/OFN offsets + long offsetFreq; + //TODO: extend to multiple carriers for OCP/OCN offsets + long cellIndividualOffset[MAX_NUM_NEIGH_CELLs+1]; + long filterCoefficientRSRP; + long filterCoefficientRSRQ; + EVENTS_t *events; +} MEASUREMENT_INFO; + + #define RRC_HEADER_SIZE_MAX 64 #define RRC_BUFFER_SIZE_MAX 1024 typedef struct { @@ -559,6 +628,7 @@ typedef struct eNB_RRC_UE_s { SRB_INFO_TABLE_ENTRY Srb2; LTE_MeasConfig_t *measConfig; HANDOVER_INFO *handover_info; + MEASUREMENT_INFO *measurement_info; LTE_MeasResults_t *measResults; LTE_MobilityControlInfo_t *mobilityInfo; @@ -756,6 +826,14 @@ typedef struct eNB_RRC_INST_s { /// NR cell id uint64_t nr_cellid; + // X2 handover controlled by network + int x2_ho_net_control; + + // Neighborouring cells id + int num_neigh_cells; + int num_neigh_cells_cc[MAX_NUM_CCs]; + uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + // other RAN parameters int srb1_timer_poll_retransmit; int srb1_poll_pdu; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b7ca81f6dde7a285821766fa755575779bdf3baa..e75353ac9e28e2063c7d51a7c4c67b97ea5575ca 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -977,6 +977,20 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.handover_info = NULL; } + if (ue_context_pP->ue_context.measurement_info) { + /* TODO: be sure free is enough here (check memory leaks) */ + if (ue_context_pP->ue_context.measurement_info->events) { + if (ue_context_pP->ue_context.measurement_info->events->a3_event) { + free(ue_context_pP->ue_context.measurement_info->events->a3_event); + ue_context_pP->ue_context.measurement_info->events->a3_event = NULL; + } + free(ue_context_pP->ue_context.measurement_info->events); + ue_context_pP->ue_context.measurement_info->events = NULL; + } + free(ue_context_pP->ue_context.measurement_info); + ue_context_pP->ue_context.measurement_info = NULL; + } + //SRB_INFO SI; //SRB_INFO Srb0; //SRB_INFO_TABLE_ENTRY Srb1; @@ -2924,8 +2938,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t LTE_RSRP_Range_t *rsrp = NULL; struct LTE_MeasConfig__speedStatePars *Sparams = NULL; LTE_QuantityConfig_t *quantityConfig = NULL; - struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList - *dedicatedInfoNASList = NULL; + LTE_CellsToAddMod_t *CellToAdd = NULL; + LTE_CellsToAddModList_t *CellsToAddModList = NULL; + struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* For no gcc warnings */ @@ -3288,20 +3303,38 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - // MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - // (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - // CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; - // - // // Add adjacent cell lists (6 per eNB) - // for (i = 0; i < 6; i++) { - // CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - // CellToAdd->cellIndex = i + 1; - // CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); - // CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; - // ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); - // } + + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + } + + if (!ue_context_pP->ue_context.measurement_info) { + ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); + } + + //TODO: Assign proper values + ue_context_pP->ue_context.measurement_info->offsetFreq = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = LTE_Q_OffsetRange_dB0; + + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { + CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1] = CellToAdd->cellIndividualOffset; + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + + if (!ue_context_pP->ue_context.measurement_info->events) { + ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); + } + // Report Configurations for periodical, A1-A5 events ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); @@ -3416,6 +3449,18 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + /* A3 event update */ + if (!ue_context_pP->ue_context.measurement_info->events->a3_event) { + ue_context_pP->ue_context.measurement_info->events->a3_event = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events->a3_event))); + } + + ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset; + ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.reportOnLeave; + ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis; + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger; + ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells; + rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); *rsrp = 20; Sparams = CALLOC(1, sizeof(*Sparams)); @@ -3440,6 +3485,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ; + /* Initialize NAS list */ dedicatedInfoNASList = CALLOC(1, sizeof(struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); @@ -3569,16 +3617,15 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t void flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, - const uint8_t ho_state, - agent_reconf_rrc *trig_param - ) + const uint8_t ho_state) //----------------------------------------------------------------------------- { - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; - int i; - // configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE - eNB_RRC_INST *rrc_inst = RC.rrc[ctxt_pP->module_id]; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int i; + + /* Configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE */ + eNB_RRC_INST *rrc_inst = RC.rrc[ctxt_pP->module_id]; struct LTE_PhysicalConfigDedicated **physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated; struct LTE_SRB_ToAddMod *SRB2_config = NULL; struct LTE_SRB_ToAddMod__rlc_Config *SRB2_rlc_config = NULL; @@ -3586,7 +3633,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt struct LTE_LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters = NULL; LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - LTE_SRB_ToAddModList_t **SRB_configList2 = NULL; + LTE_SRB_ToAddModList_t **SRB_configList2 = NULL; struct LTE_DRB_ToAddMod *DRB_config = NULL; struct LTE_RLC_Config *DRB_rlc_config = NULL; struct LTE_PDCP_Config *DRB_pdcp_config = NULL; @@ -3596,22 +3643,24 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL; LTE_DRB_ToAddModList_t **DRB_configList = &ue_context_pP->ue_context.DRB_configList; - LTE_DRB_ToAddModList_t **DRB_configList2 = NULL; + LTE_DRB_ToAddModList_t **DRB_configList2 = NULL; LTE_MAC_MainConfig_t *mac_MainConfig = NULL; LTE_MeasObjectToAddModList_t *MeasObj_list = NULL; LTE_MeasObjectToAddMod_t *MeasObj = NULL; LTE_ReportConfigToAddModList_t *ReportConfig_list = NULL; - LTE_ReportConfigToAddMod_t *ReportConfig_per;//, *ReportConfig_A1, - // *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; + LTE_ReportConfigToAddMod_t *ReportConfig_per, *ReportConfig_A1, + *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; LTE_MeasIdToAddModList_t *MeasId_list = NULL; - LTE_MeasIdToAddMod_t *MeasId0; //, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - long *sr_ProhibitTimer_r9 = NULL; - // uint8_t sCellIndexToAdd = rrc_find_free_SCell_index(enb_mod_idP, ue_mod_idP, 1); - //uint8_t sCellIndexToAdd = 0; + LTE_MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; + +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + long *sr_ProhibitTimer_r9 = NULL; #endif - long *logicalchannelgroup, *logicalchannelgroup_drb; - long *maxHARQ_Tx, *periodicBSR_Timer; + + long *logicalchannelgroup = NULL; + long *logicalchannelgroup_drb = NULL; + long *maxHARQ_Tx = NULL; + long *periodicBSR_Timer = NULL; LTE_RSRP_Range_t *rsrp = NULL; struct LTE_MeasConfig__speedStatePars *Sparams = NULL; LTE_QuantityConfig_t *quantityConfig = NULL; @@ -3619,13 +3668,16 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt LTE_CellsToAddModList_t *CellsToAddModList = NULL; struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; - /* for no gcc warnings */ - (void)dedicatedInfoNas; + + /* For no gcc warnings */ + (void) dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; int measurements_enabled; uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, -#ifdef CBA - //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; + uint8_t cc_id = ue_context_pP->ue_context.primaryCC_id; + LTE_UE_EUTRA_Capability_t *UEcap = ue_context_pP->ue_context.UE_Capability; + +#ifdef CBA // Contention Based Access uint8_t *cba_RNTI_buf; cba_RNTI = CALLOC(1, sizeof(LTE_C_RNTI_t)); cba_RNTI_buf = CALLOC(1, 2 * sizeof(uint8_t)); @@ -3633,27 +3685,33 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt cba_RNTI->size = 2; cba_RNTI->bits_unused = 0; - // associate UEs to the CBa groups as a function of their UE id + /* Associate UEs to the CBA groups as a function of their UE id */ if (rrc_inst->num_active_cba_groups) { cba_RNTI->buf[0] = rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups] & 0xff; cba_RNTI->buf[1] = 0xff; - LOG_D(RRC, - "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n", - enb_mod_idP, frameP, + LOG_D(RRC, "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n", + enb_mod_idP, + frameP, rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups], ue_mod_idP % rrc_inst->num_active_cba_groups, ue_mod_idP); } else { cba_RNTI->buf[0] = 0x0; cba_RNTI->buf[1] = 0x0; - LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", enb_mod_idP, frameP, ue_mod_idP); + LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", + enb_mod_idP, + frameP, + ue_mod_idP); } - #endif - T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), - T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); - // Configure SRB2 - /// SRB2 - SRB_configList2=&ue_context_pP->ue_context.SRB_configList2[xid]; + + T(T_ENB_RRC_CONNECTION_RECONFIGURATION, + T_INT(ctxt_pP->module_id), + T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), + T_INT(ctxt_pP->rnti)); + + /* Configure SRB2 */ + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[xid]); if (*SRB_configList2) { free(*SRB_configList2); @@ -3678,22 +3736,19 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt SRB2_lchan_config->present = LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue; SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters)); SRB2_ul_SpecificParameters->priority = 3; // let some priority for SRB1 and dedicated DRBs - SRB2_ul_SpecificParameters->prioritisedBitRate = - LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - SRB2_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - // LCG for CCCH and DCCH is 0 as defined in 36331 + SRB2_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + SRB2_ul_SpecificParameters->bucketSizeDuration = LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + + /* LCG for CCCH and DCCH is 0 as defined in 36331 */ logicalchannelgroup = CALLOC(1, sizeof(long)); *logicalchannelgroup = 0; SRB2_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB2_ul_SpecificParameters; - // this list has the configuration for SRB1 and SRB2 - ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); - // this list has only the configuration for SRB2 - ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); - // Configure DRB - //*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); // this list has the configuration for SRB1 and SRB2 + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); // this list has only the configuration for SRB2 + + /* Configure DRB */ // list for all the configured DRB if (*DRB_configList) { free(*DRB_configList); @@ -3701,8 +3756,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); memset(*DRB_configList, 0, sizeof(**DRB_configList)); - // list for the configured DRB for a this xid - DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; + + DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; // list for the configured DRB for a this xid if (*DRB_configList2) { free(*DRB_configList2); @@ -3710,17 +3765,17 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - /// DRB + DRB_config = CALLOC(1, sizeof(*DRB_config)); DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); *(DRB_config->eps_BearerIdentity) = 5L; // LW set to first value, allowed value 5..15, value : x+4 - // DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; //allowed values 1..32 // NN: this is the 1st DRB for this ue, so set it to 1 DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; // (ue_mod_idP+1); //allowed values 1..32, value: x DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); *(DRB_config->logicalChannelIdentity) = (long)3; // value : x+2 DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); DRB_config->rlc_Config = DRB_rlc_config; + #ifdef RRC_DEFAULT_RAB_IS_AM DRB_rlc_config->present = LTE_RLC_Config_PR_am; DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = LTE_T_PollRetransmit_ms50; @@ -3733,21 +3788,25 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; + #ifdef CBA - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms5;//T_Reordering_ms25; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms5; //T_Reordering_ms25; #else DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; #endif + #endif + DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); DRB_config->pdcp_Config = DRB_pdcp_config; DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long)); *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity; DRB_pdcp_config->rlc_AM = NULL; DRB_pdcp_config->rlc_UM = NULL; - /* avoid gcc warnings */ + /* Avoid gcc warnings */ (void)PDCP_rlc_AM; (void)PDCP_rlc_UM; + #ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; @@ -3757,52 +3816,111 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; #endif + DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); DRB_config->logicalChannelConfig = DRB_lchan_config; DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - DRB_ul_SpecificParameters->priority = 12; // lower priority than srb1, srb2 and other dedicated bearer - DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ; - //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + DRB_ul_SpecificParameters->priority = 12; // lower priority than srb1, srb2 and other dedicated bearer + DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; // LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + DRB_ul_SpecificParameters->bucketSizeDuration = LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM) logicalchannelgroup_drb = CALLOC(1, sizeof(long)); *logicalchannelgroup_drb = 1; DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); - //ue_context_pP->ue_context.DRB_configList2[0] = &(*DRB_configList); + + /* MAC Main Config */ + // The different parts of MAC main config are set below mac_MainConfig = CALLOC(1, sizeof(*mac_MainConfig)); - // ue_context_pP->ue_context.mac_MainConfig = LTE_MAC_MainConfig; mac_MainConfig->ul_SCH_Config = CALLOC(1, sizeof(*mac_MainConfig->ul_SCH_Config)); maxHARQ_Tx = CALLOC(1, sizeof(long)); *maxHARQ_Tx = LTE_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; + + /* BSR reconfiguration */ periodicBSR_Timer = CALLOC(1, sizeof(long)); - *periodicBSR_Timer = LTE_PeriodicBSR_Timer_r12_sf64; + *periodicBSR_Timer = LTE_PeriodicBSR_Timer_r12_sf64; //LTE_PeriodicBSR_Timer_r12_infinity; // LTE_PeriodicBSR_Timer_r12_sf64; // LTE_PeriodicBSR_Timer_r12_sf20 mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; - mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; + mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; // LTE_RetxBSR_Timer_r12_sf320; // LTE_RetxBSR_Timer_r12_sf5120 mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE mac_MainConfig->timeAlignmentTimerDedicated = LTE_TimeAlignmentTimer_infinity; - mac_MainConfig->drx_Config = NULL; + + /* PHR reconfiguration */ mac_MainConfig->phr_Config = CALLOC(1, sizeof(*mac_MainConfig->phr_Config)); mac_MainConfig->phr_Config->present = LTE_MAC_MainConfig__phr_Config_PR_setup; - mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; // Value dB1 =1 dB, dB3 = 3 dB -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf500; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_infinity + mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf200; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf1000 + mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3; // Value dB1 =1 dB, dB3 = 3 dB + + if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { + /* CDRX Configuration */ + // Need to check if UE is a BR UE + rnti_t rnti = ue_context_pP->ue_id_rnti; + module_id_t module_id = ctxt_pP->module_id; + int UE_id = find_UE_id(module_id, rnti); + eNB_MAC_INST *mac = RC.mac[module_id]; + UE_list_t *UE_list = &(mac->UE_list); + + if (UE_id != -1) { + if ((rrc_inst->carrier[cc_id].sib1->tdd_Config == NULL) && + (UE_list->UE_template[ue_context_pP->ue_context.primaryCC_id][UE_id].rach_resource_type == 0)) { + // CDRX can be only configured in case of FDD and non BR UE (09/04/19) + + LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n"); + + /* Process the IE drx_Config */ + if (cc_id < MAX_NUM_CCs) { + mac_MainConfig->drx_Config = do_DrxConfig(module_id, cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE + } else { + LOG_E(RRC, "Invalid CC_id for DRX configuration\n"); + } + + /* Set timers and thresholds values in local MAC context of UE */ + eNB_Config_Local_DRX(module_id, ue_context_pP->ue_id_rnti, mac_MainConfig->drx_Config); + + LOG_D(RRC, "DRX configured in mac main config for RRC Connection Reconfiguration\n"); + + } else { // CDRX not implemented for TDD and LTE-M (09/04/19) + mac_MainConfig->drx_Config = NULL; + } + } else { // UE_id invalid + LOG_E(RRC, "Invalid UE_id found!\n"); + mac_MainConfig->drx_Config = NULL; + } + } else { // No CDRX with the CU/DU split in this version + LOG_E(RRC, "CU/DU split activated\n"); + mac_MainConfig->drx_Config = NULL; + } + +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long)); - *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR + *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2 = 2*SR mac_MainConfig->ext1 = CALLOC(1, sizeof(struct LTE_MAC_MainConfig__ext1)); mac_MainConfig->ext1->sr_ProhibitTimer_r9 = sr_ProhibitTimer_r9; - //sps_RA_ConfigList_rlola = NULL; #endif - //change the transmission mode for the primary component carrier - //TODO: add codebook subset restriction here - //TODO: change TM for secondary CC in SCelltoaddmodlist + // free the old LTE_MAC_MainConfig_t: get a pointer to "old" memory, assign + // the new values in the ue_context, then free it + // Note: can not completely avoid race condition with FlexRAN + LTE_MAC_MainConfig_t *old_mac_MainConfig = ue_context_pP->ue_context.mac_MainConfig; + ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig; + free(old_mac_MainConfig->ul_SCH_Config->periodicBSR_Timer); + free(old_mac_MainConfig->ul_SCH_Config->maxHARQ_Tx); + free(old_mac_MainConfig->ul_SCH_Config); + free(old_mac_MainConfig->phr_Config); +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + free(old_mac_MainConfig->ext1->sr_ProhibitTimer_r9); + free(old_mac_MainConfig->ext1); +#endif + free(old_mac_MainConfig); + + // change the transmission mode for the primary component carrier + // TODO: add codebook subset restriction here + // TODO: change TM for secondary CC in SCelltoaddmodlist if (*physicalConfigDedicated) { if ((*physicalConfigDedicated)->antennaInfo) { (*physicalConfigDedicated)->antennaInfo->choice.explicitValue.transmissionMode = rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode; @@ -3849,19 +3967,20 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt LOG_E(RRC,"antenna_info not present in physical_config_dedicated. Not reconfiguring!\n"); } - /* CSI Configuration through RRC */ + /* CSI RRC Reconfiguration */ if ((*physicalConfigDedicated)->cqi_ReportConfig != NULL) { if ((rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm4) || (rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm5) || (rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm6)) { - //feedback mode needs to be set as well - //TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable - LOG_I(RRC, "Setting cqi aperiodic reporting mode to rm31 (hardcoded)\n"); + + // feedback mode needs to be set as well + // TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable + LOG_I(RRC, "Setting cqi reporting mode to rm31 (hardcoded)\n"); #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=LTE_CQI_ReportModeAperiodic_rm31; + *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic) = LTE_CQI_ReportModeAperiodic_rm31; // HLC CQI, single PMI #else - *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=LTE_CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, no PMI + *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic) = LTE_CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, single PMI #endif } } else { @@ -3879,9 +3998,33 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt MeasId0->measObjectId = 1; MeasId0->reportConfigId = 1; ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId0); - /* - * Add one EUTRA Measurement Object - */ + MeasId1 = CALLOC(1, sizeof(*MeasId1)); + MeasId1->measId = 2; + MeasId1->measObjectId = 1; + MeasId1->reportConfigId = 2; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId1); + MeasId2 = CALLOC(1, sizeof(*MeasId2)); + MeasId2->measId = 3; + MeasId2->measObjectId = 1; + MeasId2->reportConfigId = 3; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId2); + MeasId3 = CALLOC(1, sizeof(*MeasId3)); + MeasId3->measId = 4; + MeasId3->measObjectId = 1; + MeasId3->reportConfigId = 4; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId3); + MeasId4 = CALLOC(1, sizeof(*MeasId4)); + MeasId4->measId = 5; + MeasId4->measObjectId = 1; + MeasId4->reportConfigId = 5; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId4); + MeasId5 = CALLOC(1, sizeof(*MeasId5)); + MeasId5->measId = 6; + MeasId5->measObjectId = 1; + MeasId5->reportConfigId = 6; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; + // Add one EUTRA Measurement Object MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); // Configure MeasObject @@ -3889,64 +4032,162 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt memset((void *)MeasObj, 0, sizeof(*MeasObj)); MeasObj->measObjectId = 1; MeasObj->measObject.present = LTE_MeasObjectToAddMod__measObject_PR_measObjectEUTRA; - MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 3350; //band 7, 2.68GHz - //MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 36090; //band 33, 1.909GHz + MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = + to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0], + RC.rrc[ctxt_pP->module_id]->configuration.downlink_frequency[0], + RC.rrc[ctxt_pP->module_id]->configuration.N_RB_DL[0]); MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = LTE_AllowedMeasBandwidth_mbw25; MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t)); MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; - MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = (LTE_Q_OffsetRange_t *) CALLOC(1,sizeof(LTE_Q_OffsetRange_t)); + *(MeasObj->measObject.choice.measObjectEUTRA.offsetFreq) = ue_context_pP->ue_context.measurement_info->offsetFreq; // Default is 15 or 0dB - // Add adjacent cell lists (6 per eNB) - for (i = 0; i < 6; i++) { + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + } + + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); CellToAdd->cellIndex = i + 1; - CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); - CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1]; ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); } - ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; // Report Configurations for periodical, A1-A5 events + ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); + ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); + ReportConfig_A1 = CALLOC(1, sizeof(*ReportConfig_A1)); + ReportConfig_A2 = CALLOC(1, sizeof(*ReportConfig_A2)); + ReportConfig_A3 = CALLOC(1, sizeof(*ReportConfig_A3)); + ReportConfig_A4 = CALLOC(1, sizeof(*ReportConfig_A4)); + ReportConfig_A5 = CALLOC(1, sizeof(*ReportConfig_A5)); + ReportConfig_per->reportConfigId = 1; + ReportConfig_per->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_periodical; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose = + LTE_ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per); + ReportConfig_A1->reportConfigId = 2; + ReportConfig_A1->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1); + //if (ho_state == 1 /*HO_MEASURMENT */ ) { + LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, and A5 event reporting\n", + ctxt_pP->module_id, ctxt_pP->frame); + ReportConfig_A2->reportConfigId = 3; + ReportConfig_A2->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A2); + ReportConfig_A3->reportConfigId = 4; + ReportConfig_A3->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset;//10; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA3.reportOnLeave = ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells = ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger = + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3); + ReportConfig_A4->reportConfigId = 5; + ReportConfig_A4->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A4); + ReportConfig_A5->reportConfigId = 6; + ReportConfig_A5->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.choice.threshold_RSRP = 10; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.choice.threshold_RSRP = 10; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; - /* RRC Strategy Measurement */ - - if (strcmp("one_shot", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 0; - trig_param->report_amount = 0; - } else if (strcmp("event_driven", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 6; - trig_param->report_amount = 2; - } else if (strcmp("periodical", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 1; - trig_param->report_amount = 7; - } else { - LOG_E(FLEXRAN_AGENT, "There is something wrong on RRC agent!"); - } - - ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); - ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); - // Periodical Measurement Report - ReportConfig_per->reportConfigId = 1; - ReportConfig_per->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present = - LTE_ReportConfigEUTRA__triggerType_PR_periodical; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose = - LTE_ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells; - // ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger = TimeToTrigger_ms40; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = trig_param->report_interval ;//ReportInterval_ms2048; // RRC counter frame- ms1024 is 1ms - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = trig_param->report_amount; //ReportConfigEUTRA__reportAmount_r2; // put r1 to see once, r2 for 2 times and ... - ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per); + rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); + *rsrp = 20; + Sparams = CALLOC(1, sizeof(*Sparams)); + Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; + Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; + Sparams->choice.setup.timeToTrigger_SF.sf_Medium = LTE_SpeedStateScaleFactors__sf_High_oDot5; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeHigh = 10; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeMedium = 5; + Sparams->choice.setup.mobilityStateParameters.t_Evaluation = LTE_MobilityStateParameters__t_Evaluation_s60; + Sparams->choice.setup.mobilityStateParameters.t_HystNormal = LTE_MobilityStateParameters__t_HystNormal_s120; quantityConfig = CALLOC(1, sizeof(*quantityConfig)); memset((void *)quantityConfig, 0, sizeof(*quantityConfig)); quantityConfig->quantityConfigEUTRA = CALLOC(1, sizeof(struct LTE_QuantityConfigEUTRA)); @@ -3958,8 +4199,9 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP))); quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ))); - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP; + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ; + /* Initialize NAS list */ dedicatedInfoNASList = CALLOC(1, sizeof(struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); @@ -3975,12 +4217,13 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt } /* TODO parameters yet to process ... */ - // { - // ue_context_pP->ue_context.e_rab[i].param.qos; - // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; - // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; - // } - /* TODO should test if e RAB are Ok before! */ + { + // ue_context_pP->ue_context.e_rab[i].param.qos; + // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + } + + /* TODO should test if e RAB are OK before! */ ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_STATUS_DONE"); @@ -3996,38 +4239,35 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]->configuration.enable_measurement_reports; memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCConnectionReconfiguration(ctxt_pP, buffer, - xid, //Transaction_id, - (LTE_SRB_ToAddModList_t *)NULL, // SRB_configList - (LTE_DRB_ToAddModList_t *)NULL, - (LTE_DRB_ToReleaseList_t *)NULL, // DRB2_list, - (struct LTE_SPS_Config *)NULL, // *sps_Config, - (struct LTE_PhysicalConfigDedicated *)*physicalConfigDedicated, - // #ifdef EXMIMO_IOT - // NULL, NULL, NULL,NULL, - // #else - measurements_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, - measurements_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, - measurements_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, - measurements_enabled ? (LTE_MeasIdToAddModList_t *)MeasId_list : NULL, - // #endif - (LTE_MAC_MainConfig_t *)mac_MainConfig, - (LTE_MeasGapConfig_t *)NULL, - (LTE_MobilityControlInfo_t *)NULL, - (LTE_SecurityConfigHO_t *)NULL, - (struct LTE_MeasConfig__speedStatePars *)Sparams, - (LTE_RSRP_Range_t *)rsrp, - (LTE_C_RNTI_t *)cba_RNTI, - (struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *)dedicatedInfoNASList, - (LTE_SL_CommConfig_r12_t *)NULL, - (LTE_SL_DiscConfig_r12_t *)NULL + xid, // Transaction_id, + (LTE_SRB_ToAddModList_t *) *SRB_configList2, // SRB_configList + (LTE_DRB_ToAddModList_t *) *DRB_configList, + (LTE_DRB_ToReleaseList_t *) NULL, // DRB2_list, + (struct LTE_SPS_Config *) NULL, // *sps_Config, + (struct LTE_PhysicalConfigDedicated *) *physicalConfigDedicated, + measurements_enabled ? (LTE_MeasObjectToAddModList_t *) MeasObj_list : NULL, + measurements_enabled ? (LTE_ReportConfigToAddModList_t *) ReportConfig_list : NULL, + measurements_enabled ? (LTE_QuantityConfig_t *) quantityConfig : NULL, + measurements_enabled ? (LTE_MeasIdToAddModList_t *) MeasId_list : NULL, + (LTE_MAC_MainConfig_t *) mac_MainConfig, + (LTE_MeasGapConfig_t *) NULL, + (LTE_MobilityControlInfo_t *) NULL, + (LTE_SecurityConfigHO_t *) NULL, + (struct LTE_MeasConfig__speedStatePars *) Sparams, + (LTE_RSRP_Range_t *) rsrp, + (LTE_C_RNTI_t *) cba_RNTI, + (struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *) dedicatedInfoNASList, + (LTE_SL_CommConfig_r12_t *) NULL, + (LTE_SL_DiscConfig_r12_t *) NULL #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - , (LTE_SCellToAddMod_r10_t *)NULL + , (LTE_SCellToAddMod_r10_t *) NULL #endif ); - LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size, - "[MSG] RRC Connection Reconfiguration\n"); + + LOG_DUMPMSG(RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Connection Reconfiguration\n"); /* Free all NAS PDUs */ for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { @@ -4038,30 +4278,38 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt } } - LOG_I(RRC, - "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", - ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); - LOG_D(RRC, - "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", - ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); - MSC_LOG_TX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - buffer, - size, - MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_pP->ue_context.rnti, - rrc_eNB_mui, - size); - rrc_data_req( - ctxt_pP, - DCCH, - rrc_eNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + LOG_I(RRC, "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_context_pP->ue_context.rnti); + + LOG_D(RRC, "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, + ctxt_pP->module_id, + size, + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + ctxt_pP->module_id, + DCCH); + + MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req(ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); free(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ); quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = NULL; @@ -4074,18 +4322,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt free(quantityConfig); quantityConfig = NULL; - - free(mac_MainConfig->ul_SCH_Config); - mac_MainConfig->ul_SCH_Config = NULL; - - free(mac_MainConfig->phr_Config); - mac_MainConfig->phr_Config = NULL; - - free(mac_MainConfig); - mac_MainConfig = NULL; } - //----------------------------------------------------------------------------- int rrc_eNB_generate_RRCConnectionReconfiguration_SCell( @@ -4282,6 +4520,9 @@ rrc_eNB_process_MeasurementReport( if (!RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]->configuration.enable_x2) return; + if (RC.rrc[ctxt_pP->module_id]->x2_ho_net_control) + return; + LOG_D(RRC, "A3 event is triggered...\n"); /* if the UE is not in handover mode, start handover procedure */ @@ -4355,6 +4596,42 @@ rrc_eNB_generate_HandoverPreparationInformation( *_size = ho_size; } +void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m) { + if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { + LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_neigh_cells++; + RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + for (int i=0; i<m->num_cc; i++) { + RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; + } +} + +void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m) { + if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { + LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_neigh_cells++; + RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + for (int i=0; i<m->num_cc; i++) { + RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; + } +} + void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m) { struct rrc_eNB_ue_context_s *ue_context_target_p = NULL; /* TODO: get proper UE rnti */ @@ -4540,6 +4817,100 @@ void rrc_eNB_handover_cancel( S1AP_CAUSE_RADIO_NETWORK, s1_cause); } + +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id) { + + uint32_t earfcn_dl; + uint8_t KeNB_star[32] = { 0 }; + int cell_found = 0; + + /* if X2AP is disabled, do nothing */ + if (!is_x2ap_enabled()) { + LOG_E(RRC, "X2 is disabled\n"); + return -1; + } + + /* Check if eNB id belongs to the supported ones-Extend for multiple carrieres */ + for (int i=0; i < RC.rrc[mod_id]->num_neigh_cells; i++) { + if (RC.rrc[mod_id]->neigh_cells_id[i][0] == target_cell_id) { + cell_found = 1; + break; + } + } + + /* Check if eNB id was found */ + if (!cell_found) { + LOG_E(RRC, "%s(): cannot find target eNB with phyCellId %d\n", __func__, target_cell_id); + return -1; + } + + /* Handover process is following */ + LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); + + /* if the UE is not in handover mode, start handover procedure */ + if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { + MessageDef *msg; + LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); + /* Check memory leakage for handover info */ + //if (ue_context_pP->ue_context.handover_info) { + //free(ue_context_pP->ue_context.handover_info); + //} + ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); + ue_context_pP->ue_context.Status = RRC_HO_EXECUTION; + ue_context_pP->ue_context.handover_info->state = HO_REQUEST; + /* HO Preparation message */ + msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ); + rrc_eNB_generate_HandoverPreparationInformation( + ue_context_pP, + X2AP_HANDOVER_REQ(msg).rrc_buffer, + &X2AP_HANDOVER_REQ(msg).rrc_buffer_size); + X2AP_HANDOVER_REQ(msg).rnti = ctxt_pP->rnti; + X2AP_HANDOVER_REQ(msg).target_physCellId = target_cell_id; + X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id; + // Don't know how to get this ID? + X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id; + X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities; + // compute keNB* + earfcn_dl = (uint32_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, + RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL); + derive_keNB_star(ue_context_pP->ue_context.kenb, X2AP_HANDOVER_REQ(msg).target_physCellId, earfcn_dl, true, KeNB_star); + memcpy(X2AP_HANDOVER_REQ(msg).kenb, KeNB_star, 32); + X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc; + //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr; + X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs; + + for (int i=0; i<ue_context_pP->ue_context.setup_e_rabs; i++) { + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr = ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid = ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = ue_context_pP->ue_context.e_rab[i].param.qos.qci; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability; + } + + /* TODO: don't do that, X2AP should find the target by itself */ + //X2AP_HANDOVER_REQ(msg).target_mod_id = 0; + LOG_I(RRC, + "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n", + ctxt_pP->module_id, ctxt_pP->frame); + itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg); + } else { + LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame, + ctxt_pP->rnti); + } + + return 0; +} + void check_handovers( protocol_ctxt_t *const ctxt_pP @@ -4662,8 +5033,8 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct LTE_QuantityConfig_t *quantityConfig = NULL; LTE_MobilityControlInfo_t *mobilityInfo = NULL; LTE_SecurityConfigHO_t *securityConfigHO = NULL; - //CellsToAddMod_t *CellToAdd = NULL; - //CellsToAddModList_t *CellsToAddModList = NULL; + LTE_CellsToAddMod_t *CellToAdd = NULL; + LTE_CellsToAddModList_t *CellsToAddModList = NULL; struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* for no gcc warnings */ @@ -5254,7 +5625,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct MeasId5->measObjectId = 1; MeasId5->reportConfigId = 6; ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); - // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; // Add one EUTRA Measurement Object MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); @@ -5274,19 +5645,38 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - //MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - //(CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - //CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; - // Add adjacent cell lists (6 per eNB) - //for (i = 0; i < 6; i++) { - //CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - //CellToAdd->cellIndex = 1;//i + 1; - //CellToAdd->physCellId = 1;//get_adjacent_cell_id(ctxt_pP->module_id, i); - //CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0; - //ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); - //} + + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + } + + if (!ue_context_pP->ue_context.measurement_info) { + ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); + } + + //TODO: Assign proper values + ue_context_pP->ue_context.measurement_info->offsetFreq = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = LTE_Q_OffsetRange_dB0; + + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { + CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1] = CellToAdd->cellIndividualOffset; + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); - // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + + if (!ue_context_pP->ue_context.measurement_info->events) { + ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); + } + // Report Configurations for periodical, A1-A5 events ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); @@ -5401,6 +5791,18 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + /* A3 event update */ + if (!ue_context_pP->ue_context.measurement_info->events->a3_event) { + ue_context_pP->ue_context.measurement_info->events->a3_event = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events->a3_event))); + } + + ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset; + ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.reportOnLeave; + ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis; + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger; + ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells; + rsrp = CALLOC(1, sizeof(RSRP_Range_t)); *rsrp = 20; Sparams = CALLOC(1, sizeof(*Sparams)); @@ -5424,6 +5826,10 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ))); *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ; + /* mobilityinfo */ mobilityInfo = ue_context_pP->ue_context.mobilityInfo; @@ -7077,6 +7483,7 @@ rrc_eNB_decode_dcch( LTE_RRCConnectionReconfigurationComplete__criticalExtensions_PR_rrcConnectionReconfigurationComplete_r8) { /*NN: revise the condition */ /*FK: left the condition as is for the case MME is used (S1 mode) but setting dedicated_DRB = 1 otherwise (noS1 mode) so that no second RRCReconfiguration message activationg more DRB is sent as this causes problems with the nasmesh driver.*/ + int flexran_agent_handover = 0; if (EPC_MODE_ENABLED) { if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) { dedicated_DRB = 1; @@ -7113,6 +7520,8 @@ rrc_eNB_decode_dcch( break; } + flexran_agent_handover = 1; + RC.rrc[ctxt_pP->module_id]->Nb_ue++; dedicated_DRB = 3; RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; ue_context_p->ue_context.Status = RRC_RECONFIGURED; @@ -7145,7 +7554,7 @@ rrc_eNB_decode_dcch( if (flexran_agent_get_rrc_xface(ctxt_pP->module_id)) { flexran_agent_get_rrc_xface(ctxt_pP->module_id)->flexran_agent_notify_ue_state_change(ctxt_pP->module_id, ue_context_p->ue_id_rnti, - PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED); + flexran_agent_handover?PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED:PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED); } } @@ -8223,6 +8632,14 @@ void *rrc_enb_process_itti_msg(void *notUsed) { rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance); break; + case X2AP_SETUP_REQ: + rrc_eNB_process_x2_setup_request(instance, &X2AP_SETUP_REQ(msg_p)); + break; + + case X2AP_SETUP_RESP: + rrc_eNB_process_x2_setup_response(instance, &X2AP_SETUP_RESP(msg_p)); + break; + case X2AP_HANDOVER_REQ: LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s\n", instance, msg_name_p); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 34439753d8f5ab796267940e159a62ca04beee75..e7e5e71d8093f4d05bb14ddb1a64dd702f8024d5 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -306,8 +306,7 @@ void flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration( const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, - const uint8_t ho_state, - agent_reconf_rrc *trig_param + const uint8_t ho_state ); void rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP, @@ -357,6 +356,9 @@ void *rrc_enb_task(void *args_p); \param void *args_p Pointer on arguments to start the task. */ void *rrc_ue_task(void *args_p); +void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m); + +void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m); void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m); @@ -610,6 +612,12 @@ rrc_eNB_generate_HandoverPreparationInformation( //LTE_PhysCellId_t targetPhyId ); +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id); + void check_handovers( protocol_ctxt_t *const ctxt_pP diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index ad1cac04793e9a2cc28bfab9abdac6de37b98a96..2a44501a337a3008d7940aed17ba974d03774bcd 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -291,6 +291,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; uint32_t eNB_id = 0; DevAssert (pdu != NULL); @@ -391,17 +392,25 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); return -1; } + + msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_REQ); + + X2AP_SETUP_REQ(msg).num_cc = ie->value.choice.ServedCells.list.count; + if (ie->value.choice.ServedCells.list.count > 0) { x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count; for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) { servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI; + X2AP_SETUP_REQ(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; } } instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); } @@ -418,6 +427,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; uint32_t eNB_id = 0; DevAssert (pdu != NULL); @@ -500,11 +510,16 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_RESP); + + X2AP_SETUP_RESP(msg).num_cc = ie->value.choice.ServedCells.list.count; + if (ie->value.choice.ServedCells.list.count > 0) { x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count; for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) { servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI; + X2AP_SETUP_RESP(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; } } @@ -521,6 +536,8 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, instance_p->x2_target_enb_associated_nb ++; x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return 0; }