/* rlc_mac.c ------------------- AUTHOR : Lionel GAUTHIER COMPANY : EURECOM EMAIL : Lionel.Gauthier@eurecom.fr */ //----------------------------------------------------------------------------- #define RLC_MAC_C #include "rlc.h" #include "LAYER2/MAC/extern.h" #include "UTIL/LOG/log.h" #define DEBUG_MAC_INTERFACE // tb_size_t in bytes //----------------------------------------------------------------------------- struct mac_data_ind mac_rlc_deserialize_tb (char* bufferP, tb_size_t tb_sizeP, num_tb_t num_tbP, crc_t *crcsP) { //----------------------------------------------------------------------------- struct mac_data_ind data_ind; mem_block_t* tb; num_tb_t nb_tb_read; tbs_size_t tbs_size; nb_tb_read = 0; tbs_size = 0; list_init(&data_ind.data, NULL); while (num_tbP > 0) { tb = get_free_mem_block(sizeof (mac_rlc_max_rx_header_size_t) + tb_sizeP); if (tb != NULL) { ((struct mac_tb_ind *) (tb->data))->first_bit = 0; ((struct mac_tb_ind *) (tb->data))->data_ptr = (u8_t*)&tb->data[sizeof (mac_rlc_max_rx_header_size_t)]; ((struct mac_tb_ind *) (tb->data))->size = tb_sizeP; if (crcsP) ((struct mac_tb_ind *) (tb->data))->error_indication = crcsP[nb_tb_read]; else ((struct mac_tb_ind *) (tb->data))->error_indication = 0; memcpy(((struct mac_tb_ind *) (tb->data))->data_ptr, &bufferP[tbs_size], tb_sizeP); #ifdef DEBUG_MAC_INTERFACE LOG_T(RLC, "[MAC-RLC] DUMP RX PDU(%d bytes):\n", tb_sizeP); rlc_util_print_hex_octets(RLC, ((struct mac_tb_ind *) (tb->data))->data_ptr, tb_sizeP); #endif nb_tb_read = nb_tb_read + 1; tbs_size = tbs_size + tb_sizeP; list_add_tail_eurecom(tb, &data_ind.data); } num_tbP = num_tbP - 1; } data_ind.no_tb = nb_tb_read; data_ind.tb_size = tb_sizeP << 3; return data_ind; } //----------------------------------------------------------------------------- tbs_size_t mac_rlc_serialize_tb (char* bufferP, list_t transport_blocksP) { //----------------------------------------------------------------------------- mem_block_t* tb; tbs_size_t tbs_size; tbs_size_t tb_size; tbs_size = 0; while (transport_blocksP.nb_elements > 0) { tb = list_remove_head (&transport_blocksP); if (tb != NULL) { tb_size = ((struct mac_tb_req *) (tb->data))->tb_size_in_bits>>3; #ifdef DEBUG_MAC_INTERFACE LOG_T(RLC, "[MAC-RLC] DUMP TX PDU(%d bytes):\n", tb_size); rlc_util_print_hex_octets(RLC, ((struct mac_tb_req *) (tb->data))->data_ptr, tb_size); #endif memcpy(&bufferP[tbs_size], &((struct mac_tb_req *) (tb->data))->data_ptr[0], tb_size); tbs_size = tbs_size + tb_size; free_mem_block(tb); } } return tbs_size; } //----------------------------------------------------------------------------- tbs_size_t mac_rlc_data_req (module_id_t module_idP, u32_t frame, u8_t MBMS_flagP, chan_id_t channel_idP, char* bufferP) { //----------------------------------------------------------------------------- struct mac_data_req data_request; rb_id_t rb_id; #ifdef DEBUG_MAC_INTERFACE LOG_D(RLC, "\n[RLC] Inst %d(%d): MAC_RLC_DATA_REQ channel %d (%d) MAX RB %d, Num_tb %d\n", module_idP,MAX_MODULES, channel_idP, RLC_MAX_LC, RLC_MAX_RB); #endif // DEBUG_MAC_INTERFACE if ((module_idP >= 0) && (module_idP < MAX_MODULES)) { if ((channel_idP >= 0) && (channel_idP < RLC_MAX_LC)) { rb_id = rlc[module_idP].m_lcid2rbid[channel_idP]; if ((rb_id > 0) && (rb_id < RLC_MAX_RB)) { switch (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type) { case RLC_NONE: //handle_event(WARNING,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no radio bearer configured :%d\n", __FILE__, __LINE__, channel_idP); break; case RLC_AM: data_request = rlc_am_mac_data_request(&rlc[module_idP].m_rlc_am_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame); return mac_rlc_serialize_tb(bufferP, data_request.data); break; case RLC_UM: data_request = rlc_um_mac_data_request(&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame); return mac_rlc_serialize_tb(bufferP, data_request.data); break; case RLC_TM: data_request = rlc_tm_mac_data_request(&rlc[module_idP].m_rlc_tm_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame); return mac_rlc_serialize_tb(bufferP, data_request.data); break; default:; //handle_event(ERROR,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no RLC found for this radio bearer %d\n", __FILE__, __LINE__, channel_idP); } } else { LOG_E(RLC, "%s() : radio bearer id out of bounds :%d\n", __FUNCTION__, rb_id); } } else { //handle_event(ERROR,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : parameter rb_id out of bounds :%d\n", __FILE__, __LINE__, channel_idP); LOG_E(RLC, "%s() : parameter channel_id out of bounds :%d\n", __FUNCTION__, channel_idP); return(-1); } } else { LOG_E(RLC, "%s() : parameter module_id out of bounds :%d\n", __FUNCTION__, module_idP); } return (tbs_size_t)0; } //----------------------------------------------------------------------------- void mac_rlc_data_ind (module_id_t module_idP, u32_t frame, u8_t eNB_flag, u8_t MBMS_flagP, chan_id_t channel_idP, char* bufferP, tb_size_t tb_sizeP, num_tb_t num_tbP, crc_t *crcs) { //----------------------------------------------------------------------------- rb_id_t rb_id; #ifdef DEBUG_MAC_INTERFACE if (num_tbP) { LOG_D(RLC, "\n[RLC] Inst %d(%d): MAC_RLC_DATA_IND on channel %d (%d), rb max %d, Num_tb %d\n", module_idP,MAX_MODULES, channel_idP, RLC_MAX_LC, RLC_MAX_RB, num_tbP); } #endif // DEBUG_MAC_INTERFACE if ((module_idP >= 0) && (module_idP < MAX_MODULES)) { if ((channel_idP >= 0) && (channel_idP < RLC_MAX_LC)) { rb_id = rlc[module_idP].m_lcid2rbid[channel_idP]; if ((rb_id > 0) && (rb_id < RLC_MAX_RB)) { //if (num_tbP > 0) { struct mac_data_ind data_ind = mac_rlc_deserialize_tb(bufferP, tb_sizeP, num_tbP, crcs); switch (rlc[module_idP].m_rlc_pointer[rb_id].rlc_type) { case RLC_NONE: //handle_event(WARNING,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no radio bearer configured :%d\n", __FILE__, __LINE__, rb_idP); LOG_W(RLC, " FONCTION mac_rlc_data_ind() : no radio bearer configured :%d\n", rb_id); break; case RLC_AM: #ifdef DEBUG_MAC_INTERFACE LOG_D(RLC, "MAC DATA IND TO RLC_AM MOD_ID %d RB_INDEX %d (%d) MOD_ID_RLC %d\n", module_idP, rlc[module_idP].m_rlc_pointer[rb_id].rlc_index, rb_id, rlc[module_idP].m_rlc_am_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index].module_id); #endif rlc_am_mac_data_indication(&rlc[module_idP].m_rlc_am_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame, eNB_flag, data_ind); break; case RLC_UM: #ifdef DEBUG_MAC_INTERFACE LOG_D(RLC, "MAC DATA IND TO RLC_UM MOD_ID %d RB_INDEX %d MOD_ID_RLC %d\n", module_idP, rlc[module_idP].m_rlc_pointer[rb_id].rlc_index, rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index].module_id); #endif rlc_um_mac_data_indication(&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame, eNB_flag, data_ind); break; case RLC_TM: #ifdef DEBUG_MAC_INTERFACE LOG_D(RLC, "MAC DATA IND TO RLC_TM MOD_ID %d RB_INDEX %d MOD_ID_RLC %d\n", module_idP, rlc[module_idP].m_rlc_pointer[rb_id].rlc_index, rlc[module_idP].m_rlc_tm_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index].module_id); #endif rlc_tm_mac_data_indication(&rlc[module_idP].m_rlc_tm_array[rlc[module_idP].m_rlc_pointer[rb_id].rlc_index], frame, eNB_flag, data_ind); break; default: //handle_event(ERROR,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no RLC found for this radio bearer %d\n", __FILE__, __LINE__, rb_idP); LOG_W(RLC, "FILE FONCTION mac_rlc_data_ind() LINE : no RLC found for this radio bearer %d\n", rb_id); ; } } else { LOG_E(RLC, "%s() : radio bearer id out of bounds : rb is %d\n", __FUNCTION__, rb_id); } } else { LOG_E(RLC, "%s() : parameter channel_id out of bounds : channel is %d\n", __FUNCTION__, channel_idP); } } else { LOG_E(RLC, "%s() : parameter module_id out of bounds : module id is %d\n", __FUNCTION__, module_idP); } } //----------------------------------------------------------------------------- mac_rlc_status_resp_t mac_rlc_status_ind (module_id_t module_idP, u32_t frame, u8_t eNB_flag, u8_t MBMS_flagP, chan_id_t channel_idP, tb_size_t tb_sizeP) { //----------------------------------------------------------------------------- rb_id_t rb_id = 0; mac_rlc_status_resp_t mac_rlc_status_resp; mac_rlc_status_resp.bytes_in_buffer = 0; mac_rlc_status_resp.pdus_in_buffer = 0; if ((module_idP >= 0) && (module_idP < MAX_MODULES)) { if ((channel_idP >= 0) && (channel_idP < RLC_MAX_LC)) { rb_id = rlc[module_idP].m_lcid2rbid[channel_idP]; if ((rb_id > 0) && (rb_id < RLC_MAX_RB)) { struct mac_status_resp status_resp; struct mac_status_ind tx_status; switch (rlc[module_idP].m_rlc_pointer[channel_idP].rlc_type) { case RLC_NONE: //handle_event(WARNING,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no radio bearer configured :%d\n", __FILE__, __LINE__, channel_idP); break; case RLC_AM: status_resp = rlc_am_mac_status_indication(&rlc[module_idP].m_rlc_am_array[rlc[module_idP].m_rlc_pointer[channel_idP].rlc_index], frame, tb_sizeP, tx_status); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send; mac_rlc_status_resp.head_sdu_is_segmented = status_resp.head_sdu_is_segmented; return mac_rlc_status_resp; break; case RLC_UM: //msg("[RLC_UM][MOD %d] mac_rlc_status_ind tb_size %d\n", module_idP, tb_sizeP); status_resp = rlc_um_mac_status_indication(&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[channel_idP].rlc_index], frame, eNB_flag, tb_sizeP, tx_status); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send; mac_rlc_status_resp.head_sdu_is_segmented = status_resp.head_sdu_is_segmented; return mac_rlc_status_resp; break; case RLC_TM: status_resp = rlc_tm_mac_status_indication(&rlc[module_idP].m_rlc_tm_array[rlc[module_idP].m_rlc_pointer[channel_idP].rlc_index], frame, tb_sizeP, tx_status); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; return mac_rlc_status_resp; break; default:; //handle_event(ERROR,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no RLC found for this radio bearer %d\n", __FILE__, __LINE__, channel_idP); } } else { // two many traces because MAC probe inactive channels. LOG_E(RLC, "%s(Mod=%d, eNB_flag=%d, mbms flag=%d,channel_id=%d) : radio bearer id out of bounds :%d \n", __FUNCTION__, module_idP, eNB_flag, MBMS_flagP, channel_idP, rb_id); } } else { LOG_E(RLC, "%s() : parameter channel_id out of bounds :%d\n", __FUNCTION__, channel_idP); } } else { LOG_E(RLC, "%s() : parameter module_id out of bounds :%d\n", __FUNCTION__, module_idP); } return mac_rlc_status_resp; }