/* * 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 */ /*! \file flexran_agent_mac.c * \brief FlexRAN agent message handler for MAC layer * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein * \date 2016 * \version 0.1 */ #include "flexran_agent_mac.h" #include "flexran_agent_extern.h" #include "flexran_agent_common.h" #include "flexran_agent_mac_internal.h" #include "flexran_agent_net_comm.h" #include "flexran_agent_timer.h" #include "flexran_agent_ran_api.h" #include "LAYER2/MAC/mac_proto.h" #include "liblfds700.h" #include "common/utils/LOG/log.h" #include <dlfcn.h> /*Array containing the Agent-MAC interfaces*/ AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; /* Ringbuffer related structs used for maintaining the dl mac config messages */ //message_queue_t *dl_mac_config_queue; struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; /* Ringbuffer-related to slice configuration */ struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; /* Ringbuffer related to slice configuration if we need to wait for additional * controller information */ struct lfds700_ringbuffer_element *store_slice_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state store_slice_config_ringbuffer_state[NUM_MAX_ENB]; /* stores the (increasing) xid for messages to prevent double use */ int xid = 50; /* Ringbuffer-related to slice configuration */ struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; /* a list of shared objects that are loaded into the user plane */ SLIST_HEAD(flexran_so_handle, flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB]; int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, uint32_t ue_flags) { const int cc_id = 0; // TODO: make for multiple CCs for (int i = 0; i < n_ue; i++) { const rnti_t rnti = ue_report[i]->rnti; const int UE_id = flexran_get_mac_ue_id_rnti(mod_id, rnti); /* buffer status report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) { ue_report[i]->n_bsr = 4; //TODO should be automated uint32_t *elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr); if (elem == NULL) goto error; for (int j = 0; j < ue_report[i]->n_bsr; j++) { elem[j] = flexran_get_ue_bsr_ul_buffer_info (mod_id, i, j); } ue_report[i]->bsr = elem; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR; } /* power headroom report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PHR) { ue_report[i]->phr = flexran_get_ue_phr (mod_id, UE_id); ue_report[i]->has_phr = 1; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PHR; } /* Check flag for creation of RLC buffer status report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) { ue_report[i]->n_rlc_report = 3; // Set this to the number of LCs for this UE. This needs to be generalized for for LCs Protocol__FlexRlcBsr ** rlc_reports; rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr *) * ue_report[i]->n_rlc_report); if (rlc_reports == NULL) goto error; for (int j = 0; j < ue_report[i]->n_rlc_report; j++) { rlc_reports[j] = malloc(sizeof(Protocol__FlexRlcBsr)); if (rlc_reports[j] == NULL) { for (int k = 0; k < j; k++) { free(rlc_reports[k]); } free(rlc_reports); goto error; } protocol__flex_rlc_bsr__init(rlc_reports[j]); rlc_reports[j]->lc_id = j+1; rlc_reports[j]->has_lc_id = 1; rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(mod_id, UE_id, j + 1); rlc_reports[j]->has_tx_queue_size = 1; rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(mod_id, UE_id, j + 1); rlc_reports[j]->has_tx_queue_hol_delay = 1; //TODO:Set retransmission queue size in bytes rlc_reports[j]->retransmission_queue_size = 10; rlc_reports[j]->has_retransmission_queue_size = 0; //TODO:Set retransmission queue head of line delay in ms rlc_reports[j]->retransmission_queue_hol_delay = 100; rlc_reports[j]->has_retransmission_queue_hol_delay = 0; rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(mod_id, UE_id, j + 1); rlc_reports[j]->has_status_pdu_size = 1; } if (ue_report[i]->n_rlc_report > 0) ue_report[i]->rlc_report = rlc_reports; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS; } /* MAC CE buffer status report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) { // TODO: Fill in the actual MAC CE buffer status report ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(mod_id, UE_id, 0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15; // Use as bitmap. Set one or more of the; // PROTOCOL__FLEX_CE_TYPE__FLPCET_ values // found in stats_common.pb-c.h. See // flex_ce_type in FlexRAN specification ue_report[i]->has_pending_mac_ces = 1; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS; } /* DL CQI report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) { // TODO: Fill in the actual DL CQI report for the UE based on its configuration Protocol__FlexDlCqiReport * dl_report; dl_report = malloc(sizeof(Protocol__FlexDlCqiReport)); if (dl_report == NULL) goto error; protocol__flex_dl_cqi_report__init(dl_report); dl_report->sfn_sn = flexran_get_sfn_sf(mod_id); dl_report->has_sfn_sn = 1; dl_report->n_csi_report = flexran_get_active_CC(mod_id, UE_id); dl_report->n_csi_report = 1 ; //Create the actual CSI reports. Protocol__FlexDlCsi **csi_reports; csi_reports = malloc(sizeof(Protocol__FlexDlCsi *)*dl_report->n_csi_report); if (csi_reports == NULL) { free(dl_report); goto error; } for (int j = 0; j < dl_report->n_csi_report; j++) { csi_reports[j] = malloc(sizeof(Protocol__FlexDlCsi)); if (csi_reports[j] == NULL) { for (int k = 0; k < j; k++) { free(csi_reports[k]); } free(csi_reports); csi_reports = NULL; goto error; } protocol__flex_dl_csi__init(csi_reports[j]); csi_reports[j]->serv_cell_index = j; csi_reports[j]->has_serv_cell_index = 1; csi_reports[j]->ri = flexran_get_current_RI(mod_id, UE_id, j); csi_reports[j]->has_ri = 1; //TODO: the type of CSI report based on the configuration of the UE //For now we only support type P10, which only needs a wideband value csi_reports[j]->type = PROTOCOL__FLEX_CSI_TYPE__FLCSIT_P10; csi_reports[j]->has_type = 1; csi_reports[j]->report_case = PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI; if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI) { Protocol__FlexCsiP10 *csi10; csi10 = malloc(sizeof(Protocol__FlexCsiP10)); if (csi10 == NULL) { for (int k = 0; k <= j; k++) { free(csi_reports[k]); } free(csi_reports); csi_reports = NULL; goto error; } protocol__flex_csi_p10__init(csi10); csi10->wb_cqi = flexran_get_ue_wcqi(mod_id, UE_id); csi10->has_wb_cqi = 1; csi_reports[j]->p10csi = csi10; } /* else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI) { Protocol__FlexCsiP11 *csi11; csi11 = malloc(sizeof(Protocol__FlexCsiP11)); if (csi11 == NULL) { for (int k = 0; k <= j; k++) { free(csi_reports[k]); } free(csi_reports); csi_reports = NULL; goto error; } protocol__flex_csi_p11__init(csi11); csi11->wb_cqi = malloc(sizeof(csi11->wb_cqi)); csi11->n_wb_cqi = 1; csi11->wb_cqi[0] = flexran_get_ue_wcqi (mod_id, UE_id); // According To spec 36.213 if (flexran_get_antenna_ports(mod_id, j) == 2 && csi_reports[j]->ri == 1) { // TODO PMI csi11->wb_pmi = flexran_get_ue_wpmi(mod_id, UE_id, 0); csi11->has_wb_pmi = 1; } else if (flexran_get_antenna_ports(mod_id, j) == 2 && csi_reports[j]->ri == 2) { // TODO PMI csi11->wb_pmi = flexran_get_ue_wpmi(mod_id, UE_id, 0); csi11->has_wb_pmi = 1; } else if (flexran_get_antenna_ports(mod_id, j) == 4 && csi_reports[j]->ri == 2) { // TODO PMI csi11->wb_pmi = flexran_get_ue_wpmi(mod_id, UE_id, 0); csi11->has_wb_pmi = 1; } csi11->has_wb_pmi = 0; csi_reports[j]->p11csi = csi11; } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI) { Protocol__FlexCsiP20 *csi20; csi20 = malloc(sizeof(Protocol__FlexCsiP20)); if (csi20 == NULL) { for (int k = 0; k <= j; k++) { free(csi_reports[k]); } free(csi_reports); csi_reports = NULL; goto error; } protocol__flex_csi_p20__init(csi20); csi20->wb_cqi = flexran_get_ue_wcqi (mod_id, UE_id); csi20->has_wb_cqi = 1; csi20->bandwidth_part_index = 1 ; //TODO csi20->has_bandwidth_part_index = 0; csi20->sb_index = 1; //TODO csi20->has_sb_index = 1; csi_reports[j]->p20csi = csi20; } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI) { // Protocol__FlexCsiP21 *csi21; // csi21 = malloc(sizeof(Protocol__FlexCsiP21)); // if (csi21 == NULL) // goto error; // protocol__flex_csi_p21__init(csi21); // csi21->wb_cqi = flexran_get_ue_wcqi (mod_id, UE_id); // csi21->wb_pmi = flexran_get_ue_pmi(mod_id); //TDO inside // csi21->has_wb_pmi = 1; // csi21->sb_cqi = 1; // TODO // csi21->bandwidth_part_index = 1 ; //TDO inside // csi21->has_bandwidth_part_index = 1 ; // csi21->sb_index = 1 ;//TODO // csi21->has_sb_index = 1 ; // csi_reports[j]->p20csi = csi21; } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI) { // Protocol__FlexCsiA12 *csi12; // csi12 = malloc(sizeof(Protocol__FlexCsiA12)); // if (csi12 == NULL) // goto error; // protocol__flex_csi_a12__init(csi12); // csi12->wb_cqi = flexran_get_ue_wcqi (mod_id, UE_id); // csi12->sb_pmi = 1 ; //TODO inside // TODO continou } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI) { // Protocol__FlexCsiA22 *csi22; // csi22 = malloc(sizeof(Protocol__FlexCsiA22)); // if (csi22 == NULL) // goto error; // protocol__flex_csi_a22__init(csi22); // csi22->wb_cqi = flexran_get_ue_wcqi (mod_id, UE_id); // csi22->sb_cqi = 1 ; //TODO inside // csi22->wb_pmi = flexran_get_ue_wcqi (mod_id, UE_id); // csi22->has_wb_pmi = 1; // csi22->sb_pmi = 1 ; //TODO inside // csi22->has_wb_pmi = 1; // csi22->sb_list = flexran_get_ue_wcqi (mod_id, UE_id); } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI) { // Protocol__FlexCsiA20 *csi20; // csi20 = malloc(sizeof(Protocol__FlexCsiA20)); // if (csi20 == NULL) // goto error; // protocol__flex_csi_a20__init(csi20); // csi20->wb_cqi = flexran_get_ue_wcqi (mod_id, UE_id); // csi20->has_wb_cqi = 1; // csi20>sb_cqi = 1 ; //TODO inside // csi20>has_sb_cqi = 1 ; // csi20->sb_list = 1; // TODO inside } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI) { } else if (csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI) { } */ } dl_report->csi_report = csi_reports; ue_report[i]->dl_cqi_report = dl_report; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI; } /* paging buffer status report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) { //TODO: Fill in the actual paging buffer status report. For this field to be valid, the RNTI //set in the report must be a P-RNTI Protocol__FlexPagingBufferReport *paging_report; paging_report = malloc(sizeof(Protocol__FlexPagingBufferReport)); if (paging_report == NULL) goto error; protocol__flex_paging_buffer_report__init(paging_report); paging_report->n_paging_info = 1; Protocol__FlexPagingInfo **p_info; p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * paging_report->n_paging_info); if (p_info == NULL) { free(paging_report); goto error; } for (int j = 0; j < paging_report->n_paging_info; j++) { p_info[j] = malloc(sizeof(Protocol__FlexPagingInfo)); if (p_info[j] == NULL) { for (int k = 0; k < j; k++) { free(p_info[k]); } free(p_info); p_info = NULL; free(paging_report); goto error; } protocol__flex_paging_info__init(p_info[j]); //TODO: Set paging index. This index is the same that will be used for the scheduling of the //paging message by the controller p_info[j]->paging_index = 10; p_info[j]->has_paging_index = 0; //TODO:Set the paging message size p_info[j]->paging_message_size = 100; p_info[j]->has_paging_message_size = 0; //TODO: Set the paging subframe p_info[j]->paging_subframe = 10; p_info[j]->has_paging_subframe = 0; //TODO: Set the carrier index for the pending paging message p_info[j]->carrier_index = 0; p_info[j]->has_carrier_index = 0; } //Add all paging info to the paging buffer rerport paging_report->paging_info = p_info; //Add the paging report to the UE report ue_report[i]->pbr = paging_report; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS; } /* Check flag for creation of UL CQI report */ if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) { //Fill in the full UL CQI report of the UE Protocol__FlexUlCqiReport *full_ul_report; full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport)); if (full_ul_report == NULL) goto error; protocol__flex_ul_cqi_report__init(full_ul_report); full_ul_report->sfn_sn = flexran_get_sfn_sf(mod_id); full_ul_report->has_sfn_sn = 1; //TODO:Set the number of UL measurement reports based on the types of measurements //configured for this UE and on the servCellIndex full_ul_report->n_cqi_meas = 1; Protocol__FlexUlCqi **ul_report; ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas); if (ul_report == NULL) { free(full_ul_report); goto error; } //Fill each UL report of the UE for each of the configured report types for (int j = 0; j < full_ul_report->n_cqi_meas; j++) { ul_report[j] = malloc(sizeof(Protocol__FlexUlCqi)); if (ul_report[j] == NULL) { for (int k = 0; k < j; k++) { free(ul_report[k]); } free(ul_report); free(full_ul_report); goto error; } protocol__flex_ul_cqi__init(ul_report[j]); //TODO: Set the type of the UL report. As an example set it to SRS UL report ul_report[j]->type = PROTOCOL__FLEX_UL_CQI_TYPE__FLUCT_SRS; ul_report[j]->has_type = 1; //TODO:Set the number of SINR measurements based on the report type ul_report[j]->n_sinr = 0; uint32_t *sinr_meas; sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[j]->n_sinr); if (sinr_meas == NULL) { for (int k = 0; k < j; k++) { free(ul_report[k]); } free(ul_report); free(full_ul_report); goto error; } //TODO:Set the SINR measurements for the specified type for (int k = 0; k < ul_report[j]->n_sinr; k++) { sinr_meas[k] = 10; } ul_report[j]->sinr = sinr_meas; //TODO: Set the servCellIndex for this report ul_report[j]->serv_cell_index = 0; ul_report[j]->has_serv_cell_index = 1; //Set the list of UL reports of this UE to the full UL report full_ul_report->cqi_meas = ul_report; full_ul_report->n_pucch_dbm = MAX_NUM_CCs; full_ul_report->pucch_dbm = malloc(sizeof(Protocol__FlexPucchDbm *) * full_ul_report->n_pucch_dbm); for (int j = 0; j < MAX_NUM_CCs; j++) { full_ul_report->pucch_dbm[j] = malloc(sizeof(Protocol__FlexPucchDbm)); protocol__flex_pucch_dbm__init(full_ul_report->pucch_dbm[j]); full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1; full_ul_report->pucch_dbm[j]->serv_cell_index = j; if (flexran_get_p0_pucch_dbm(mod_id, UE_id, j) != -1) { full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(mod_id, UE_id, j); full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1; } } } // Add full UL CQI report to the UE report ue_report[i]->ul_cqi_report = full_ul_report; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI; } if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_STATS) { Protocol__FlexMacStats *macstats; macstats = malloc(sizeof(Protocol__FlexMacStats)); if (macstats == NULL) goto error; protocol__flex_mac_stats__init(macstats); macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, UE_id, cc_id); macstats->has_total_bytes_sdus_dl = 1; macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, UE_id, cc_id); macstats->has_total_bytes_sdus_ul = 1; macstats->tbs_dl = flexran_get_TBS_dl(mod_id, UE_id, cc_id); macstats->has_tbs_dl = 1; macstats->tbs_ul = flexran_get_TBS_ul(mod_id, UE_id, cc_id); macstats->has_tbs_ul = 1; macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, UE_id, cc_id); macstats->has_prb_retx_dl = 1; macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, UE_id, cc_id); macstats->has_prb_retx_ul = 1; macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, UE_id, cc_id); macstats->has_prb_dl = 1; macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, UE_id, cc_id); macstats->has_prb_ul = 1; macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, UE_id, cc_id); macstats->has_mcs1_dl = 1; macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, UE_id, cc_id); macstats->has_mcs2_dl = 1; macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, UE_id, cc_id); macstats->has_mcs1_ul = 1; macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, UE_id, cc_id); macstats->has_mcs2_ul = 1; macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, UE_id, cc_id); macstats->has_total_prb_dl = 1; macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, UE_id, cc_id); macstats->has_total_prb_ul = 1; macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, UE_id, cc_id); macstats->has_total_pdu_dl = 1; macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, UE_id, cc_id); macstats->has_total_pdu_ul = 1; macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, UE_id, cc_id); macstats->has_total_tbs_dl = 1; macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, UE_id, cc_id); macstats->has_total_tbs_ul = 1; macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, UE_id); macstats->has_harq_round = 1; Protocol__FlexMacSdusDl ** mac_sdus; mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id)); if (mac_sdus == NULL) { free(macstats); goto error; } macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id); for (int j = 0; j < macstats->n_mac_sdus_dl; j++) { mac_sdus[j] = malloc(sizeof(Protocol__FlexMacSdusDl)); protocol__flex_mac_sdus_dl__init(mac_sdus[j]); mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, UE_id, cc_id, j); mac_sdus[j]->has_lcid = 1; mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, UE_id, cc_id, mac_sdus[j]->lcid); mac_sdus[j]->has_sdu_length = 1; } macstats->mac_sdus_dl = mac_sdus; ue_report[i]->mac_stats = macstats; ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_STATS; } } return 0; error: if (ue_report != NULL) { if (n_ue > 0) { for (int i = 0; i < n_ue; i++) { if (ue_report[i]->bsr != NULL) { free(ue_report[i]->bsr); ue_report[i]->bsr = NULL; } if (ue_report[i]->rlc_report != NULL) { for (int j = 0; j < ue_report[i]->n_rlc_report; j++) { if (ue_report[i]->rlc_report[j] != NULL) { free(ue_report[i]->rlc_report[j]); ue_report[i]->rlc_report[j] = NULL; } } free(ue_report[i]->rlc_report); ue_report[i]->rlc_report = NULL; } if (ue_report[i]->dl_cqi_report != NULL) { if (ue_report[i]->dl_cqi_report->csi_report != NULL) { for (int j = 0; j < ue_report[i]->dl_cqi_report->n_csi_report; j++) { if (ue_report[i]->dl_cqi_report->csi_report[j] != NULL) { if (ue_report[i]->dl_cqi_report->csi_report[j]->p10csi != NULL) { free(ue_report[i]->dl_cqi_report->csi_report[j]->p10csi); ue_report[i]->dl_cqi_report->csi_report[j]->p10csi = NULL; } if (ue_report[i]->dl_cqi_report->csi_report[j]->p11csi != NULL) { if (ue_report[i]->dl_cqi_report->csi_report[j]->p11csi->wb_cqi != NULL) { free(ue_report[i]->dl_cqi_report->csi_report[j]->p11csi->wb_cqi); ue_report[i]->dl_cqi_report->csi_report[j]->p11csi->wb_cqi = NULL; } free(ue_report[i]->dl_cqi_report->csi_report[j]->p11csi); ue_report[i]->dl_cqi_report->csi_report[j]->p11csi = NULL; } if (ue_report[i]->dl_cqi_report->csi_report[j]->p20csi != NULL) { free(ue_report[i]->dl_cqi_report->csi_report[j]->p20csi); ue_report[i]->dl_cqi_report->csi_report[j]->p20csi = NULL; } free(ue_report[i]->dl_cqi_report->csi_report[j]); ue_report[i]->dl_cqi_report->csi_report[j] = NULL; } } free(ue_report[i]->dl_cqi_report->csi_report); ue_report[i]->dl_cqi_report->csi_report = NULL; } free(ue_report[i]->dl_cqi_report); ue_report[i]->dl_cqi_report = NULL; } if (ue_report[i]->pbr != NULL) { if (ue_report[i]->pbr->paging_info != NULL) { for (int j = 0; j < ue_report[i]->pbr->n_paging_info; j++) { free(ue_report[i]->pbr->paging_info[j]); ue_report[i]->pbr->paging_info[j] = NULL; } free(ue_report[i]->pbr->paging_info); ue_report[i]->pbr->paging_info = NULL; } free(ue_report[i]->pbr); ue_report[i]->pbr = NULL; } if (ue_report[i]->ul_cqi_report != NULL) { if (ue_report[i]->ul_cqi_report->cqi_meas != NULL) { for (int j = 0; j < ue_report[i]->ul_cqi_report->n_cqi_meas; j++) { if (ue_report[i]->ul_cqi_report->cqi_meas[j] != NULL) { if (ue_report[i]->ul_cqi_report->cqi_meas[j]->sinr != NULL) { free(ue_report[i]->ul_cqi_report->cqi_meas[j]->sinr); ue_report[i]->ul_cqi_report->cqi_meas[j]->sinr = NULL; } free(ue_report[i]->ul_cqi_report->cqi_meas[j]); ue_report[i]->ul_cqi_report->cqi_meas[j] = NULL; } } free(ue_report[i]->ul_cqi_report->cqi_meas); ue_report[i]->ul_cqi_report->cqi_meas = NULL; } if (ue_report[i]->ul_cqi_report->pucch_dbm != NULL) { for (int j = 0; j < MAX_NUM_CCs; j++) { if (ue_report[i]->ul_cqi_report->pucch_dbm[j] != NULL) { free(ue_report[i]->ul_cqi_report->pucch_dbm[j]); ue_report[i]->ul_cqi_report->pucch_dbm[j] = NULL; } } free(ue_report[i]->ul_cqi_report->pucch_dbm); ue_report[i]->ul_cqi_report->pucch_dbm = NULL; } free(ue_report[i]->ul_cqi_report); ue_report[i]->ul_cqi_report = NULL; } if (ue_report[i]->mac_stats != NULL) { if (ue_report[i]->mac_stats->mac_sdus_dl != NULL) { for (int j = 0; j < ue_report[i]->mac_stats->n_mac_sdus_dl; j++) { if (ue_report[i]->mac_stats->mac_sdus_dl[j] != NULL) { free(ue_report[i]->mac_stats->mac_sdus_dl[j]); ue_report[i]->mac_stats->mac_sdus_dl[j] = NULL; } } free(ue_report[i]->mac_stats->mac_sdus_dl); ue_report[i]->mac_stats->mac_sdus_dl = NULL; } free(ue_report[i]->mac_stats); ue_report[i]->mac_stats = NULL; } } } free(ue_report); } return -1; } int flexran_agent_mac_stats_reply_cell(mid_t mod_id, Protocol__FlexCellStatsReport **cell_report, int n_cc, uint32_t cc_flags) { for (int i = 0; i < n_cc; i++) { /* noise and interference report */ if(cc_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)); AssertFatal(ni_report, "cannot malloc() ni_report\n"); protocol__flex_noise_interference_report__init(ni_report); ni_report->sfn_sf = flexran_get_sfn_sf(mod_id); ni_report->has_sfn_sf = 1; ni_report->rip = 0; //TODO: Received interference power in dbm ni_report->has_rip = 0; ni_report->tnp = 0; //TODO: Thermal noise power in dbm ni_report->has_tnp = 0; ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(mod_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; } int flexran_agent_mac_destroy_stats_reply(Protocol__FlexStatsReply *reply) { int i, j, k; Protocol__FlexDlCqiReport *dl_report; Protocol__FlexUlCqiReport *ul_report; Protocol__FlexPagingBufferReport *paging_report; // Free the memory for the UE reports for (i = 0; i < reply->n_ue_report; i++) { free(reply->ue_report[i]->bsr); for (j = 0; j < reply->ue_report[i]->n_rlc_report; j++) { free(reply->ue_report[i]->rlc_report[j]); } free(reply->ue_report[i]->rlc_report); // If DL CQI report flag was set if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) { dl_report = reply->ue_report[i]->dl_cqi_report; // Delete all CSI reports for (j = 0; j < dl_report->n_csi_report; j++) { //Must free memory based on the type of report switch(dl_report->csi_report[j]->report_case) { case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI: free(dl_report->csi_report[j]->p10csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI: free(dl_report->csi_report[j]->p11csi->wb_cqi); free(dl_report->csi_report[j]->p11csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI: free(dl_report->csi_report[j]->p20csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI: free(dl_report->csi_report[j]->p21csi->wb_cqi); free(dl_report->csi_report[j]->p21csi->sb_cqi); free(dl_report->csi_report[j]->p21csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI: free(dl_report->csi_report[j]->a12csi->wb_cqi); free(dl_report->csi_report[j]->a12csi->sb_pmi); free(dl_report->csi_report[j]->a12csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI: free(dl_report->csi_report[j]->a22csi->wb_cqi); free(dl_report->csi_report[j]->a22csi->sb_cqi); free(dl_report->csi_report[j]->a22csi->sb_list); free(dl_report->csi_report[j]->a22csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI: free(dl_report->csi_report[j]->a20csi->sb_list); free(dl_report->csi_report[j]->a20csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI: free(dl_report->csi_report[j]->a30csi->sb_cqi); free(dl_report->csi_report[j]->a30csi); break; case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI: free(dl_report->csi_report[j]->a31csi->wb_cqi); for (k = 0; k < dl_report->csi_report[j]->a31csi->n_sb_cqi; k++) { free(dl_report->csi_report[j]->a31csi->sb_cqi[k]); } free(dl_report->csi_report[j]->a31csi->sb_cqi); break; default: break; } free(dl_report->csi_report[j]); } free(dl_report->csi_report); free(dl_report); } // If Paging buffer report flag was set if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) { paging_report = reply->ue_report[i]->pbr; // Delete all paging buffer reports for (j = 0; j < paging_report->n_paging_info; j++) { free(paging_report->paging_info[j]); } free(paging_report->paging_info); free(paging_report); } // If UL CQI report flag was set if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) { ul_report = reply->ue_report[i]->ul_cqi_report; for (j = 0; j < ul_report->n_cqi_meas; j++) { free(ul_report->cqi_meas[j]->sinr); free(ul_report->cqi_meas[j]); } free(ul_report->cqi_meas); for (j = 0; j < ul_report->n_pucch_dbm; j++) { free(ul_report->pucch_dbm[j]); } free(ul_report->pucch_dbm); free(ul_report); } if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_STATS) { for (j = 0; j < reply->ue_report[i]->mac_stats->n_mac_sdus_dl; j++) free(reply->ue_report[i]->mac_stats->mac_sdus_dl[j]); free(reply->ue_report[i]->mac_stats->mac_sdus_dl); free(reply->ue_report[i]->mac_stats); } } // Free memory for all Cell reports for (i = 0; i < reply->n_cell_report; i++) { if (reply->cell_report[i]->flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) { free(reply->cell_report[i]->noise_inter_report); } } return 0; } int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexHeader *header = NULL; int i; const int xid = *((int *)params); Protocol__FlexUlSrInfo *ul_sr_info_msg; ul_sr_info_msg = malloc(sizeof(Protocol__FlexUlSrInfo)); if (ul_sr_info_msg == NULL) { goto error; } protocol__flex_ul_sr_info__init(ul_sr_info_msg); if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_SR_INFO, &header) != 0) goto error; ul_sr_info_msg->header = header; ul_sr_info_msg->has_sfn_sf = 1; ul_sr_info_msg->sfn_sf = flexran_get_sfn_sf(mod_id); /*TODO: Set the number of UEs that sent an SR */ ul_sr_info_msg->n_rnti = 1; ul_sr_info_msg->rnti = (uint32_t *) malloc(ul_sr_info_msg->n_rnti * sizeof(uint32_t)); if(ul_sr_info_msg->rnti == NULL) { goto error; } /*TODO:Set the rnti of the UEs that sent an SR */ for (i = 0; i < ul_sr_info_msg->n_rnti; i++) { ul_sr_info_msg->rnti[i] = 1; } *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) goto error; protocol__flexran_message__init(*msg); (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG; (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; (*msg)->ul_sr_info_msg = ul_sr_info_msg; return 0; error: // TODO: Need to make proper error handling if (header != NULL) free(header); if (ul_sr_info_msg != NULL) { free(ul_sr_info_msg->rnti); free(ul_sr_info_msg); } if(*msg != NULL) free(*msg); //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__); return -1; } int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) { if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG) goto error; free(msg->ul_sr_info_msg->header); free(msg->ul_sr_info_msg->rnti); free(msg->ul_sr_info_msg); free(msg); return 0; error: //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__); return -1; } int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexHeader *header = NULL; int i, j, UE_id; int available_harq[MAX_MOBILES_PER_ENB]; const int xid = *((int *)params); Protocol__FlexSfTrigger *sf_trigger_msg; sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger)); if (sf_trigger_msg == NULL) { goto error; } protocol__flex_sf_trigger__init(sf_trigger_msg); if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_SF_TRIGGER, &header) != 0) goto error; frame_t frame; sub_frame_t subframe; for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { available_harq[i] = -1; } int ahead_of_time = 0; frame = (frame_t) flexran_get_current_system_frame_num(mod_id); subframe = (sub_frame_t) flexran_get_current_subframe(mod_id); subframe = ((subframe + ahead_of_time) % 10); if (subframe < flexran_get_current_subframe(mod_id)) { frame = (frame + 1) % 1024; } int additional_frames = ahead_of_time / 10; frame = (frame + additional_frames) % 1024; sf_trigger_msg->header = header; sf_trigger_msg->has_sfn_sf = 1; sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 3); sf_trigger_msg->n_dl_info = 0; for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) { available_harq[i] = j; break; } } } // LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10); sf_trigger_msg->n_dl_info = flexran_get_mac_num_ues(mod_id); Protocol__FlexDlInfo **dl_info = NULL; if (sf_trigger_msg->n_dl_info > 0) { dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info); if(dl_info == NULL) goto error; i = -1; //Fill the status of the current HARQ process for each UE for(i = 0; i < sf_trigger_msg->n_dl_info; i++) { if (available_harq[i] < 0) continue; dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo)); if(dl_info[i] == NULL) goto error; UE_id = flexran_get_mac_ue_id(mod_id, i); protocol__flex_dl_info__init(dl_info[i]); dl_info[i]->rnti = flexran_get_mac_ue_crnti(mod_id, UE_id); dl_info[i]->has_rnti = 1; /*Fill in the right id of this round's HARQ process for this UE*/ // uint8_t harq_id; //uint8_t harq_status; // flexran_get_harq(mod_id, UE_PCCID(mod_id, UE_id), i, frame, subframe, &harq_id, &harq_status); dl_info[i]->harq_process_id = available_harq[UE_id]; if (RC.mac && RC.mac[mod_id]) RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0; dl_info[i]->has_harq_process_id = 1; /* Fill in the status of the HARQ process (2 TBs)*/ dl_info[i]->n_harq_status = 2; dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status); for (j = 0; j < dl_info[i]->n_harq_status; j++) { dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_info.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j]; // TODO: This should be different per TB } // LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]); if(dl_info[i]->harq_status[0] > 0) { // LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Need to make a retransmission for harq %d (round %d)\n", flexran_get_current_frame(mod_id), flexran_get_current_subframe(mod_id), dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]); } /*Fill in the serving cell index for this UE */ dl_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id); dl_info[i]->has_serv_cell_index = 1; } } sf_trigger_msg->dl_info = dl_info; /* Fill in the number of UL reception status related info, based on the number of currently * transmitting UEs */ sf_trigger_msg->n_ul_info = flexran_get_mac_num_ues(mod_id); Protocol__FlexUlInfo **ul_info = NULL; if (sf_trigger_msg->n_ul_info > 0) { ul_info = malloc(sizeof(Protocol__FlexUlInfo *) * sf_trigger_msg->n_ul_info); if(ul_info == NULL) goto error; //Fill the reception info for each transmitting UE for(i = 0; i < sf_trigger_msg->n_ul_info; i++) { ul_info[i] = malloc(sizeof(Protocol__FlexUlInfo)); if(ul_info[i] == NULL) goto error; protocol__flex_ul_info__init(ul_info[i]); UE_id = flexran_get_mac_ue_id(mod_id, i); ul_info[i]->rnti = flexran_get_mac_ue_crnti(mod_id, UE_id); ul_info[i]->has_rnti = 1; /* Fill in the Tx power control command for this UE (if available), * primary carrier */ if(flexran_get_tpc(mod_id, UE_id, 0) != 1){ /* assume primary carrier */ ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0); ul_info[i]->has_tpc = 1; } else{ /* assume primary carrier */ ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0); ul_info[i]->has_tpc = 0; } /*TODO: fill in the amount of data in bytes in the MAC SDU received in this subframe for the given logical channel*/ ul_info[i]->n_ul_reception = 0; ul_info[i]->ul_reception = malloc(sizeof(uint32_t) * ul_info[i]->n_ul_reception); for (j = 0; j < ul_info[i]->n_ul_reception; j++) { ul_info[i]->ul_reception[j] = 100; } /*TODO: Fill in the reception status for each UEs data*/ ul_info[i]->reception_status = PROTOCOL__FLEX_RECEPTION_STATUS__FLRS_OK; ul_info[i]->has_reception_status = 1; /*Fill in the serving cell index for this UE */ ul_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id); ul_info[i]->has_serv_cell_index = 1; } } sf_trigger_msg->ul_info = ul_info; *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) goto error; protocol__flexran_message__init(*msg); (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG; (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; (*msg)->sf_trigger_msg = sf_trigger_msg; return 0; error: if (header != NULL) free(header); if (sf_trigger_msg != NULL) { if (sf_trigger_msg->dl_info != NULL) { for (i = 0; i < sf_trigger_msg->n_dl_info; i++) { if (sf_trigger_msg->dl_info[i] != NULL) { if (sf_trigger_msg->dl_info[i]->harq_status != NULL) { free(sf_trigger_msg->dl_info[i]->harq_status); } free(sf_trigger_msg->dl_info[i]); } } free(sf_trigger_msg->dl_info); } if (sf_trigger_msg->ul_info != NULL) { for (i = 0; i < sf_trigger_msg->n_ul_info; i++) { if (sf_trigger_msg->ul_info[i] != NULL) { if (sf_trigger_msg->ul_info[i]->ul_reception != NULL) { free(sf_trigger_msg->ul_info[i]->ul_reception); } free(sf_trigger_msg->ul_info[i]); } } free(sf_trigger_msg->ul_info); } free(sf_trigger_msg); } if(*msg != NULL) free(*msg); //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__); return -1; } int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg) { int i; if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG) goto error; free(msg->sf_trigger_msg->header); for (i = 0; i < msg->sf_trigger_msg->n_dl_info; i++) { free(msg->sf_trigger_msg->dl_info[i]->harq_status); free(msg->sf_trigger_msg->dl_info[i]); } free(msg->sf_trigger_msg->dl_info); for (i = 0; i < msg->sf_trigger_msg->n_ul_info; i++) { free(msg->sf_trigger_msg->ul_info[i]->ul_reception); free(msg->sf_trigger_msg->ul_info[i]); } free(msg->sf_trigger_msg->ul_info); free(msg->sf_trigger_msg); free(msg); return 0; error: //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__); return -1; } int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg) { int xid = 0; Protocol__FlexHeader *header = NULL; if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_DL_MAC_CONFIG, &header) != 0) goto error; Protocol__FlexDlMacConfig *dl_mac_config_msg; dl_mac_config_msg = malloc(sizeof(Protocol__FlexDlMacConfig)); if (dl_mac_config_msg == NULL) { free(header); goto error; } protocol__flex_dl_mac_config__init(dl_mac_config_msg); dl_mac_config_msg->header = header; dl_mac_config_msg->has_sfn_sf = 1; dl_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id); *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) { free(dl_mac_config_msg); free(header); goto error; } protocol__flexran_message__init(*msg); (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG; (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; (*msg)->dl_mac_config_msg = dl_mac_config_msg; return 0; error: return -1; } int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg) { int i,j, k; if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG) goto error; Protocol__FlexDlDci *dl_dci; free(msg->dl_mac_config_msg->header); for (i = 0; i < msg->dl_mac_config_msg->n_dl_ue_data; i++) { free(msg->dl_mac_config_msg->dl_ue_data[i]->ce_bitmap); for (j = 0; j < msg->dl_mac_config_msg->dl_ue_data[i]->n_rlc_pdu; j++) { for (k = 0; k < msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) { free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]); } free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb); free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]); } free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu); dl_dci = msg->dl_mac_config_msg->dl_ue_data[i]->dl_dci; free(dl_dci->tbs_size); free(dl_dci->mcs); free(dl_dci->ndi); free(dl_dci->rv); free(dl_dci); free(msg->dl_mac_config_msg->dl_ue_data[i]); } free(msg->dl_mac_config_msg->dl_ue_data); for (i = 0; i < msg->dl_mac_config_msg->n_dl_rar; i++) { dl_dci = msg->dl_mac_config_msg->dl_rar[i]->rar_dci; free(dl_dci->tbs_size); free(dl_dci->mcs); free(dl_dci->ndi); free(dl_dci->rv); free(dl_dci); free(msg->dl_mac_config_msg->dl_rar[i]); } free(msg->dl_mac_config_msg->dl_rar); for (i = 0; i < msg->dl_mac_config_msg->n_dl_broadcast; i++) { dl_dci = msg->dl_mac_config_msg->dl_broadcast[i]->broad_dci; free(dl_dci->tbs_size); free(dl_dci->mcs); free(dl_dci->ndi); free(dl_dci->rv); free(dl_dci); free(msg->dl_mac_config_msg->dl_broadcast[i]); } free(msg->dl_mac_config_msg->dl_broadcast); for ( i = 0; i < msg->dl_mac_config_msg->n_ofdm_sym; i++) { free(msg->dl_mac_config_msg->ofdm_sym[i]); } free(msg->dl_mac_config_msg->ofdm_sym); free(msg->dl_mac_config_msg); free(msg); return 0; error: return -1; } int flexran_agent_mac_create_empty_ul_config(mid_t mod_id, Protocol__FlexranMessage **msg) { int xid = 0; Protocol__FlexHeader *header = NULL; if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_MAC_CONFIG, &header) != 0) goto error; Protocol__FlexUlMacConfig *ul_mac_config_msg; ul_mac_config_msg = malloc(sizeof(Protocol__FlexUlMacConfig)); if (ul_mac_config_msg == NULL) { goto error; } protocol__flex_ul_mac_config__init(ul_mac_config_msg); ul_mac_config_msg->header = header; ul_mac_config_msg->has_sfn_sf = 1; ul_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id); *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) { free(ul_mac_config_msg); goto error; } protocol__flexran_message__init(*msg); (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG; (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; (*msg)->ul_mac_config_msg = ul_mac_config_msg; return 0; error: if(header){ free(header); header = NULL; } return -1; } int flexran_agent_mac_destroy_ul_config(Protocol__FlexranMessage *msg) { int i; //,j, k; if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG) goto error; // Protocol__FlexUlDci *ul_dci; free(msg->ul_mac_config_msg->header); for (i = 0; i < msg->ul_mac_config_msg->n_ul_ue_data; i++) { // TODO uplink rlc ... // free(msg->ul_mac_config_msg->dl_ue_data[i]->ce_bitmap); // for (j = 0; j < msg->ul_mac_config_msg->ul_ue_data[i]->n_rlc_pdu; j++) { // for (k = 0; k < msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) { // free(msg->ul_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]); // } // free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb); // free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]); // } // free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu); // ul_dci = msg->ul_mac_config_msg->ul_ue_data[i]->ul_dci; // free(dl_dci->tbs_size); // free(ul_dci->mcs); // free(ul_dci->ndi); // free(ul_dci->rv); // free(ul_dci); // free(msg->ul_mac_config_msg->ul_ue_data[i]); } free(msg->ul_mac_config_msg->ul_ue_data); free(msg->ul_mac_config_msg); free(msg); return 0; error: return -1; } void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg) { struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); if (lfds700_ringbuffer_read(&ringbuffer_state[mod_id], NULL, (void **) msg, &ls) == 0) { *msg = NULL; } } int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { struct lfds700_misc_prng_state ls; enum lfds700_misc_flag overwrite_occurred_flag; Protocol__FlexranMessage *overwritten_dl_config; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); lfds700_ringbuffer_write( &ringbuffer_state[mod_id], NULL, (void *) params, &overwrite_occurred_flag, NULL, (void **)&overwritten_dl_config, &ls); if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { // Delete unmanaged dl_config flexran_agent_mac_destroy_dl_config(overwritten_dl_config); } *msg = NULL; return 2; // error: //*msg = NULL; //return -1; } void flexran_agent_init_mac_agent(mid_t mod_id) { int i, j; lfds700_misc_library_init_valid_on_current_logical_core(); lfds700_misc_prng_init(&ps[mod_id]); int num_elements = RINGBUFFER_SIZE + 1; //Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time /* lfds700_ringbuffer_init_valid_on_current_logical_core()'s second argument * must be aligned to LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES. From the * documentation: "Heap allocated variables however will by no means be * correctly aligned and an aligned malloc must be used." Therefore, we use * posix_memalign */ i = posix_memalign((void **)&dl_mac_config_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, sizeof(struct lfds700_ringbuffer_element) * num_elements); AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n"); lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL); struct lfds700_misc_prng_state scrng; i = posix_memalign((void **) &slice_config_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, sizeof(struct lfds700_ringbuffer_element) * num_elements); AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory\n"); lfds700_ringbuffer_init_valid_on_current_logical_core( &slice_config_ringbuffer_state[mod_id], slice_config_array[mod_id], num_elements, &scrng, NULL); struct lfds700_misc_prng_state sscrng; i = posix_memalign((void **) &store_slice_config_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, sizeof(struct lfds700_ringbuffer_element) * num_elements); AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory\n"); lfds700_ringbuffer_init_valid_on_current_logical_core( &store_slice_config_ringbuffer_state[mod_id], store_slice_config_array[mod_id], num_elements, &sscrng, NULL); struct lfds700_misc_prng_state uarng; i = posix_memalign((void **) &ue_assoc_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, sizeof(struct lfds700_ringbuffer_element) * num_elements); AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory\n"); lfds700_ringbuffer_init_valid_on_current_logical_core( &ue_assoc_ringbuffer_state[mod_id], ue_assoc_array[mod_id], num_elements, &uarng, NULL); for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; } } SLIST_INIT(&flexran_handles[mod_id]); } /*********************************************** * FlexRAN agent - technology mac API implementation ***********************************************/ void flexran_agent_send_sr_info(mid_t mod_id) { int size; Protocol__FlexranMessage *msg = NULL; void *data; int priority = 0; err_code_t err_code; int xid = 0; /*TODO: Must use a proper xid*/ err_code = flexran_agent_mac_sr_info(mod_id, (void *) &xid, &msg); if (err_code < 0) { goto error; } if (msg != NULL){ data=flexran_agent_pack_message(msg, &size); /*Send sr info using the MAC channel of the eNB*/ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) { err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING; goto error; } LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size); return; } error: LOG_D(FLEXRAN_AGENT, "Could not send sr message\n"); } void flexran_agent_send_sf_trigger(mid_t mod_id) { int size; Protocol__FlexranMessage *msg = NULL; void *data; int priority = 0; err_code_t err_code; int xid = 0; /*TODO: Must use a proper xid*/ err_code = flexran_agent_mac_sf_trigger(mod_id, (void *) &xid, &msg); if (err_code < 0) { goto error; } if (msg != NULL){ data=flexran_agent_pack_message(msg, &size); /*Send sr info using the MAC channel of the eNB*/ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) { err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING; goto error; } LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size); return; } error: LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n"); } int flexran_agent_register_mac_xface(mid_t mod_id) { if (agent_mac_xface[mod_id]) { LOG_E(MAC, "MAC agent for eNB %d is already registered\n", mod_id); return -1; } AGENT_MAC_xface *xface = malloc(sizeof(AGENT_MAC_xface)); if (!xface) { LOG_E(FLEXRAN_AGENT, "could not allocate memory for MAC agent xface %d\n", mod_id); return -1; } xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info; xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger; xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config; xface->flexran_agent_notify_tick = flexran_agent_timer_signal; xface->dl_scheduler_loaded_lib = NULL; xface->ul_scheduler_loaded_lib = NULL; agent_mac_xface[mod_id] = xface; return 0; } void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id, Protocol__FlexCellConfig *conf) { if (!conf->si_config) { conf->si_config = malloc(sizeof(Protocol__FlexSiConfig)); if (conf->si_config) protocol__flex_si_config__init(conf->si_config); } if (conf->si_config) { conf->si_config->sfn = flexran_get_current_system_frame_num(mod_id); conf->si_config->has_sfn = 1; } conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig)); if (conf->slice_config) { protocol__flex_slice_config__init(conf->slice_config); Protocol__FlexSliceConfig *sc = conf->slice_config; sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); DevAssert(sc->dl); protocol__flex_slice_dl_ul_config__init(sc->dl); sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id); sc->dl->has_algorithm = 1; sc->dl->n_slices = flexran_get_num_dl_slices(mod_id); if (sc->dl->n_slices > 0) { sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *)); DevAssert(sc->dl->slices); for (int i = 0; i < sc->dl->n_slices; ++i) { sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice)); DevAssert(sc->dl->slices[i]); protocol__flex_slice__init(sc->dl->slices[i]); flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm); } } else { sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id); } sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); DevAssert(sc->ul); protocol__flex_slice_dl_ul_config__init(sc->ul); sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id); sc->ul->has_algorithm = 1; sc->ul->n_slices = flexran_get_num_ul_slices(mod_id); if (sc->ul->n_slices > 0) { sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *)); DevAssert(sc->ul->slices); for (int i = 0; i < sc->ul->n_slices; ++i) { sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice)); DevAssert(sc->ul->slices[i]); protocol__flex_slice__init(sc->ul->slices[i]); flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm); } } else { sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id); } } } void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) { Protocol__FlexSliceConfig *sc = conf->slice_config; for (int i = 0; i < sc->dl->n_slices; ++i) { free(sc->dl->slices[i]); sc->dl->slices[i] = NULL; /* scheduler names are not freed: we assume we read them directly from the * underlying memory and do not dispose it */ } free(sc->dl->slices); /* scheduler name is not freed */ free(sc->dl); sc->dl = NULL; for (int i = 0; i < sc->ul->n_slices; ++i) { free(sc->ul->slices[i]); sc->ul->slices[i] = NULL; /* scheduler names are not freed */ } free(sc->ul->slices); /* scheduler name is not freed */ free(sc->ul); sc->ul = NULL; free(conf->slice_config); conf->slice_config = NULL; } void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, Protocol__FlexUeConfig *ue_conf) { if (ue_conf->has_rnti && ue_conf->rnti != flexran_get_mac_ue_crnti(mod_id, ue_id)) { LOG_E(FLEXRAN_AGENT, "ue_config existing RNTI %x does not match MAC RNTI %x\n", ue_conf->rnti, flexran_get_mac_ue_crnti(mod_id, ue_id)); return; } ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); ue_conf->has_rnti = 1; int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); ue_conf->dl_slice_id = dl_id; ue_conf->has_dl_slice_id = dl_id >= 0; int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); ue_conf->ul_slice_id = ul_id; ue_conf->has_ul_slice_id = ul_id >= 0; ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id); ue_conf->has_ue_aggregated_max_bitrate_ul = 1; ue_conf->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id, ue_id); ue_conf->has_ue_aggregated_max_bitrate_dl = 1; /* TODO update through RAN API */ //config->has_pcell_carrier_index = 1; //config->pcell_carrier_index = UE_PCCID(mod_id, i); //TODO: Set carrier aggregation support (boolean) } void flexran_agent_fill_mac_lc_ue_config(mid_t mod_id, mid_t ue_id, Protocol__FlexLcUeConfig *lc_ue_conf) { lc_ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); lc_ue_conf->has_rnti = 1; lc_ue_conf->n_lc_config = flexran_get_num_ue_lcs(mod_id, ue_id); if (lc_ue_conf->n_lc_config == 0) return; Protocol__FlexLcConfig **lc_config = calloc(lc_ue_conf->n_lc_config, sizeof(Protocol__FlexLcConfig *)); if (!lc_config) { LOG_E(FLEXRAN_AGENT, "could not allocate memory for lc_config of UE %x\n", lc_ue_conf->rnti); lc_ue_conf->n_lc_config = 0; return; // can not allocate memory, skip rest } for (int j = 0; j < lc_ue_conf->n_lc_config; j++) { lc_config[j] = malloc(sizeof(Protocol__FlexLcConfig)); if (!lc_config[j]) continue; // go over this error, try entry protocol__flex_lc_config__init(lc_config[j]); lc_config[j]->has_lcid = 1; lc_config[j]->lcid = j+1; const int lcg = flexran_get_lcg(mod_id, ue_id, j+1); if (lcg >= 0 && lcg <= 3) { lc_config[j]->has_lcg = 1; lc_config[j]->lcg = flexran_get_lcg(mod_id, ue_id, j+1); } lc_config[j]->has_direction = 1; lc_config[j]->direction = flexran_get_direction(ue_id, j+1); //TODO: Bearer type. One of FLQBT_* values. Currently only default bearer supported lc_config[j]->has_qos_bearer_type = 1; lc_config[j]->qos_bearer_type = PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_NON_GBR; //TODO: Set the QCI defined in TS 23.203, coded as defined in TS 36.413 // One less than the actual QCI value. Needs to be generalized lc_config[j]->has_qci = 1; lc_config[j]->qci = 1; if (lc_config[j]->direction == PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_GBR) { /* TODO all of the need to be taken from API */ //TODO: Set the max bitrate (UL) lc_config[j]->has_e_rab_max_bitrate_ul = 0; lc_config[j]->e_rab_max_bitrate_ul = 0; //TODO: Set the max bitrate (DL) lc_config[j]->has_e_rab_max_bitrate_dl = 0; lc_config[j]->e_rab_max_bitrate_dl = 0; //TODO: Set the guaranteed bitrate (UL) lc_config[j]->has_e_rab_guaranteed_bitrate_ul = 0; lc_config[j]->e_rab_guaranteed_bitrate_ul = 0; //TODO: Set the guaranteed bitrate (DL) lc_config[j]->has_e_rab_guaranteed_bitrate_dl = 0; lc_config[j]->e_rab_guaranteed_bitrate_dl = 0; } } lc_ue_conf->lc_config = lc_config; } int flexran_agent_unregister_mac_xface(mid_t mod_id) { if (!agent_mac_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id); return -1; } lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); free(dl_mac_config_array[mod_id]); lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); free(slice_config_array[mod_id]); lfds700_ringbuffer_cleanup(&store_slice_config_ringbuffer_state[mod_id], NULL ); free(store_slice_config_array[mod_id]); lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); free(ue_assoc_array[mod_id]); lfds700_misc_library_cleanup(); AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; xface->flexran_agent_send_sr_info = NULL; xface->flexran_agent_send_sf_trigger = NULL; xface->flexran_agent_get_pending_dl_mac_config = NULL; xface->flexran_agent_notify_tick = NULL; xface->dl_scheduler_loaded_lib = NULL; xface->ul_scheduler_loaded_lib = NULL; free(xface); agent_mac_xface[mod_id] = NULL; return 0; } void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { if (slice_config->dl) { if (slice_config->dl->scheduler) free(slice_config->dl->scheduler); for (int i = 0; i < slice_config->dl->n_slices; i++) if (slice_config->dl->slices[i]->scheduler) free(slice_config->dl->slices[i]->scheduler); } if (slice_config->ul) { if (slice_config->ul->scheduler) free(slice_config->ul->scheduler); for (int i = 0; i < slice_config->ul->n_slices; i++) if (slice_config->ul->slices[i]->scheduler) free(slice_config->ul->slices[i]->scheduler); } Protocol__FlexCellConfig helper; helper.slice_config = slice_config; flexran_agent_destroy_mac_slice_config(&helper); } int check_scheduler(mid_t mod_id, char *s) { if (!s) return 1; if (dlsym(NULL, s)) return 1; flexran_agent_so_handle_t *so = NULL; SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { if (strcmp(so->name, s) == 0) return 1; } return 0; } void request_scheduler(mid_t mod_id, char *s, int xid) { LOG_W(FLEXRAN_AGENT, "unknown scheduler %s, requesting controller to send it\n", s); Protocol__FlexControlDelegationRequest *req = malloc(sizeof(Protocol__FlexControlDelegationRequest)); DevAssert(req); protocol__flex_control_delegation_request__init(req); Protocol__FlexHeader *header = NULL; int rc = flexran_create_header( xid, PROTOCOL__FLEX_TYPE__FLPT_DELEGATE_REQUEST, &header); AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); req->header = header; req->delegation_type = PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER; req->name = strdup(s); Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); DevAssert(msg); protocol__flexran_message__init(msg); msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG; msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; msg->control_del_req_msg = req; int size = 0; void *data = flexran_agent_pack_message(msg, &size); if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0) LOG_E(FLEXRAN_AGENT, "%s(): error while sending message\n", __func__); } Protocol__FlexranMessage *request_scheduler_timeout( mid_t mod_id, const Protocol__FlexranMessage *msg) { const Protocol__FlexEnbConfigReply *ecr = msg->enb_config_reply_msg; struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); Protocol__FlexranMessage *smsg = NULL; struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; if (lfds700_ringbuffer_read(state, NULL, (void **) &smsg, &ls)) { AssertFatal(msg == smsg, "expected and returned enb_config_reply are not the same\n"); AssertFatal(ecr->header->xid == smsg->enb_config_reply_msg->header->xid, "expected and returned enb_config_reply are not the same\n"); } else { LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); } /* call the helper so that scheduler names are correctly freed */ helper_destroy_mac_slice_config(ecr->cell_config[0]->slice_config); ecr->cell_config[0]->slice_config = NULL; /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since * upon timer removal, this is automatically done */ LOG_W(FLEXRAN_AGENT, "remove stored slice config (xid %d) after timeout\n", ecr->header->xid); flexran_agent_destroy_timer(mod_id, ecr->header->xid); return NULL; } void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config, int request_objects) { if (!*slice_config) return; /* just use the memory and set to NULL in original */ Protocol__FlexSliceConfig *sc = *slice_config; *slice_config = NULL; struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); enum lfds700_misc_flag overwrite_occurred_flag; int put_on_hold = 0; if (request_objects && sc->dl->scheduler && !check_scheduler(mod_id, sc->dl->scheduler)) { request_scheduler(mod_id, sc->dl->scheduler, xid++); put_on_hold = 1; } for (int i = 0; request_objects && i < sc->dl->n_slices; ++i) { Protocol__FlexSlice *sl = sc->dl->slices[i]; if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) { request_scheduler(mod_id, sl->scheduler, xid++); put_on_hold = 1; } } if (put_on_hold) { Protocol__FlexEnbConfigReply *reply = malloc(sizeof(Protocol__FlexEnbConfigReply)); DevAssert(reply); protocol__flex_enb_config_reply__init(reply); /* use the last used xid so we can correlate answer and waiting config */ int rc = flexran_create_header( xid - 1, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &reply->header); AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); reply->n_cell_config = 1; reply->cell_config = malloc(sizeof(Protocol__FlexCellConfig *)); DevAssert(reply->cell_config); reply->cell_config[0] = malloc(sizeof(Protocol__FlexCellConfig)); DevAssert(reply->cell_config[0]); protocol__flex_cell_config__init(reply->cell_config[0]); reply->cell_config[0]->slice_config = sc; Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); DevAssert(msg); protocol__flexran_message__init(msg); msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG; msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; msg->enb_config_reply_msg = reply; Protocol__FlexEnbConfigReply *o; lfds700_ringbuffer_write(&store_slice_config_ringbuffer_state[mod_id], NULL, (void *)msg, &overwrite_occurred_flag, NULL, (void **) &o, &ls); AssertFatal(overwrite_occurred_flag == LFDS700_MISC_FLAG_LOWERED, "unhandled: stored slice config for controller has been overwritten\n"); flexran_agent_create_timer(mod_id, 3000, FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid - 1, request_scheduler_timeout, msg); /* need reply for xid */ return; } Protocol__FlexSliceConfig *overwritten_sc; lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], NULL, (void *)sc, &overwrite_occurred_flag, NULL, (void **)&overwritten_sc, &ls); if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { helper_destroy_mac_slice_config(overwritten_sc); LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n"); } } void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); enum lfds700_misc_flag overwrite_occurred_flag; Protocol__FlexUeConfig *overwritten_ue_config; lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id], NULL, (void *) *ue_config, &overwrite_occurred_flag, NULL, (void **)&overwritten_ue_config, &ls); if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { free(overwritten_ue_config); LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n"); } } void flexran_agent_slice_update(mid_t mod_id) { struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); Protocol__FlexSliceConfig *sc = NULL; struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id]; if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) { apply_update_dl_slice_config(mod_id, sc->dl); apply_update_ul_slice_config(mod_id, sc->ul); helper_destroy_mac_slice_config(sc); flexran_agent_so_handle_t *so = NULL; flexran_agent_so_handle_t *prev = NULL; // the previous to current element, if we delete in order to go back //SLIST_FOREACH(so, &flexran_handles[mod_id], entries) for(so = flexran_handles[mod_id].slh_first; so;) { char *name = so->name; int in_use = strcmp(flexran_get_dl_scheduler_name(mod_id), name) == 0 || strcmp(flexran_get_ul_scheduler_name(mod_id), name) == 0; Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); if (!in_use && dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { int n = flexran_get_num_dl_slices(mod_id); for (int i = 0; i < n; ++i) { Protocol__FlexSlice s; /* NONE so it won't do any allocations */ flexran_get_dl_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); if (strcmp(s.scheduler, name) == 0) { in_use = 1; break; } } } Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); if (!in_use && ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { int n = flexran_get_num_ul_slices(mod_id); for (int i = 0; i < n; ++i) { Protocol__FlexSlice s; /* NONE so it won't do any allocations */ flexran_get_ul_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); if (strcmp(s.scheduler, name) == 0) { in_use = 1; break; } } } if (!in_use) { char s[512]; int rc = flexran_agent_map_name_to_delegated_object(mod_id, so->name, s, 512); LOG_W(FLEXRAN_AGENT, "removing %s (library handle %p) since it is not used in the user " "plane anymore\n", s, so->dl_handle); dlclose(so->dl_handle); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", so->name); } else { int rc = remove(s); if (rc < 0) LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", s, strerror(errno)); } free (so->name); if (!prev) { //it's the head, start over SLIST_REMOVE_HEAD(&flexran_handles[mod_id], entries); so = flexran_handles[mod_id].slh_first; } else { SLIST_REMOVE(&flexran_handles[mod_id], so, flexran_agent_so_handle_s, entries); so = prev->entries.sle_next; } } else { prev = so; so = so->entries.sle_next; } } } Protocol__FlexUeConfig *ue_config = NULL; state = &ue_assoc_ringbuffer_state[mod_id]; if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) { apply_ue_slice_assoc_update(mod_id, ue_config); free(ue_config); } } void flexran_agent_mac_inform_delegation(mid_t mod_id, Protocol__FlexControlDelegation *cdm) { LOG_W(FLEXRAN_AGENT, "received FlexControlDelegation message for object '%s' xid %d\n", cdm->name, cdm->header->xid); if (cdm->header->xid < xid - 1) { LOG_I(FLEXRAN_AGENT, "waiting for %d more messages (up to xid %d)\n", xid - 1 - cdm->header->xid, xid - 1); return; } /* should receive up to xid - 1, otherwise it means there was no request */ AssertFatal(xid > cdm->header->xid, "received control delegation with xid %d that we never requested " "(last request %d)\n", cdm->header->xid, xid - 1); /* Load the library so the user plane can search it */ char s[512]; int rc = flexran_agent_map_name_to_delegated_object(mod_id, cdm->name, s, 512); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", cdm->name); return; } /* TODO where to unload/save handle?? */ void *h = dlopen(s, RTLD_NOW); if (!h) { LOG_E(FLEXRAN_AGENT, "dlopen(): %s\n", dlerror()); return; } LOG_I(FLEXRAN_AGENT, "library handle %p\n", h); struct lfds700_misc_prng_state ls; LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; lfds700_misc_prng_init(&ls); Protocol__FlexranMessage *msg = NULL; struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; if (lfds700_ringbuffer_read(state, NULL, (void **) &msg, &ls) == 0) { LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); return; } AssertFatal(cdm->header->xid == msg->enb_config_reply_msg->header->xid, "expected and retrieved xid of stored slice configuration does " "not match (expected %d, retrieved %d)\n", cdm->header->xid, msg->enb_config_reply_msg->header->xid); /* Since we recover, stop the timeout */ rc = flexran_agent_destroy_timer(mod_id, cdm->header->xid); prepare_update_slice_config( mod_id, &msg->enb_config_reply_msg->cell_config[0]->slice_config, 0 /* don't do a request */); /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since * upon timer removal, this is automatically done. * prepare_update_slice_config() takes ownership of the slice config, it is * freed inside */ flexran_agent_so_handle_t *so = malloc(sizeof(flexran_agent_so_handle_t)); DevAssert(so); so->name = strdup(cdm->name); DevAssert(so->name); so->dl_handle = h; SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries); } void flexran_agent_mac_fill_loaded_mac_objects( mid_t mod_id, Protocol__FlexEnbConfigReply *reply) { int n = 0; flexran_agent_so_handle_t *so = NULL; SLIST_FOREACH(so, &flexran_handles[mod_id], entries) ++n; reply->n_loadedmacobjects = n; reply->loadedmacobjects = calloc(n, sizeof(char *)); if (!reply->loadedmacobjects) { reply->n_loadedmacobjects = 0; return; } n = 0; SLIST_FOREACH(so, &flexran_handles[mod_id], entries) reply->loadedmacobjects[n++] = so->name; }