diff --git a/openair2/ENB_APP/enb_agent_mac_defs.h b/openair2/ENB_APP/enb_agent_mac_defs.h index c2891e87ca..6e960cdb69 100644 --- a/openair2/ENB_APP/enb_agent_mac_defs.h +++ b/openair2/ENB_APP/enb_agent_mac_defs.h @@ -39,6 +39,8 @@ #define __ENB_AGENT_MAC_PRIMITIVES_H__ #include "enb_agent_defs.h" +#include "progran.pb-c.h" +#include "header.pb-c.h" /* ENB AGENT-MAC Interface */ typedef struct { diff --git a/openair2/LAYER2/MAC/eNB_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/eNB_agent_scheduler_dataplane.c new file mode 100644 index 0000000000..43d4ad2b51 --- /dev/null +++ b/openair2/LAYER2/MAC/eNB_agent_scheduler_dataplane.c @@ -0,0 +1,544 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + +*******************************************************************************/ + +/*! \file eNB_agent_scheduler_dataplane.c + * \brief data plane procedures related to eNB scheduling + * \author Xenofon Foukas + * \date 2016 + * \email: x.foukas@sms.ed.ac.uk + * \version 0.1 + * @ingroup _mac + + */ + +#include "assertions.h" +#include "PHY/defs.h" +#include "PHY/extern.h" + +#include "SCHED/defs.h" +#include "SCHED/extern.h" + +#include "LAYER2/MAC/enb_agent_mac_proto.h" +#include "LAYER2/MAC/defs.h" +#include "LAYER2/MAC/proto.h" +#include "LAYER2/MAC/extern.h" + +#include "UTIL/LOG/log.h" +#include "UTIL/LOG/vcd_signal_dumper.h" +#include "UTIL/OPT/opt.h" +#include "OCG.h" +#include "OCG_extern.h" + +#include "RRC/LITE/extern.h" +#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" + +#include "header.pb-c.h" +#include "progran.pb-c.h" + +#include "SIMULATION/TOOLS/defs.h" // for taus + + +void apply_dl_scheduling_decisions(mid_t mod_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + Protocol__ProgranMessage *dl_scheduling_info) { + + Protocol__PrpDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg; + + // Check if there is anything to schedule for random access + if (mac_config->n_dl_rar > 0) { + /*TODO: call the random access data plane function*/ + } + + // Check if there is anything to schedule for paging/broadcast + if (mac_config->n_dl_broadcast > 0) { + /*TODO: call the broadcast/paging data plane function*/ + } + + // Check if there is anything to schedule for the UEs + if (mac_config->n_dl_ue_data > 0) { + apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag, + mac_config->n_dl_ue_data, mac_config->dl_ue_data); + } + +} + + +void apply_ue_spec_scheduling_decisions(mid_t mod_id, + uint32_t frame, + uint32_t subframe, + int *mbsfn_flag, + uint32_t n_dl_ue_data, + const Protocol__PrpDlData **dl_ue_data) { + + uint8_t CC_id; + int UE_id; + int N_RBG[MAX_NUM_CCs]; + unsigned char aggregation; + mac_rlc_status_resp_t rlc_status; + unsigned char header_len_dcch=0, header_len_dcch_tmp=0,header_len_dtch=0,header_len_dtch_tmp=0, ta_len=0; + unsigned char sdu_lcids[11],offset,num_sdus=0; + uint16_t nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb; + uint16_t TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0; + unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; + unsigned char round = 0; + unsigned char harq_pid = 0; + + LTE_eNB_UE_stats *eNB_UE_stats = NULL; + uint16_t sdu_length_total = 0; + int mcs; + uint16_t min_rb_unit[MAX_NUM_CCs]; + short ta_update = 0; + eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; + UE_list_t *UE_list = &eNB->UE_list; + LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; + int32_t normalized_rx_power, target_rx_power; + int32_t tpc=1; + static int32_t tpc_accumulated=0; + UE_sched_ctrl *ue_sched_ctl; + + int i; + + Protocol__PrpDlData *dl_data; + Protocol__PrpDlDci *dl_dci; + + uint32_t rlc_size, n_lc, lcid; + + + // For each UE-related command + for (i = 0; i < n_dl_ue_data; i++) { + + dl_data = dl_ue_data[i]; + dl_dci = dl_data->dl_dci; + + CC_id = dl_data->serv_cell_index; + frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); + + rnti = dl_data->rnti; + UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); + + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti); + + round = dl_dci->rv[0]; + harq_pid = dl_dci->harq_process; + + // If this is a new transmission + if (round == 0) { + // First we have to deal with the creation of the PDU based on the message instructions + rlc_status.bytes_in_buffer = 0; + + TBS = dl_dci->tbs_size[0]; + LOG_D(MAC,"[TEST] The TBS during the creation process is %d\n", TBS); + + if (dl_data->n_ce_bitmap > 0) { + //Check if there is TA command + if (dl_data->ce_bitmap[0] & PROTOCOL__PRP_CE_TYPE__PRPCET_TA) { + ta_len = 2; + LOG_D(MAC, "[TEST] Need to send timing advance\n"); + } else { + ta_len = 0; + LOG_D(MAC, "[TEST] No timing advance\n"); + } + } + + + n_lc = dl_data->n_rlc_pdu; + num_sdus = 0; + sdu_length_total = 0; + // Go through each one of the channel commands and create SDUs + for (i = 0; i < n_lc; i++) { + lcid = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->logical_channel_id; + LOG_D(MAC, "[TEST] Going through SDU of channel %d\n", lcid); + rlc_size = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->size; + LOG_D(MAC,"[TEST] [eNB %d] Frame %d, LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + mod_id, frame, lcid, CC_id, rlc_size); + if (rlc_size > 0) { + + rlc_status = mac_rlc_status_ind(mod_id, + rnti, + mod_id, + frame, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + rlc_size); // transport block set size + + sdu_lengths[i] = 0; + + LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid); + + sdu_lengths[i] += mac_rlc_data_req(mod_id, + rnti, + mod_id, + frame, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + (char *)&dlsch_buffer[sdu_length_total]); + + LOG_D(MAC, "[TEST] RLC gave %d bytes in LCID %d\n", sdu_lengths[i], lcid); + + LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[i]); + sdu_length_total += sdu_lengths[i]; + LOG_D(MAC, "[TEST] Total sdu size became %d\n", sdu_length_total); + sdu_lcids[i] = lcid; + + UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; + UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[i]; + + if (lcid == DCCH || lcid == DCCH1) { + header_len_dcch += 2; + } else if (lcid == DTCH) { + if (sdu_lengths[i] < 128) { + header_len_dtch = 2; + } else { + header_len_dtch = 3; + } + } + + num_sdus++; + } + } // SDU creation end + + + if (((sdu_length_total + header_len_dcch + header_len_dtch) > 0)) { + + header_len_dcch_tmp = header_len_dcch; + header_len_dtch_tmp = header_len_dtch; + + if (header_len_dtch==0) { + header_len_dcch = (header_len_dcch >0) ? (header_len_dcch - 1) : header_len_dcch; // remove length field + } else { + header_len_dtch = (header_len_dtch > 0) ? 1 : header_len_dtch; // remove length field for the last SDU + } + + // there is a payload + if (((sdu_length_total + header_len_dcch + header_len_dtch ) > 0)) { + if ((TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len) <= 2 + || (TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len) > TBS) { //protect from overflow + padding = (TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len); + post_padding = 0; + } else { + padding = 0; + + // adjust the header len + if (header_len_dtch==0) { + header_len_dcch = header_len_dcch_tmp; + } else { + header_len_dtch = header_len_dtch_tmp; + } + + post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len - 1; // 1 is for the postpadding header + } + } + + + if (ta_len > 0) { + ta_update = ue_sched_ctl->ta_update; + } else { + ta_update = 0; + } + + offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + // offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0], + num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, + 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, + post_padding); + + LOG_D(MAC, "[TEST]Have to schedule %d SDUs with length %d. TBS is %d, LCID is %d, post padding is %d, padding is %d, header offset is %d, total sdu size is %d\n", num_sdus, sdu_lengths[0], TBS, sdu_lcids[0], post_padding, padding, offset, sdu_length_total); + +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n"); + + for (i=0; i<16; i++) { + LOG_T(MAC,"%x.",dlsch_buffer[i]); + } + + LOG_T(MAC,"\n"); +#endif + // cycle through SDUs and place in dlsch_buffer + memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); + // memcpy(&eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); + + // fill remainder of DLSCH with random data + for (j=0; j<(TBS-sdu_length_total-offset); j++) { + UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); + } + + //eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff); + if (opt_enabled == 1) { + trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + TBS, mod_id, 3, UE_RNTI(mod_id, UE_id), + eNB->subframe,0,0); + LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n", + mod_id, CC_id, frame, UE_RNTI(mod_id,UE_id), TBS); + } + + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; + UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0]; + + UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti; + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(mod_id, rnti); + UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; + UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; + + nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=dl_dci->mcs[0]; + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=dl_dci->mcs[0]; + UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; + + UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; + UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; + UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; + + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]]; + eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + } + } else { + // No need to create anything apart of DCI in case of retransmission + + /*TODO: Must add these */ + //eNB_UE_stats->dlsch_trials[round]++; + //UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; + //UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; + //UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; + //UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id]; + //UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; + //UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1; + } + //Fill the proper DCI of OAI + fill_oai_dci(mod_id, CC_id, rnti, dl_dci); + } +} + +void fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, + const Protocol__PrpDlDci *dl_dci) { + + void *DLSCH_dci = NULL; + DCI_PDU *DCI_pdu; + + unsigned char round = 0; + unsigned char harq_pid = 0; + LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; + int size_bits, size_bytes; + eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id]; + UE_list_t *UE_list = &eNB->UE_list; + + int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]); + + harq_pid = dl_dci->harq_process; + round = dl_dci->rv[0]; + + // Note this code is for a specific DCI format + DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid]; + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; + + frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id); + + switch (frame_parms[CC_id]->N_RB_DL) { + case 6: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rv = round; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->dai = dl_dci->dai; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_1_5MHz_TDD_t); + size_bits = sizeof_DCI1_1_5MHz_TDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + LOG_D(MAC,"[TEST] Setting DCI format 1\n"); + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rv = round; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_1_5MHz_FDD_t); + size_bits = sizeof_DCI1_1_5MHz_FDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } + break; + case 25: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rv = round; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->dai = dl_dci->dai; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_5MHz_TDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_5MHz_TDD_t); + size_bits = sizeof_DCI1_5MHz_TDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rv = round; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_5MHz_FDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_5MHz_FDD_t); + size_bits = sizeof_DCI1_5MHz_FDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } + break; + case 50: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rv = round; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->dai = dl_dci->dai; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_10MHz_TDD_t); + size_bits = sizeof_DCI1_10MHz_TDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rv = round; + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_10MHz_FDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_10MHz_TDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_10MHz_FDD_t); + size_bits = sizeof_DCI1_10MHz_FDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } + break; + case 100: + if (frame_parms[CC_id]->frame_type == TDD) { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rv = round; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->dai = dl_dci->dai; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_20MHz_TDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_20MHz_TDD_t); + size_bits = sizeof_DCI1_20MHz_TDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } else { + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rv = round; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rballoc = dl_dci->rb_bitmap; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rah = dl_dci->res_alloc; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->mcs = dl_dci->mcs[0]; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->TPC = dl_dci->tpc; + ((DCI1_20MHz_FDD_t*)DLSCH_dci)->ndi = dl_dci->ndi[0]; + size_bytes = sizeof(DCI1_20MHz_FDD_t); + size_bits = sizeof_DCI1_20MHz_FDD_t; + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + //TODO + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1D) { + //TODO + } + } + break; + } + + //Add DCI based on format + if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_1) { + add_ue_spec_dci(DCI_pdu, + DLSCH_dci, + rnti, + size_bytes, + dl_dci->aggr_level,//aggregation + size_bits, + format1, + 0); + } else if (dl_dci->format == PROTOCOL__PRP_DCI_FORMAT__PRDCIF_2A) { + add_ue_spec_dci(DCI_pdu, + DLSCH_dci, + rnti, + size_bytes, + dl_dci->aggr_level,//aggregation + size_bits, + format2A, + 0); + } +} diff --git a/openair2/LAYER2/MAC/enb_agent_mac_proto.h b/openair2/LAYER2/MAC/enb_agent_mac_proto.h new file mode 100644 index 0000000000..7fcdbc29c3 --- /dev/null +++ b/openair2/LAYER2/MAC/enb_agent_mac_proto.h @@ -0,0 +1,71 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + +*******************************************************************************/ + +/*! \file enb_agent_mac_proto.h + * \brief MAC functions for eNB agent + * \author Xenofon Foukas + * \date 2016 + * \email: x.foukas@sms.ed.ac.uk + * \version 0.1 + * @ingroup _mac + + */ + +#ifndef __LAYER2_MAC_ENB_AGENT_MAC_PROTO_H__ +#define __LAYER2_MAC_ENB_AGENT_MAC_PROTO_H__ + +#include "enb_agent_defs.h" +#include "header.pb-c.h" +#include "progran.pb-c.h" + +/* + * Default scheduler used by the eNB agent + */ +void schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe, + int *mbsfn_flag, Protocol__ProgranMessage *dl_info); + + +/* + * Data plane function for applying the DL decisions of the scheduler + */ +void apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, + Protocol__ProgranMessage *dl_scheduling_info); + +/* + * Data plane function for applying the UE specific DL decisions of the scheduler + */ +void apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, + uint32_t n_dl_ue_data, const Protocol__PrpDlData **dl_ue_data); + +/* + * Data plane function for filling the DCI structure + */ +void fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, const Protocol__PrpDlDci *dl_dci); + +#endif diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index faf0bf9954..be553c278d 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -36,10 +36,6 @@ #ifndef __LAYER2_MAC_PROTO_H__ #define __LAYER2_MAC_PROTO_H__ -#include "enb_agent_defs.h" -#include "header.pb-c.h" -#include "progran.pb-c.h" - /** \addtogroup _mac * @{ */ @@ -133,9 +129,6 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i */ void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); -//To be used by the agent -void schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe, - int *mbsfn_flag, Protocol__ProgranMessage *dl_info); /** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure. @param Mod_id Module id of UE