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