Commit 0b64cfb9 authored by Cedric Roux's avatar Cedric Roux

commit current status of work

parent 73f92fd9
......@@ -119,6 +119,7 @@ endmacro(add_list_string_option)
####################################################
# compilation flags
#############################################
set(CMAKE_BUILD_TYPE "Debug")
if (CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
......@@ -557,7 +558,7 @@ add_boolean_option(TRACE_RLC_PAYLOAD False "Fatal assert in this case")
add_boolean_option(RLC_STOP_ON_LOST_PDU False "Fatal assert in this case")
add_boolean_option(TRACE_RLC_MUTEX True "TRACE for RLC, possible problem in thread scheduling")
add_boolean_option(TRACE_RLC_AM_BO False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_BO True "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_FREE_SDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_HOLE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_PDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
......@@ -566,7 +567,7 @@ add_boolean_option(TRACE_RLC_AM_RX False "TRACE for RLC AM, TO BE CHANGE
add_boolean_option(TRACE_RLC_AM_RX_DECODE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_TX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_TX_STATUS False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_STATUS_CREATION False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(TRACE_RLC_AM_STATUS_CREATION True "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
add_boolean_option(STOP_ON_IP_TRAFFIC_OVERLOAD False "")
add_boolean_option(TRACE_RLC_UM_DAR False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
......
......@@ -2028,7 +2028,11 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
mod_sym_t **txdataF,
uint32_t subframe)
uint32_t subframe
#if FAPI
, int num_pdcch_symbols_from_fapi
#endif
)
{
uint8_t *e_ptr,num_pdcch_symbols;
......@@ -2078,7 +2082,11 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
break;
}
#if FAPI
num_pdcch_symbols = num_pdcch_symbols_from_fapi;
#else
num_pdcch_symbols = get_num_pdcch_symbols(num_ue_spec_dci+num_common_dci,dci_alloc,frame_parms,subframe);
#endif
// printf("subframe %d in generate_dci_top num_pdcch_symbols = %d, num_dci %d\n",
// subframe,num_pdcch_symbols,num_ue_spec_dci+num_common_dci);
generate_pcfich(num_pdcch_symbols,
......@@ -2349,7 +2357,11 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB,
uint8_t num_ue_spec_dci,
uint8_t num_common_dci,
DCI_ALLOC_t *dci_alloc,
uint8_t subframe)
uint8_t subframe
#if FAPI
, int num_pdcch_symbols_from_fapi
#endif
)
{
int n_dci, n_dci_dl;
uint8_t ue_id;
......@@ -2358,6 +2370,9 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB,
dci_alloc,
&phy_vars_eNB->lte_frame_parms,
subframe);
#if FAPI
num_pdcch_symbols = num_pdcch_symbols_from_fapi;
#endif
eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.cfi=num_pdcch_symbols;
memcpy(phy_vars_eNB->dci_alloc[subframe&1],dci_alloc,sizeof(DCI_ALLOC_t)*(num_ue_spec_dci+num_common_dci));
......
......@@ -1149,13 +1149,21 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
mod_sym_t **txdataF,
uint32_t sub_frame_offset);
uint32_t sub_frame_offset
#if FAPI
, int num_pdcch_symbols_from_fapi
#endif
);
uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB,
uint8_t num_ue_spec_dci,
uint8_t num_common_dci,
DCI_ALLOC_t *dci_alloc,
uint8_t subframe);
uint8_t subframe
#if FAPI
, int num_pdcch_symbols_from_fapi
#endif
);
void generate_64qam_table(void);
......
......@@ -2040,7 +2040,11 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e
AMP,
&phy_vars_eNB->lte_frame_parms,
phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
subframe);
subframe
#if FAPI
, DCI_pdu->num_pdcch_symbols
#endif
);
#ifdef DEBUG_PHY_PROC
// LOG_I(PHY,"[eNB %d] Frame %d, subframe %d: num_pdcch_symbols %d)\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, next_slot>>1,num_pdcch_symbols);
......@@ -2051,7 +2055,11 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
else {
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top_emul\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, subframe);
num_pdcch_symbols = generate_dci_top_emul(phy_vars_eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe);
num_pdcch_symbols = generate_dci_top_emul(phy_vars_eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe
#if FAPI
, DCI_pdu->num_pdcch_symbols
#endif
);
}
#endif
......@@ -2736,6 +2744,11 @@ void process_HARQ_feedback(uint8_t UE_id,
if ((dl_harq_pid[m]<dlsch->Mdlharq) &&
(dlsch_harq_proc->status == ACTIVE)) {
#if FAPI
/* TODO: handle transport block != 0 */
printf("SEND ack %d harq pid %d rnti %d f/sf %d/%d\n", dlsch_ACK[mp], dl_harq_pid[m], dlsch->rnti, frame, subframe);
mac_xface->fapi_dl_ack_nack(dlsch->rnti, dl_harq_pid[m], 0 /* transport block */, dlsch_ACK[mp]);
#endif
// dl_harq_pid of DLSCH is still active
// msg("[PHY] eNB %d Process %d is active (%d)\n",phy_vars_eNB->Mod_id,dl_harq_pid[m],dlsch_ACK[m]);
......@@ -3489,6 +3502,10 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++;
#if FAPI
mac_xface->fapi_ul_ack_nack(frame, subframe, phy_vars_eNB->ulsch_eNB[i]->rnti, 0);
#endif
LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round);
if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) {
......@@ -3648,6 +3665,10 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0;
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors = 0;
#if FAPI
mac_xface->fapi_ul_ack_nack(frame, subframe, phy_vars_eNB->ulsch_eNB[i]->rnti, 1);
#endif
if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) {
#ifdef OPENAIR2
//#ifdef DEBUG_PHY_PROC
......@@ -4240,6 +4261,10 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++;
#if FAPI
mac_xface->fapi_ul_ack_nack(frame, subframe, phy_vars_eNB->ulsch_eNB[i]->rnti, 0);
#endif
} // ulsch in error
else {
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
......@@ -4250,6 +4275,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1;
phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0;
phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors = 0;
#if FAPI
mac_xface->fapi_ul_ack_nack(frame, subframe, phy_vars_eNB->ulsch_eNB[i]->rnti, 1);
#endif
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",
......
......@@ -56,6 +56,10 @@
#include "PMCH-InfoList-r9.h"
#endif
#if FAPI
#include "ff-mac-csched-sap.h"
#endif
/* sec 5.9, 36.321: MAC Reset Procedure */
void ue_mac_reset(module_id_t module_idP,uint8_t eNB_index)
{
......@@ -563,3 +567,61 @@ rrc_get_estimated_ue_distance(
}
#endif
#if FAPI
void rrc_mac_fapi_configure_srb12(int module_id, int CC_id, int rnti)
{
struct CschedLcConfigReqParameters lc;
struct LogicalChannelConfigListElement_s lcs[2];
struct CschedLcConfigCnfParameters lcr;
fapi_interface_t *fapi;
LOG_I(MAC, "eNB %d/%d: FAPI: configure SRB 1 and 2 for UE %x\n", module_id, CC_id, rnti);
fapi = eNB_mac_inst[module_id].fapi;
lc.rnti = rnti;
lc.reconfigureFlag = false;
lc.nr_logicalChannelConfigList = 2;
lc.logicalChannelConfigList = lcs;
lc.nr_vendorSpecificList = 0;
lc.vendorSpecificList = NULL;
/* SRB 1 */
lcs[0].logicalChannelIdentity = 1;
lcs[0].logicalChannelGroup = 0; /* TBC */
lcs[0].direction = DIR_BOTH;
lcs[0].qosBearerType = QBT_NON_GBR;
lcs[0].qci = 5; /* what to put? see 23.203 table 6.1.7 */
/* bitrates not used - we are in non GBR */
/* SRB 2 */
lcs[1].logicalChannelIdentity = 2;
lcs[1].logicalChannelGroup = 0; /* TBC */
lcs[1].direction = DIR_BOTH;
lcs[1].qosBearerType = QBT_NON_GBR;
lcs[1].qci = 5; /* what to put? see 23.203 table 6.1.7 */
/* bitrates not used - we are in non GBR */
CschedLcConfigReq(fapi->sched, &lc);
CschedLcConfigCnf(fapi, &lcr);
if (lcr.rnti != rnti)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.result != ff_SUCCESS)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.nr_logicalChannelIdendity != 2)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
/* libscheduler.a does not set those values as of v7 */
#if 0
if (lcr.logicalChannelIdentity[0] != 1 && lcr.logicalChannelIdentity[0] != 2)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.logicalChannelIdentity[1] != 2 && lcr.logicalChannelIdentity[1] != 1)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.logicalChannelIdentity[0] == lcr.logicalChannelIdentity[1])
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
#endif
}
#endif
......@@ -785,6 +785,10 @@ typedef struct {
int16_t timing_offset;
/// Timeout for RRC connection
int16_t RRC_timer;
#if FAPI
/// UL grant as returned by FAPI scheduler
uint32_t UL_grant;
#endif
} RA_TEMPLATE;
......
......@@ -78,7 +78,781 @@
#if FAPI
/* this structure is used to store downlink ack/nack information
* to be sent to FAPI by SchedDlTriggerReq
*/
/* TODO: lock access to it or not? */
/* TODO: do it per CC */
static struct {
struct {
int rnti;
int harq_pid;
int ack[MAX_TB_LIST];
int ack_count;
} ack[MAX_DL_INFO_LIST];
int count;
} fapi_dl_ack_nack_data;
/* this array is used to store uplink ack/nack information
* to be sent to FAPI by SchedUlTriggerReq
* one element per TTI
*/
/* TODO: do it per CC */
static struct {
struct {
int rnti;
int ack;
int length[MAX_LC_LIST+1];
} ack[MAX_UL_INFO_LIST];
int count;
} fapi_ul_ack_nack_data[10];
/* this function is called by the PHY to signal UE's ACK/NACK */
/* TODO: do it per CC */
void fapi_dl_ack_nack(int rnti, int harq_pid, int transport_block, int ack)
{
int pos = fapi_dl_ack_nack_data.count;
printf("GOT DOWNLINK ack %d for rnti %x harq_pid %d transport_block %d\n", ack, rnti, harq_pid, transport_block);
/* TODO: handle more than 1 TB */
if (transport_block) { printf("%s:%d:%s: TODO: tb != 0\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (pos == MAX_DL_INFO_LIST) {
LOG_E(MAC, "fapi_dl_ack_nack: full!\n");
abort();
}
fapi_dl_ack_nack_data.ack[pos].rnti = rnti;
fapi_dl_ack_nack_data.ack[pos].harq_pid = harq_pid;
fapi_dl_ack_nack_data.ack[pos].ack[0] = ack; /* TODO: use transport_block here */
fapi_dl_ack_nack_data.ack[pos].ack_count = 1; /* TODO: take care of transport block */
fapi_dl_ack_nack_data.count++;
}
/* this function is called by the PHY to inform about correct or wrong
* reception by the eNodeB of an uplink UE transmission
*/
/* TODO: do it per CC */
void fapi_ul_ack_nack(int frame, int subframe, int rnti, int ack)
{
printf("GOT UPLINK ack %d for rnti %x (f/sf %d/%d)\n", ack, rnti, frame, subframe);
int pos = fapi_ul_ack_nack_data[subframe].count;
if (pos == MAX_UL_INFO_LIST) {
LOG_E(MAC, "fapi_ul_ack_nack: full! (f/sf %d/%d)\n", frame, subframe);
abort();
}
fapi_ul_ack_nack_data[subframe].ack[pos].rnti = rnti;
fapi_ul_ack_nack_data[subframe].ack[pos].ack = ack;
/* the values in length are set later in the function fapi_ul_lc_length */
memset(fapi_ul_ack_nack_data[subframe].ack[pos].length, 0, sizeof(int) * MAX_LC_LIST+1);
fapi_ul_ack_nack_data[subframe].count++;
}
/* this function is called by rx_sdu to indicate the number of
* bytes received by the given Logical Channel
*/
void fapi_ul_lc_length(int frame, int subframe, int lcid, int length, int rnti)
{
printf("GOT lcid %d length %d (f/sf %d/%d)\n", lcid, length, frame, subframe);
int pos = fapi_ul_ack_nack_data[subframe].count - 1;
if (pos < 0) { printf("%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
/* TODO: remove this check (and the rnti paramete)? */
if (rnti != fapi_ul_ack_nack_data[subframe].ack[pos].rnti) {
printf("%s:%d:%s: fatal error: LCID %d wrong RNTI %x (expected %x)\n",
__FILE__, __LINE__, __FUNCTION__, lcid,
rnti, fapi_ul_ack_nack_data[subframe].ack[pos].rnti);
abort();
}
if (lcid < 0 || lcid > 3)
{ printf("%s:%d:%s: fatal error: unhandled LCID %d\n", __FILE__, __LINE__, __FUNCTION__, lcid); abort(); }
fapi_ul_ack_nack_data[subframe].ack[pos].length[lcid] = length;
}
static void fapi_convert_dl_1A_5MHz_FDD(struct DlDciListElement_s *dci, DCI_ALLOC_t *a)
{
DCI1A_5MHz_FDD_t *d = (DCI1A_5MHz_FDD_t *)a->dci_pdu;
if (dci->nr_of_tbs != 1) { printf("%s:%d: TODO\n", __FUNCTION__, __LINE__); exit(1); }
d->type = 1; /* type = 0 => DCI Format 0, type = 1 => DCI Format 1A */
d->vrb_type = dci->vrbFormat == VRB_LOCALIZED ? 0 :
dci->vrbFormat == VRB_DISTRIBUTED ? 1 :
(printf("%s:%d: error\n", __FUNCTION__, __LINE__), abort(), 0);
d->rballoc = dci->rbBitmap;
d->mcs = dci->mcs[0]; /* TODO: take care of transport block index */
d->harq_pid = dci->harqProcess;
d->ndi = dci->ndi[0]; /* TODO: take care of transport block index */
d->rv = dci->rv[0]; /* TODO: take care of transport block index */
d->TPC = dci->tpc;
d->padding = 0;
a->dci_length = sizeof_DCI1A_5MHz_FDD_t;
a->format = format1A;
}
static uint32_t revert(uint32_t x, int len)
{
int i;
int ret = 0;
for (i = 0; i < len; i++) {
ret <<= 1;
ret |= x & 1;
x >>= 1;
}
return ret;
}
static void fapi_convert_dl_1_5MHz_FDD(struct DlDciListElement_s *dci, DCI_ALLOC_t *a)
{
DCI1_5MHz_FDD_t *d = (DCI1_5MHz_FDD_t *)a->dci_pdu;
if (dci->nr_of_tbs != 1) { printf("%s:%d: TODO\n", __FUNCTION__, __LINE__); exit(1); }
d->rah = dci->resAlloc == 0 ? 0 :
dci->resAlloc == 1 ? 1 :
(printf("%s:%d: error\n", __FUNCTION__, __LINE__), abort(), 0);
d->rballoc = revert(dci->rbBitmap, 13);
d->mcs = dci->mcs[0]; /* TODO: take care of transport block index */
d->harq_pid = dci->harqProcess;
d->ndi = dci->ndi[0]; /* TODO: take care of transport block index */
d->rv = dci->rv[0]; /* TODO: take care of transport block index */
d->TPC = dci->tpc;
d->dummy = 0;
a->dci_length = sizeof_DCI1_5MHz_FDD_t;
a->format = format1;
}
static void fapi_convert_dl_dci(struct DlDciListElement_s *dci, DCI_ALLOC_t *a)
{
/* 5MHz FDD supposed, not checked */
switch (dci->format) {
case ONE_A:
fapi_convert_dl_1A_5MHz_FDD(dci, a);
break;
case ONE:
fapi_convert_dl_1_5MHz_FDD(dci, a);
break;
default: printf("%s:%d: TODO\n", __FUNCTION__, __LINE__); abort();
}
a->L = dci->aggrLevel == 1 ? 0 :
dci->aggrLevel == 2 ? 1 :
dci->aggrLevel == 4 ? 2 :
dci->aggrLevel == 8 ? 3 :
(printf("%s:%d: error\n", __FUNCTION__, __LINE__), abort(), 0);
a->firstCCE = dci->cceIndex;
a->ra_flag = 0; /* TODO: set to 1 only by fapi_schedule_RAR, is it ok? */
a->rnti = dci->rnti;
}
static void fapi_convert_ul_5MHz_FDD(module_id_t module_idP, int CC_id,
struct UlDciListElement_s *dci, DCI_ALLOC_t *a)
{
DCI0_5MHz_FDD_t *d = (DCI0_5MHz_FDD_t *)a->dci_pdu;
d->type = 0; /* type = 0 => DCI Format 0, type = 1 => DCI Format 1A */
d->hopping = dci->hopping;
d->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL, dci->rbStart, dci->rbLen);
d->mcs = dci->mcs;
d->ndi = dci->ndi;
d->TPC = dci->tpc;
d->cshift = dci->n2Dmrs;
d->cqi_req = dci->cqiRequest;
d->padding = 0;
a->dci_length = sizeof_DCI0_5MHz_FDD_t;
a->format = format0;
}
static void fapi_convert_ul_dci(module_id_t module_idP, int CC_id,
struct UlDciListElement_s *dci, DCI_ALLOC_t *a)
{
/* 5MHz FDD supposed, not checked */
fapi_convert_ul_5MHz_FDD(module_idP, CC_id, dci, a);
a->L = dci->aggrLevel == 1 ? 0 :
dci->aggrLevel == 2 ? 1 :
dci->aggrLevel == 4 ? 2 :
dci->aggrLevel == 8 ? 3 :
(printf("%s:%d: error\n", __FUNCTION__, __LINE__), abort(), 0);
a->firstCCE = dci->cceIndex;
a->ra_flag = 0;
a->rnti = dci->rnti;
}
/* index 0 for SIB1, 1 for SIB23 */
static void fapi_schedule_SI(module_id_t module_idP, int CC_id, frame_t frameP,
sub_frame_t subframeP, uint8_t index, struct DlDciListElement_s *dci)
{
eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP];
DCI_PDU *dci_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
DCI_ALLOC_t *a = &dci_pdu->dci_alloc[dci_pdu->Num_common_dci];
int bcch_sdu_length;
if (dci_pdu->Num_common_dci >= NUM_DCI_MAX) { printf("%s:%d:%s: too much DCIs\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
/* we can increment Num_common_dci or Num_ue_spec_dci, there is no difference */
dci_pdu->Num_common_dci++;
fapi_convert_dl_dci(dci, a);
/* bug in libscheduler.a? rnti is 0 */
a->rnti = SI_RNTI;
if (index == 0)
bcch_sdu_length = mac_rrc_get_SIB1(module_idP, CC_id, &eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
else if (index == 1)
bcch_sdu_length = mac_rrc_get_SIB23(module_idP, CC_id, &eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
else { printf("%s:%d: fatal error\n", __FUNCTION__, __LINE__); abort(); }
eNB->eNB_stats[CC_id].total_num_bcch_pdu+=1;
eNB->eNB_stats[CC_id].bcch_buffer=bcch_sdu_length;
eNB->eNB_stats[CC_id].total_bcch_buffer+=bcch_sdu_length;
eNB->eNB_stats[CC_id].bcch_mcs=dci->mcs[0]; /* TODO: take care of transport block index */
}
static void fapi_schedule_RAR(int module_idP, int CC_id, frame_t frameP,
sub_frame_t subframeP, uint16_t rnti, uint32_t grant,
struct DlDciListElement_s *dci)
{
eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP];
DCI_PDU *dci_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
DCI_ALLOC_t *a = &dci_pdu->dci_alloc[dci_pdu->Num_common_dci];
RA_TEMPLATE *RA_template = NULL;
int i;
if (dci_pdu->Num_common_dci >= NUM_DCI_MAX) { printf("%s:%d:%s: too much DCIs\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
for (i = 0; i < NB_RA_PROC_MAX; i++) {
RA_template = (RA_TEMPLATE *)&eNB->common_channels[CC_id].RA_template[i];
if (RA_template->RA_active != TRUE) continue;
if (RA_template->rnti != rnti) continue;
break;
}
if (i == NB_RA_PROC_MAX) { printf("%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
RA_template->generate_rar = 1;
RA_template->UL_grant = grant;
/* we can increment Num_common_dci or Num_ue_spec_dci, there is no difference */
dci_pdu->Num_common_dci++;
fapi_convert_dl_dci(dci, a);
a->ra_flag = 1;
/* bug in libscheduler.a? rnti is 0 */
a->rnti = RA_template->RA_rnti;
}
static void fapi_schedule_RA_Msg4(int module_idP, int CC_id, int RA,
int frameP, int subframeP, struct DlDciListElement_s *dci, int pdu_maxsize)
{
int UE_id;
int rrc_sdu_length;
eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP];
RA_TEMPLATE *RA_template;
int msg4_header_length;
int msg4_padding, msg4_post_padding;
int TBsize;
DCI_PDU *dci_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
DCI_ALLOC_t *a = &dci_pdu->dci_alloc[dci_pdu->Num_common_dci];
int offset;
unsigned char lcid;
if (dci_pdu->Num_common_dci >= NUM_DCI_MAX) { printf("%s:%d:%s: too much DCIs\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
RA_template = (RA_TEMPLATE *)&eNB->common_channels[CC_id].RA_template[RA];
UE_id = find_UE_id(module_idP,RA_template->rnti);
rrc_sdu_length = mac_rrc_data_req(module_idP,
CC_id,
frameP,
CCCH,
1, // 1 transport block
&eNB->common_channels[CC_id].CCCH_pdu.payload[0],
ENB_FLAG_YES,
module_idP,
0); // not used in this case
if (rrc_sdu_length <= 0) {
LOG_E(MAC, "fapi_schedule_RA_Msg4: rrc_sdu_length (%d) is not > 0\n", rrc_sdu_length);
abort();
}
if (rrc_sdu_length > pdu_maxsize) {
LOG_E(MAC, "fapi_schedule_RA_Msg4: rrc_sdu_length (%d) > pdu_maxsize (%d)\n", rrc_sdu_length, pdu_maxsize);
abort();
}
msg4_header_length = 1+6+1; // CR header, CR CE, SDU header
TBsize = dci->tbsSize[CC_id] / 8;
if ((TBsize - rrc_sdu_length - msg4_header_length) <= 2) {
msg4_padding = TBsize - rrc_sdu_length - msg4_header_length;
msg4_post_padding = 0;
} else {
msg4_padding = 0;
msg4_post_padding = TBsize - rrc_sdu_length - msg4_header_length -1;
}
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n",
module_idP, CC_id, frameP, subframeP, TBsize, rrc_sdu_length, msg4_header_length, msg4_padding, msg4_post_padding);
lcid = 0;
offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0],
1, //num_sdus
(unsigned short*)&rrc_sdu_length, //
&lcid, // sdu_lcid
255, // no drx
0, // no timing advance
RA_template->cont_res_id, // contention res id
msg4_padding, // no padding
msg4_post_padding);
memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],
&eNB->common_channels[CC_id].CCCH_pdu.payload[0],
rrc_sdu_length);
RA_template->generate_Msg4=0;
RA_template->wait_ack_Msg4=1;
RA_template->RA_active = FALSE;
/* we can increment Num_common_dci or Num_ue_spec_dci, there is no difference */
dci_pdu->Num_common_dci++;
fapi_convert_dl_dci(dci, a);
}
/* returns 1 if the given LCID has a MAC header of fixed size (for DL-SCH) */
static int fixed_size(int lcid)
{
/* see 36.321, especially table 6.2.1-1 (rel. 10 is used here) */
return lcid >= 27;
}
/* TODO: deal with more than one transport block */
static void fapi_schedule_ue(int module_id, int CC_id, int frame, int subframe, struct BuildDataListElement_s *d)
{
int header_size;
int payload_size;
int padding_size;
int tbs;
int i;
mac_rlc_status_resp_t rlc_status;
unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
int dlsch_filled = 0;
int output_length;
int UE_id;
eNB_MAC_INST *eNB = &eNB_mac_inst[module_id];
UE_list_t *UE_list = &eNB->UE_list;
int num_sdus;
unsigned short sdu_lengths[MAX_RLC_PDU_LIST];
unsigned char sdu_lcids[MAX_RLC_PDU_LIST];
int offset;
DCI_PDU *dci_pdu = &eNB->common_channels[CC_id].DCI_pdu;
DCI_ALLOC_t *a = &dci_pdu->dci_alloc[dci_pdu->Num_common_dci];
/* generate DCI */
if (dci_pdu->Num_common_dci >= NUM_DCI_MAX) { printf("%s:%d:%s: too much DCIs\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
/* we can increment Num_common_dci or Num_ue_spec_dci, there is no difference */
dci_pdu->Num_common_dci++;
fapi_convert_dl_dci(&d->dci, a);
printf("RUN fapi_schedule_ue\n");
if (d->nr_rlcPDU_List[0] != 1) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (d->nr_rlcPDU_List[1] != 0) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (d->ceBitmap[0]) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (d->ceBitmap[1]) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (d->servCellIndex != 0) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
tbs = d->dci.tbsSize[0] / 8;
num_sdus = 0;
/* get DLSCH buffer and adjust size according to what RLC says */
for (i = 0; i < d->nr_rlcPDU_List[0]; i++) {
rlc_status = mac_rlc_status_ind(
module_id,
d->rnti,
module_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
d->rlcPduList[0][i].logicalChannelIdentity,
d->rlcPduList[0][i].size);
printf("RLC_SIZE in fapi_schedule_ue %d (asked %d) lcid %d rnti %x f/sf %d/%d\n", rlc_status.bytes_in_buffer, d->rlcPduList[0][i].size, d->rlcPduList[0][i].logicalChannelIdentity, d->rnti, frame, subframe);
if (rlc_status.bytes_in_buffer <= 0) { printf("%s:%d:%s: error\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (rlc_status.bytes_in_buffer > d->rlcPduList[0][i].size) abort(); /* that can't happen */
if (dlsch_filled + d->rlcPduList[0][i].size > MAX_DLSCH_PAYLOAD_BYTES) {
printf("dlsch buffer filled too much\n");
abort();
}
output_length = mac_rlc_data_req(
module_id,
d->rnti,
module_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
d->rlcPduList[0][i].logicalChannelIdentity,
(char *)&dlsch_buffer[dlsch_filled]);
if (output_length <= 0 || output_length > d->rlcPduList[0][i].size) abort();
d->rlcPduList[0][i].size = output_length;
dlsch_filled += output_length;
sdu_lengths[num_sdus] = output_length;
sdu_lcids[num_sdus] = d->rlcPduList[0][i].logicalChannelIdentity;
num_sdus++;
printf("FILLED %d bytes\n", output_length);
}
/* get size of header and payload */
header_size = 0;
payload_size = 0;
if (d->nr_rlcPDU_List[0]) {
header_size++;
payload_size += d->rlcPduList[0][0].size;
}
for (i = 1; i < d->nr_rlcPDU_List[0]; i++) {
if (!fixed_size(d->rlcPduList[0][i-1].logicalChannelIdentity)) {
header_size++;
if (d->rlcPduList[0][i-1].size >= 128)
header_size++;
}
header_size++;
payload_size += d->rlcPduList[0][i].size;
}
padding_size = tbs - header_size - payload_size;
printf("PADDING_SIZE %d\n", padding_size);
UE_id = find_UE_id(module_id, d->rnti);
/* generate dlsch header */
offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
num_sdus,
sdu_lengths,
sdu_lcids,
255, // no drx
0, /* TODO: timing advance */
NULL, // contention res id
padding_size <= 2 ? padding_size : 0,
padding_size > 2 ? padding_size : 0);
/* fill payload */
memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, dlsch_filled);
add_ue_dlsch_info(module_id,
CC_id,
UE_id,
subframe,
/* S_DL_SCHEDULED */ S_DL_WAITING);
}
static void fapi_schedule_uplink(int module_idP, int CC_id, struct UlDciListElement_s *dci)
{
DCI_PDU *dci_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
DCI_ALLOC_t *a = &dci_pdu->dci_alloc[dci_pdu->Num_common_dci];
if (dci_pdu->Num_common_dci >= NUM_DCI_MAX) { printf("%s:%d:%s: too much DCIs\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
/* we can increment Num_common_dci or Num_ue_spec_dci, there is no difference */
dci_pdu->Num_common_dci++;
fapi_convert_ul_dci(module_idP, CC_id, dci, a);
}
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) //, int calibration_flag) {
{
int CC_id;
int i, j;
DCI_PDU *DCI_pdu[MAX_NUM_CCs];
int mbsfn_status[MAX_NUM_CCs];
UE_list_t *UE_list = &eNB_mac_inst[module_idP].UE_list;
fapi_interface_t *fapi;
struct SchedDlTriggerReqParameters dlreq;
struct SchedDlConfigIndParameters dlind;
struct DlInfoListElement_s dlinfo[MAX_DL_INFO_LIST];
protocol_ctxt_t ctxt;
int UE_id;
eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP];
struct SchedUlTriggerReqParameters ulreq;
struct SchedUlConfigIndParameters ulind;
struct UlInfoListElement_s ulinfo[MAX_UL_INFO_LIST];
int ulsf;
#if defined(ENABLE_ITTI)
while (1) {
// Checks if a message has been sent to MAC sub-task
MessageDef *msg_p;
int result;
itti_poll_msg (TASK_MAC_ENB, &msg_p);
if (msg_p == NULL) break;
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
#endif
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
DCI_pdu[CC_id] = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
DCI_pdu[CC_id]->nCCE=0;
DCI_pdu[CC_id]->num_pdcch_symbols=1;
mbsfn_status[CC_id]=0;
// clear vrb_map
memset(eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map,0,100);
}
// refresh UE list based on UEs dropped by PHY in previous subframe
i = UE_list->head;
while (i>=0) {
int rnti, next_i;
rnti = UE_RNTI(module_idP, i);
CC_id = UE_PCCID(module_idP, i);
next_i= UE_list->next[i];
if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
mac_remove_ue(module_idP, i, frameP, subframeP);
}
i = next_i;
}
// clear DCI and BCCH contents before scheduling
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
DCI_pdu[CC_id]->Num_common_dci = 0;
DCI_pdu[CC_id]->Num_ue_spec_dci = 0;
#ifdef Rel10
eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active = 0;
#endif
eNB_mac_inst[module_idP].frame = frameP;
eNB_mac_inst[module_idP].subframe = subframeP;
}
/* run PDCP */
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, 0, module_idP);
pdcp_run(&ctxt);
// check HO
rrc_rx_tx(&ctxt,
0, // eNB index, unused in eNB
CC_id);
/* MBMS thing not done */
mbsfn_status[0]++; /* avoid gcc warning */
/* let's FAPI schedule! */
fapi = eNB_mac_inst[module_idP].fapi;
/*************************************************/
/* downlink scheduling */
/*************************************************/
/* check RA - is there one in generate_Msg4 mode with some CCCH data ready in the RRC Srb0? */
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
for (i=0; i < NB_RA_PROC_MAX; i++) {
if (eNB->common_channels[CC_id].RA_template[i].RA_active == TRUE &&
eNB->common_channels[CC_id].RA_template[i].generate_Msg4 == 1 &&
mac_rrc_get_ccch_size(module_idP, CC_id) > 0) {
struct SchedDlRlcBufferReqParameters rlc;
memset(&rlc, 0, sizeof(rlc));
rlc.rnti = eNB->common_channels[CC_id].RA_template[i].rnti;
rlc.logicalChannelIdentity = CCCH;
rlc.rlcTransmissionQueueSize = mac_rrc_get_ccch_size(module_idP, CC_id);
LOG_I(MAC, "calling SchedDlRlcBufferReq on CCCH rnti %x queue_size %d\n", rlc.rnti, rlc.rlcTransmissionQueueSize);
SchedDlRlcBufferReq(fapi->sched, &rlc);
/* let's report only once, so put generate_Msg4 to 2
* (we will generate later on, when FAPI tells us to do so)
*/
eNB->common_channels[CC_id].RA_template[i].generate_Msg4 = 2;
}
}
}
/* update RLC buffers status in the scheduler */
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
struct SchedDlRlcBufferReqParameters rlc;
mac_rlc_status_resp_t rlc_status;
memset(&rlc, 0, sizeof(rlc));
rlc.rnti = UE_RNTI(module_idP, UE_id);
/* this code is wrong: we should loop over all configured RaB */
/* DCCH (srb 1, lcid 1) */
rlc_status = mac_rlc_get_buffer_occupancy(module_idP, rlc.rnti, frameP, DCCH);
rlc.logicalChannelIdentity = DCCH;
rlc.rlcTransmissionQueueSize = rlc_status.bytes_in_buffer;
LOG_I(MAC, "calling SchedDlRlcBufferReq on DCCH rnti %x queue_size %d\n", rlc.rnti, rlc_status.bytes_in_buffer);
SchedDlRlcBufferReq(fapi->sched, &rlc);
printf("BUF %d\n", rlc_status.bytes_in_buffer);
/* DCCH+1 (srb 2, lcid 2) */
rlc_status = mac_rlc_get_buffer_occupancy(module_idP, rlc.rnti, frameP, DCCH+1);
rlc.logicalChannelIdentity = DCCH+1;
rlc.rlcTransmissionQueueSize = rlc_status.bytes_in_buffer;
LOG_I(MAC, "calling SchedDlRlcBufferReq on DCCH+1 rnti %x queue_size %d\n", rlc.rnti, rlc_status.bytes_in_buffer);
SchedDlRlcBufferReq(fapi->sched, &rlc);
printf("BUF %d\n", rlc_status.bytes_in_buffer);
/* DTCH (drb 1, lcid 3) */
rlc_status = mac_rlc_get_buffer_occupancy(module_idP, rlc.rnti, frameP, DTCH);
rlc.logicalChannelIdentity = DTCH;
rlc.rlcTransmissionQueueSize = rlc_status.bytes_in_buffer;
LOG_I(MAC, "calling SchedDlRlcBufferReq on DTCH rnti %x queue_size %d\n", rlc.rnti, rlc_status.bytes_in_buffer);
SchedDlRlcBufferReq(fapi->sched, &rlc);
printf("BUF %d\n", rlc_status.bytes_in_buffer);
}
dlreq.sfnSf = frameP * 16 + subframeP;
dlreq.nr_dlInfoList = 0;
dlreq.dlInfoList = NULL;
dlreq.nr_vendorSpecificList = 0;
dlreq.vendorSpecificList = NULL;
/* fill harq feedback data */
/* TODO: deal with more than one TB */
for (i = 0; i < fapi_dl_ack_nack_data.count; i++) {
dlinfo[i].rnti = fapi_dl_ack_nack_data.ack[i].rnti;
dlinfo[i].harqProcessId = fapi_dl_ack_nack_data.ack[i].harq_pid;
dlinfo[i].nr_harqStatus = 1; /* TODO: deal with more than 1 TB */
dlinfo[i].harqStatus[0] = fapi_dl_ack_nack_data.ack[i].ack[0]; /* TODO: more than 1 TB */
dlinfo[i].servCellIndex = 0; /* TODO: get real value for the servCellIndex */
printf("FILL feedback f/sf %d/%d rnti %x harq %d ack %d\n", frameP, subframeP, dlinfo[i].rnti, dlinfo[i].harqProcessId, dlinfo[i].harqStatus[0]);
}
if (fapi_dl_ack_nack_data.count) {
dlreq.nr_dlInfoList = fapi_dl_ack_nack_data.count;
dlreq.dlInfoList = dlinfo;
}
fapi_dl_ack_nack_data.count = 0;
LOG_I(MAC, "calling SchedDlTriggerReq\n");
SchedDlTriggerReq(fapi->sched, &dlreq);
LOG_I(MAC, "calling SchedDlConfigInd\n");
SchedDlConfigInd(fapi, &dlind);
LOG_I(MAC, "SchedDlConfigInd returns dlind.nr_buildDataList %d f/sf %d/%d\n", dlind.nr_buildDataList, frameP, subframeP);
LOG_I(MAC, "SchedDlConfigInd returns dlind.nr_buildRARList %d f/sf %d/%d\n", dlind.nr_buildRARList, frameP, subframeP);
LOG_I(MAC, "SchedDlConfigInd returns dlind.nr_buildBroadcastList %d f/sf %d/%d\n", dlind.nr_buildBroadcastList, frameP, subframeP);
/* TODO: rewrite. All should go into fapi_schedule_ue where special cases should be handled */
for (i = 0; i < dlind.nr_buildDataList; i++) {
if (dlind.buildDataList[i].ceBitmap[1] != 0 || dlind.buildDataList[i].nr_rlcPDU_List[1] != 0) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (dlind.buildDataList[i].nr_rlcPDU_List[0] != 1) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
switch (dlind.buildDataList[i].rlcPduList[0][0].logicalChannelIdentity) {
case 0: /* CCCH */
/* TODO: get the right CC_id from servCellIndex, depending on the UE rnti/pcell/scell settings */
CC_id = dlind.buildDataList[i].servCellIndex;
/* look for an active RA with generate_Msg4 == 2 for this rnti */
for (j=0; j < NB_RA_PROC_MAX; j++) {
if (eNB->common_channels[CC_id].RA_template[j].RA_active == TRUE &&
eNB->common_channels[CC_id].RA_template[j].generate_Msg4 == 2 &&
eNB->common_channels[CC_id].RA_template[j].rnti == dlind.buildDataList[i].rnti) {
if (dlind.buildDataList[i].ceBitmap[CC_id] != ff_CR) { printf("%s:%d:%s: TODO)\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
fapi_schedule_RA_Msg4(module_idP, CC_id, j, frameP, subframeP,
&dlind.buildDataList[i].dci, dlind.buildDataList[i].rlcPduList[0][0].size);
break;
}
}
if (j == NB_RA_PROC_MAX) { printf("%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
break;
case 1: /* DCCH (SRB1) */
case 2: /* DCCH+1 (SRB2) */
case 3: /* DTCH (DRB1) */
/* TODO: get the correct CC_id from servCellIndex */
fapi_schedule_ue(module_idP, dlind.buildDataList[i].servCellIndex /* CC_id */, frameP, subframeP, &dlind.buildDataList[i]);
break;
default: printf("%s:%d:%s: bad channel ID (%d)\n", __FILE__, __LINE__, __FUNCTION__, dlind.buildDataList[i].rlcPduList[0][0].logicalChannelIdentity); abort();
}
}
if (dlind.nr_buildRARList) {
if (dlind.nr_buildRARList != 1) { printf("%s:%d: more than 1 RAR, todo\n", __FUNCTION__, __LINE__); exit(0); }
if (dlind.buildRarList[0].carrierIndex != 0) { printf("%s:%d: 2nd CC: todo properly\n", __FUNCTION__, __LINE__); exit(0); }
/* force bit 0 of grant to 0
* according to 36.213 6.2 the value
* is reserved but openair needs it to be 0
* this is for contention-based RA
* maybe we will need to review that if/when we do contention-free RA
*/
dlind.buildRarList[0].grant &= ~1;
fapi_schedule_RAR(module_idP, dlind.buildRarList[0].carrierIndex, frameP, subframeP,
dlind.buildRarList[0].rnti, dlind.buildRarList[0].grant, &dlind.buildRarList[0].dci);
}
if (dlind.nr_buildBroadcastList) {
if (dlind.nr_buildBroadcastList != 1) { printf("%s:%d: more than 1 broadcast SI, todo\n", __FUNCTION__, __LINE__); exit(0); }
if (dlind.buildBroadcastList[0].type == ff_PCCH) { printf("%s:%d: PCCH: todo\n", __FUNCTION__, __LINE__); exit(0); }
if (dlind.buildBroadcastList[0].carrierIndex != 0) { printf("%s:%d: 2nd CC: todo properly\n", __FUNCTION__, __LINE__); exit(0); }
fapi_schedule_SI(module_idP, dlind.buildBroadcastList[0].carrierIndex, frameP, subframeP,
dlind.buildBroadcastList[0].index,
&dlind.buildBroadcastList[0].dci);
}
/* TODO: do it correctly */
if (dlind.nr_ofdmSymbolsCount != 0) {
if (dlind.nr_ofdmSymbolsCount != 1) { printf("%s:%d:%s: what to do?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
if (dlind.nrOfPdcchOfdmSymbols[CC_id] != NULL) {
int cc = dlind.nrOfPdcchOfdmSymbols[CC_id]->carrierIndex;
DCI_pdu[cc]->num_pdcch_symbols = dlind.nrOfPdcchOfdmSymbols[CC_id]->pdcchOfdmSymbolCount;
}
}
}
#if 0
// Allocate CCEs for good after scheduling is done
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++)
allocate_CCEs(module_idP,CC_id,subframeP,0);
#endif
/*************************************************/
/* uplink scheduling */
/*************************************************/
ulreq.sfnSf = frameP * 16 + subframeP;
ulreq.nr_ulInfoList = 0;
ulreq.ulInfoList = NULL;
ulreq.nr_vendorSpecificList = 0;
ulreq.vendorSpecificList = NULL;
/* fill ulInfoList */
ulsf = (subframeP + 6) % 10;
if (fapi_ul_ack_nack_data[ulsf].count) {
ulreq.nr_ulInfoList = fapi_ul_ack_nack_data[ulsf].count;
ulreq.ulInfoList = ulinfo;
for (i = 0; i < ulreq.nr_ulInfoList; i++) {
printf("MAC to FAPI uplink acknack to send to ue %x ack %d\n", fapi_ul_ack_nack_data[ulsf].ack[i].rnti, fapi_ul_ack_nack_data[ulsf].ack[i].ack);
ulinfo[i].rnti = fapi_ul_ack_nack_data[ulsf].ack[i].rnti;
ulinfo[i].receptionStatus = fapi_ul_ack_nack_data[ulsf].ack[i].ack == 1 ? Ok : NotOk;
ulinfo[i].tpc = 0; /* TODO */
ulinfo[i].servCellIndex = 0; /* TODO: get correct value */
for (j = 0; j < MAX_LC_LIST+1; j++)
ulinfo[i].ulReception[j] = fapi_ul_ack_nack_data[ulsf].ack[i].length[j];
}
}
LOG_I(MAC, "calling SchedUlTriggerReq\n");
SchedUlTriggerReq(fapi->sched, &ulreq);
LOG_I(MAC, "calling SchedUlConfigInd\n");
SchedUlConfigInd(fapi, &ulind);
printf("yo nr_dclList %d nr_phichList %d\n", ulind.nr_dciList, ulind.nr_phichList);
for (i = 0; i < ulind.nr_dciList; i++) {
/* TODO: get the right CC_id from servCellIndex, depending on the UE rnti/pcell/scell settings */
CC_id = ulind.dciList[i].servCellIndex;
printf("FAPI to MAC schedule uplink ue %x ndi %d (fsf %d %d)\n", ulind.dciList[i].rnti, ulind.dciList[i].ndi, frameP, subframeP);
fapi_schedule_uplink(module_idP, CC_id, &ulind.dciList[i]);
}
}
#else /* FAPI */
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) //, int calibration_flag) {
{
......@@ -551,5 +1325,4 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
#endif /* FAPI */
......@@ -68,6 +68,9 @@
#include "SIMULATION/TOOLS/defs.h" // for taus
#if FAPI
#include "ff-mac-csched-sap.h"
#endif
void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,unsigned char Msg3_subframe)
{
......@@ -730,6 +733,81 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
stop_meas(&eNB->schedule_ra);
}
#if FAPI
void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframeP,
uint8_t f_id)
{
fapi_interface_t *fapi = eNB_mac_inst[module_idP].fapi;
struct SchedDlRachInfoReqParameters p;
struct RachListElement_s r;
int i;
RA_TEMPLATE *RA_template = &eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[0];
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
p.sfnSf = frameP * 16 + subframeP;
p.nrrachList = 1;
p.rachList = &r;
p.nr_vendorSpecificList = 0;
p.vendorSpecificList = NULL;
/* we should have a proper way for this rnti */
r.rnti = taus(); LOG_W(MAC, "%s:%s:%d: C-RNTI generation is wrong (rnti %d|0x%x)\n", __FILE__, __FUNCTION__, __LINE__, r.rnti, r.rnti);
r.estimatedSize = 144; LOG_W(MAC, "initiate_ra_proc: estimated minimum size of first UL message set to 144 bits, what value put?\n");
r.carrierIndex = CC_id;
for (i=0; i<NB_RA_PROC_MAX; i++) {
if (RA_template[i].RA_active==FALSE) {
RA_template[i].RA_active=TRUE;
RA_template[i].generate_rar=0;
RA_template[i].generate_Msg4=0;
RA_template[i].wait_ack_Msg4=0;
RA_template[i].timing_offset=timing_offset;
RA_template[i].rnti = r.rnti;
RA_template[i].RA_rnti = 1+subframeP+(10*f_id);
RA_template[i].preamble_index = preamble_index;
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n",
module_idP,CC_id,frameP,i,RA_template[i].rnti,
RA_template[i].RA_active);
break;
}
}
if (i == NB_RA_PROC_MAX) { printf("%s:%d:%s: handle this case\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
LOG_I(MAC, "calling SchedDlRachInfoReq\n");
SchedDlRachInfoReq(fapi->sched, &p);
#if 0
while (1) {
struct SchedDlTriggerReqParameters req;
struct SchedDlConfigIndParameters ind;
req.sfnSf = frameP * 16 + subframeP;
req.nr_dlInfoList = 0;
req.dlInfoList = NULL;
req.nr_vendorSpecificList = 0;
req.vendorSpecificList = NULL;
LOG_I(MAC, "calling SchedDlTriggerReq\n");
SchedDlTriggerReq(fapi->sched, &req);
LOG_I(MAC, "calling SchedDlConfigInd\n");
SchedDlConfigInd(fapi, &ind);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildDataList %d f/sf %d/%d\n", ind.nr_buildDataList, frameP, subframeP);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildRARList %d f/sf %d/%d\n", ind.nr_buildRARList, frameP, subframeP);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildBroadcastList %d f/sf %d/%d\n", ind.nr_buildBroadcastList, frameP, subframeP);
subframeP++; if (subframeP == 10) { frameP++; subframeP = 0; } if (frameP >= 1024) frameP = 0;
if (ind.nr_buildRARList) {
printf("yo\n");
}
if (ind.nr_buildBroadcastList) {
printf("yu\n");
}
}
#endif
}
#else /* FAPI */
void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframeP,
uint8_t f_id)
{
......@@ -759,6 +837,8 @@ void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t
}
}
#endif /* FAPI */
void cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, rnti_t rnti)
{
unsigned char i;
......
......@@ -447,6 +447,30 @@ schedule_ue_spec(
void *DLSCH_dci;
DCI_PDU *DCI_pdu = &eNB->common_channels[0 /* CC_id */].DCI_pdu;
int loop = 10 * 20;
while (loop) {
req.sfnSf = frameP * 16 + subframeP;
req.nr_dlInfoList = 0;
req.dlInfoList = NULL;
req.nr_vendorSpecificList = 0;
req.vendorSpecificList = NULL;
LOG_I(MAC, "calling SchedDlTriggerReq\n");
SchedDlTriggerReq(fapi->sched, &req);
LOG_I(MAC, "calling SchedDlConfigInd\n");
SchedDlConfigInd(fapi, &ind);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildDataList %d\n", ind.nr_buildDataList);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildRARList %d\n", ind.nr_buildRARList);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildBroadcastList %d\n", ind.nr_buildBroadcastList);
subframeP++;
if (subframeP == 10) {
subframeP = 0;
frameP++;
if (frameP == 1024) frameP = 0;
}
loop--;
}
exit(0);
/* let's only schedule subframe 2 for the moment */
if (subframeP != 2) return;
......@@ -503,6 +527,8 @@ schedule_ue_spec(
LOG_I(MAC, "calling SchedDlConfigInd\n");
SchedDlConfigInd(fapi, &ind);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildDataList %d\n", ind.nr_buildDataList);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildRARList %d\n", ind.nr_buildRARList);
LOG_I(MAC, "SchedDlConfigInd returns ind.nr_buildBroadcastList %d\n", ind.nr_buildBroadcastList);
if (ind.nr_buildDataList == 0) return;
......
......@@ -244,6 +244,10 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
{
int UE_id;
int j;
#if FAPI
struct CschedUeConfigReqParameters p;
struct CschedUeConfigCnfParameters r;
#endif
UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
......@@ -278,6 +282,56 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
dump_ue_list(UE_list,0);
#if FAPI
LOG_W(MAC, "%s:%d:%s: set correct values in CschedUeConfigReqParameters\n", __FILE__, __LINE__, __FUNCTION__);
p.rnti = rntiP;
p.reconfigureFlag = false;
p.drxConfigPresent = false;
p.timeAlignmentTimer = 0; /* TBC */
p.measGapConfigPattern = OFF; /* TBC */
p.spsConfigPresent = false;
p.srConfigPresent = false; /* TODO? */
p.cqiConfigPresent = false; /* TODO? */
p.transmissionMode = 1; /* get real one */
p.ueAggregatedMaximumBitrateUl = 900000000L; /* TODO */
p.ueAggregatedMaximumBitrateDl = 900000000L; /* TODO */
/* initial UE capabilities - let's pretend to be cat3 */
p.ueCapabilities.halfDuplex = false;
p.ueCapabilities.intraSfHopping = false;
p.ueCapabilities.type2Sb1 = false;
p.ueCapabilities.ueCategory = 3;
p.ueCapabilities.resAllocType1 = true; /* TBC */
p.ueTransmitAntennaSelection = noneloop; /* TBC */
p.ttiBundling = false; /* TBC */
p.maxHarqTx = 8; /* get real one */
p.betaOffsetAckIndex = 0; /* TODO */
p.betaOffsetRiIndex = 0; /* TODO */
p.betaOffsetCqiIndex = 0; /* TODO */
p.ackNackSrsSimultaneousTransmission = false; /* get real one */
p.simultaneousAckNackAndCqi = true; /* get real one */
p.aperiodicCqiRepMode = ff_rm30; /* get real one */
p.tddAckNackFeedbackMode = ff_bundling; /* get real one */
p.ackNackRepetitionFactor = 0; /* get real one */
p.extendedBSRSizes = false;
p.caSupport = false;
p.crossCarrierSchedSupport = false;
p.pcellCarrierIndex = 0; /* TBC */
p.nr_scells = 0;
p.scellConfigList[0] = NULL;
p.scellDeactivationTimer = 0;
LOG_I(MAC, "calling CschedUeConfigReq\n");
CschedUeConfigReq(eNB_mac_inst[mod_idP].fapi->sched, &p);
LOG_I(MAC, "calling CschedUeConfigCnf\n");
CschedUeConfigCnf(eNB_mac_inst[mod_idP].fapi, &r);
if (r.rnti != rntiP || r.result != ff_SUCCESS) {
LOG_E(MAC, "FAPI fatal error: rnti is %x (expected %x); result is %s (expected ff_SUCCESS)\n",
r.rnti, rntiP, r.result == ff_SUCCESS ? "ff_SUCCESS" : "ff_FAILURE");
abort();
}
#endif
return(UE_id);
}
......@@ -366,6 +420,11 @@ int mac_remove_ue(module_id_t mod_idP, int ue_idP, int frameP, sub_frame_t subfr
prev=i;
}
#if FAPI
printf("FAPI: remove UE: TODO\n");
abort();
#endif
if (ret == 0) {
return (0);
}
......@@ -530,6 +589,37 @@ void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag)
dump_ue_list(listP,ul_flag);
}
#if FAPI
void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP)
{
fapi_interface_t *fapi;
int UE_id;
struct SchedUlSrInfoReqParameters p;
struct SrListElement_s sr;
UE_id = find_UE_id(mod_idP, rntiP);
if (UE_id == -1) {
LOG_E(MAC, "%s:%d:%s: rnti %x: no such UE\n", __FILE__, __LINE__, __FUNCTION__, rntiP);
abort();
}
fapi = eNB_mac_inst[mod_idP].fapi;
p.sfnSf = frameP * 16 + subframeP;
p.nr_srList = 1;
p.srList = &sr;
p.nr_vendorSpecificList = 0;
p.vendorSpecificList = NULL;
sr.rnti = rntiP;
LOG_I(MAC, "eNB %d/%d f/sf %d/%d calling SchedUlSrInfoReq for rnti %x\n", mod_idP, cc_idP, frameP, subframeP, rntiP);
SchedUlSrInfoReq(fapi->sched, &p);
}
#else /* FAPI */
void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP)
{
......@@ -547,6 +637,7 @@ void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP
}
}
#endif /* FAPI */
......@@ -1101,8 +1192,10 @@ boolean_t CCE_allocation_infeasible(int module_idP,
DCI_pdu->Num_ue_spec_dci++;
ret = allocate_CCEs(module_idP,CC_idP,subframe,1);
if (ret==-1)
res = FALSE;
res = TRUE;
DCI_pdu->Num_ue_spec_dci--;
}
return res;
}
......@@ -227,6 +227,11 @@ void rx_sdu(
for (i=0; i<num_sdu; i++) {
LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
#if FAPI
if (UE_id != -1)
fapi_ul_lc_length(frameP, subframeP, rx_lcids[i], rx_lengths[i], rntiP);
#endif
switch (rx_lcids[i]) {
case CCCH :
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n",
......@@ -252,9 +257,56 @@ void rx_sdu(
if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) {
mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n");
// kill RA procedure
} else
} else {
#if FAPI
fapi_interface_t *fapi = eNB->fapi;
struct SchedDlMacBufferReqParameters p;
struct MacCeDlListElement_s ce;
#if 0
struct CschedLcConfigReqParameters lc;
struct LogicalChannelConfigListElement_s lc0;
struct CschedLcConfigCnfParameters lcr;
#endif
/* inform FAPI that we want to send contention resolution Control Element */
p.rnti = eNB->common_channels[CC_idP].RA_template[ii].rnti;
p.nr_macCEDL_List = 1;
p.macCeDlList = &ce;
p.nr_vendorSpecificList = 0;
p.vendorSpecificList = NULL;
ce.rnti = eNB->common_channels[CC_idP].RA_template[ii].rnti;
ce.macCeType = ff_CR;
SchedDlMacBufferReq(fapi->sched, &p);
#if 0
/* configure LC 0 (this is a bug of libscheduler.a, FAPI says this channel is preconfigured) */
lc.rnti = eNB->common_channels[CC_idP].RA_template[ii].rnti;
lc.reconfigureFlag = false;
lc.nr_logicalChannelConfigList = 1;
lc.logicalChannelConfigList = &lc0;
lc.nr_vendorSpecificList = 0;
lc.vendorSpecificList = NULL;
lc0.logicalChannelIdentity = 0; /* this is not possible according to FAPI */
lc0.logicalChannelGroup = 0; /* TBC */
lc0.direction = DIR_BOTH;
lc0.qosBearerType = QBT_NON_GBR;
lc0.qci = 5; /* what to put? see 23.203 table 6.1.7 */
/* bitrates not used - we are in non GBR */
CschedLcConfigReq(fapi->sched, &lc);
CschedLcConfigCnf(fapi, &lcr);
if (lcr.rnti != eNB->common_channels[CC_idP].RA_template[ii].rnti)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.result != ff_SUCCESS)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.nr_logicalChannelIdendity != 1)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (lcr.logicalChannelIdentity[0] != 0)
{ LOG_E(MAC, "%s:%d:%s: possible?\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
#endif
#endif /* FAPI */
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n",
enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id);
}
} else {
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %d\n",
enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP);
......
......@@ -5,11 +5,12 @@
#include "log.h"
#include "assertions.h"
//#undef LOG_D
//#define LOG_D LOG_I
#undef LOG_D
#define LOG_D LOG_I
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
/* callback IDs */
#define SCHED_DL_CONFIG_IND 0
......@@ -33,6 +34,9 @@ struct fapi {
volatile int rsp_id[N_IDs];
struct CschedCellConfigCnfParameters CschedCellConfigCnfParameters;
struct SchedDlConfigIndParameters SchedDlConfigIndParameters;
struct SchedUlConfigIndParameters SchedUlConfigIndParameters;
struct CschedUeConfigCnfParameters CschedUeConfigCnfParameters;
struct CschedLcConfigCnfParameters CschedLcConfigCnfParameters;
};
#define LOCK(fi, fn) do { \
......@@ -49,7 +53,7 @@ struct fapi {
#define CHECK(fi, fn) do { \
if (fi->req_id[fn] != fi->rsp_id[fn]) \
AssertFatal(0, "%s:%d:%s: check error\n", __FILE__, __LINE__, __FUNCTION__); \
AssertFatal(0, "%s:%d:%s: check error red_id %d rsp_id %d\n", __FILE__, __LINE__, __FUNCTION__, fi->req_id[fn], fi->rsp_id[fn]); \
} while (0)
#define WAIT(fi, fn) do { \
......@@ -59,8 +63,28 @@ struct fapi {
AssertFatal(0, "%s:%d:%s: cond error\n", __FILE__, __LINE__, __FUNCTION__); \
} while (0)
#define WAIT_TIMEOUT(fi, fn, delay_ms, has_timed_out) do { \
int ret = 0; \
has_timed_out = 0; \
LOG_D(MAC, "%s: WAIT fn %d req %d rsp %d\n", __FUNCTION__, fn, fi->req_id[fn], fi->rsp_id[fn]); \
struct timespec tout; \
if (clock_gettime(CLOCK_REALTIME, &tout)) \
AssertFatal(0, "%s:%d:%s: clock_gettime error\n", __FILE__, __LINE__, __FUNCTION__); \
tout.tv_nsec += (unsigned long)(delay_ms) * 1000000; \
while (tout.tv_nsec > 999999999) { \
tout.tv_sec++; \
tout.tv_nsec -= 1000000000; \
} \
while (ret == 0 && fi->req_id[fn] == fi->rsp_id[fn]) \
ret = pthread_cond_timedwait(&fi->cond[fn], &fi->mutex[fn], &tout); \
if (ret && ret != ETIMEDOUT) \
AssertFatal(0, "%s:%d:%s: cond error\n", __FILE__, __LINE__, __FUNCTION__); \
has_timed_out = ret == ETIMEDOUT; \
} while (0)
#define DONE_callback(fi, fn) do { \
fi->req_id[fn]++; \
/* printf("DONE_callback: req id %d rsp id %d\n", fi->req_id[fn], fi->rsp_id[fn]); */ \
if (pthread_cond_signal(&fi->cond[fn])) \
AssertFatal(0, "%s:%d:%s: mutex error\n", __FILE__, __LINE__, __FUNCTION__); \
} while (0)
......@@ -75,22 +99,47 @@ void SchedDlConfigInd(fapi_interface_t *_fi, struct SchedDlConfigIndParameters *
{
struct fapi *fi = (struct fapi *)_fi;
int fn = SCHED_DL_CONFIG_IND;
LOG_D(MAC, "SchedDlConfigInd enter\n");
int has_timed_out;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
//WAIT_TIMEOUT(fi, fn, 100, has_timed_out);
WAIT(fi, fn);
#if 0
if (has_timed_out) {
LOG_E(MAC, "SchedDlConfigInd timed out\n");
memset(params, 0, sizeof(*params));
goto end;
}
#endif
*params = fi->SchedDlConfigIndParameters;
DONE_wrapper(fi, fn);
end:
UNLOCK(fi, fn);
LOG_D(MAC, "SchedDlConfigInd leave\n");
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void SchedUlConfigInd(fapi_interface_t *_fi, struct SchedUlConfigIndParameters *params)
{
struct fapi *fi = (struct fapi *)_fi;
int fn = SCHED_UL_CONFIG_IND;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
WAIT(fi, fn);
*params = fi->SchedUlConfigIndParameters;
DONE_wrapper(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
/* CSCHED "wrappers" */
......@@ -99,7 +148,7 @@ void CschedCellConfigCnf(fapi_interface_t *_fi, struct CschedCellConfigCnfParame
{
struct fapi *fi = (struct fapi *)_fi;
int fn = CSCHED_CELL_CONFIG_CNF;
LOG_D(MAC, "CschedCellConfigCnf enter\n");
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
WAIT(fi, fn);
......@@ -109,17 +158,41 @@ void CschedCellConfigCnf(fapi_interface_t *_fi, struct CschedCellConfigCnfParame
DONE_wrapper(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "CschedCellConfigCnf leave\n");
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedUeConfigCnf(fapi_interface_t *_fi, struct CschedUeConfigCnfParameters *params)
{
struct fapi *fi = (struct fapi *)_fi;
int fn = CSCHED_UE_CONFIG_CNF;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
WAIT(fi, fn);
*params = fi->CschedUeConfigCnfParameters;
DONE_wrapper(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedLcConfigCnf(fapi_interface_t *_fi, struct CschedLcConfigCnfParameters *params)
{
struct fapi *fi = (struct fapi *)_fi;
int fn = CSCHED_LC_CONFIG_CNF;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
WAIT(fi, fn);
*params = fi->CschedLcConfigCnfParameters;
DONE_wrapper(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedLcReleaseCnf(fapi_interface_t *_fi, struct CschedLcReleaseCnfParameters *params)
......@@ -148,7 +221,7 @@ void SchedDlConfigInd_callback(void *callback_data, const struct SchedDlConfigIn
{
struct fapi *fi = callback_data;
int fn = SCHED_DL_CONFIG_IND;
LOG_D(MAC, "SchedDlConfigInd_callback enter\n");
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
CHECK(fi, fn);
......@@ -158,12 +231,24 @@ void SchedDlConfigInd_callback(void *callback_data, const struct SchedDlConfigIn
DONE_callback(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "SchedDlConfigInd_callback leave\n");
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void SchedUlConfigInd_callback(void *callback_data, const struct SchedUlConfigIndParameters *params)
{
struct fapi *fi = callback_data;
int fn = SCHED_UL_CONFIG_IND;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
CHECK(fi, fn);
fi->SchedUlConfigIndParameters = *params;
DONE_callback(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
/* CSCHED callbacks */
......@@ -172,7 +257,7 @@ void CschedCellConfigCnf_callback(void *callback_data, const struct CschedCellCo
{
struct fapi *fi = callback_data;
int fn = CSCHED_CELL_CONFIG_CNF;
LOG_D(MAC, "CschedCellConfigCnf_callback enter\n");
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
CHECK(fi, fn);
......@@ -182,37 +267,65 @@ void CschedCellConfigCnf_callback(void *callback_data, const struct CschedCellCo
DONE_callback(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "CschedCellConfigCnf_callback leave\n");
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedUeConfigCnf_callback(void *callback_data, const struct CschedUeConfigCnfParameters *params)
{
struct fapi *fi = callback_data;
int fn = CSCHED_UE_CONFIG_CNF;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
CHECK(fi, fn);
fi->CschedUeConfigCnfParameters = *params;
DONE_callback(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedLcConfigCnf_callback(void *callback_data, const struct CschedLcConfigCnfParameters *params)
{
struct fapi *fi = callback_data;
int fn = CSCHED_LC_CONFIG_CNF;
LOG_D(MAC, "%s enter\n", __FUNCTION__);
LOCK(fi, fn);
CHECK(fi, fn);
fi->CschedLcConfigCnfParameters = *params;
DONE_callback(fi, fn);
UNLOCK(fi, fn);
LOG_D(MAC, "%s leave\n", __FUNCTION__);
}
void CschedLcReleaseCnf_callback(void *callback_data, const struct CschedLcReleaseCnfParameters *params)
{
int fn = CSCHED_LC_RELEASE_CNF;
abort();
}
void CschedUeReleaseCnf_callback(void *callback_data, const struct CschedUeReleaseCnfParameters *params)
{
int fn = CSCHED_UE_RELEASE_CNF;
abort();
}
void CschedUeConfigUpdateInd_callback(void *callback_data, const struct CschedUeConfigUpdateIndParameters *params)
{
int fn = CSCHED_UE_CONFIG_UPDATE_IND;
abort();
}
void CschedCellConfigUpdateInd_callback(void *callback_data, const struct CschedCellConfigUpdateIndParameters *params)
{
int fn = CSCHED_CELL_CONFIG_UPDATE_IND;
abort();
}
fapi_interface_t *init_fapi(void)
......
......@@ -35,4 +35,15 @@ void CschedUeReleaseCnf(fapi_interface_t *, struct CschedUeReleaseCnfParameters
void CschedUeConfigUpdateInd(fapi_interface_t *, struct CschedUeConfigUpdateIndParameters *params);
void CschedCellConfigUpdateInd(fapi_interface_t *, struct CschedCellConfigUpdateIndParameters *params);
/* those functions are called by the PHY layer to inform FAPI of events */
/* signal uplink ACKs/NACKs */
void fapi_ul_ack_nack(int frame, int subframe, int rnti, int ack);
/* signal uplink LC data length received */
void fapi_ul_lc_length(int frame, int subframe, int lcid, int length, int rnti);
/* signal downlink ACKs/NACKs */
void fapi_dl_ack_nack(int rnti, int harq_pid, int transport_block, int ack);
#endif /* FF_MAC_H */
......@@ -667,6 +667,10 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
//Mac_rlc_xface->Is_cluster_head[0] = 1;
//Mac_rlc_xface->Is_cluster_head[1] = 0;
#if FAPI
mac_xface->fapi_ul_ack_nack = fapi_ul_ack_nack;
mac_xface->fapi_dl_ack_nack = fapi_dl_ack_nack;
#endif
return(1);
}
......
......@@ -764,6 +764,12 @@ int rrc_mac_config_req(module_id_t module_idP,
#endif
);
#if FAPI
void rrc_mac_fapi_configure_srb12(int module_id, int CC_id, int rnti);
#endif
/** \brief get the estimated UE distance from the PHY->MAC layer.
@param Mod_id Instance ID of eNB
@param UE_id Index of UE if this is an eNB configuration
......
......@@ -54,6 +54,74 @@ extern unsigned int distRIV2alloc_LUT25[512];
extern unsigned short RIV2nb_rb_LUT25[512];
extern unsigned short RIV2first_rb_LUT25[512];
#if FAPI
//------------------------------------------------------------------------------
unsigned short fill_rar(
const module_id_t module_idP,
const int CC_id,
const frame_t frameP,
uint8_t* const dlsch_buffer,
const uint16_t N_RB_UL,
const uint8_t input_buffer_length
)
//------------------------------------------------------------------------------
{
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer;
uint8_t *rar = (uint8_t *)(dlsch_buffer+1);
int i;
int ra_idx = -1;
uint32_t ul_grant;
AssertFatal(CC_id < MAX_NUM_CCs, "CC_id %u < MAX_NUM_CCs %u", CC_id, MAX_NUM_CCs);
for (i=0; i<NB_RA_PROC_MAX; i++) {
if (eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[i].generate_rar == 1) {
ra_idx=i;
eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[i].generate_rar = 0;
break;
}
}
if (ra_idx==-1)
return(0);
ul_grant = eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[i].UL_grant;
// subheader fixed
rarh->E = 0; // First and last RAR
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
rarh->RAPID = eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].preamble_index; // Respond to Preamble 0 only for the moment
rar[4] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti>>8);
rar[5] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti&0xff);
eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps
rar[0] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4
rar[1] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
rar[1] |= (ul_grant >> 16) & 0x0f;
rar[2] = (ul_grant >> 8) & 0xff;
rar[3] = ul_grant & 0xff;
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Generating RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ra_idx %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n",
module_idP, CC_id,
frameP,
*(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5],
ra_idx,
eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti,
rarh->RAPID,eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[0].preamble_index,
eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset);
if (opt_enabled) {
trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1,
eNB_mac_inst[module_idP].subframe, 0, 0);
LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
module_idP, CC_id, frameP, eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti,
rarh->RAPID, input_buffer_length);
}
return(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti);
}
#else /* FAPI */
//------------------------------------------------------------------------------
unsigned short fill_rar(
const module_id_t module_idP,
......@@ -107,7 +175,7 @@ unsigned short fill_rar(
eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps
rar[0] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4
rar[1] = (uint8_t)(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
rballoc = mac_xface->computeRIV(N_RB_UL,1,1); // first PRB only for UL Grant
rballoc = mac_xface->computeRIV(N_RB_UL,0,1); // first PRB only for UL Grant
rar[1] |= (rballoc>>7)&7; // Hopping = 0 (bit 3), 3 MSBs of rballoc
rar[2] = ((uint8_t)(rballoc&0xff))<<1; // 7 LSBs of rballoc
mcs = 10;
......@@ -137,6 +205,8 @@ unsigned short fill_rar(
return(eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti);
}
#endif /* FAPI */
//------------------------------------------------------------------------------
uint16_t
ue_process_rar(
......
......@@ -65,7 +65,7 @@ rlc_am_get_buffer_occupancy_in_bytes (
#if TRACE_RLC_AM_BO
if (((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) {
LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : CONTROL PDU %d bytes \n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3));
}
......@@ -90,7 +90,6 @@ rlc_am_get_buffer_occupancy_in_bytes (
#if TRACE_RLC_AM_BO
if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retransmission_buffer_occupancy);
......@@ -659,6 +658,33 @@ rlc_am_mac_status_indication (
#endif
return status_resp;
}
#if FAPI
//-----------------------------------------------------------------------------
struct mac_status_resp
rlc_am_mac_get_buffer_occupancy(
const protocol_ctxt_t* const ctxt_pP,
void * const rlc_pP)
{
struct mac_status_resp status_resp;
uint16_t sdu_size = 0;
uint16_t sdu_remaining_size = 0;
int32_t diff_time=0;
rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
status_resp.buffer_occupancy_in_bytes = 0;
status_resp.buffer_occupancy_in_pdus = 0;
status_resp.head_sdu_remaining_size_to_send = 0;
status_resp.head_sdu_creation_time = 0;
status_resp.head_sdu_is_segmented = 0;
status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
return status_resp;
}
#endif /* FAPI */
//-----------------------------------------------------------------------------
struct mac_data_req
rlc_am_mac_data_request (
......
......@@ -280,6 +280,10 @@ protected_rlc_am( void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void *
*/
public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
#if FAPI
public_rlc_am( struct mac_status_resp rlc_am_mac_get_buffer_occupancy(const protocol_ctxt_t* const ctxtP, void * const rlc_pP);)
#endif
/*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP)
* \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context.
......
......@@ -171,6 +171,21 @@ rlc_tm_mac_status_indication (
return status_resp;
}
#if FAPI
//-----------------------------------------------------------------------------
struct mac_status_resp
rlc_tm_mac_get_buffer_occupancy(
const protocol_ctxt_t* const ctxt_pP,
void * const rlc_pP)
{
struct mac_status_resp status_resp;
status_resp.buffer_occupancy_in_bytes = ((rlc_tm_entity_t *) rlc_pP)->buffer_occupancy;
return status_resp;
}
#endif /* FAPI */
//-----------------------------------------------------------------------------
struct mac_data_req
rlc_tm_mac_data_request (
......
......@@ -124,6 +124,9 @@ public_rlc_tm( struct mac_status_resp rlc_tm_mac_status_indication (
const uint16_t tb_sizeP,
struct mac_status_ind tx_statusP);)
#if FAPI
public_rlc_tm( struct mac_status_resp rlc_tm_mac_get_buffer_occupancy( const protocol_ctxt_t* const ctxt_pP, void * const rlcP);)
#endif
/*! \fn struct mac_data_req rlc_tm_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void * const rlcP)
* \brief Gives PDUs to lower layer MAC.
......
......@@ -513,6 +513,32 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
return status_resp;
}
#if FAPI
//-----------------------------------------------------------------------------
struct mac_status_resp
rlc_um_mac_get_buffer_occupancy(const protocol_ctxt_t* const ctxt_pP, void *rlc_pP)
{
struct mac_status_resp status_resp;
rlc_um_entity_t *rlc_p = NULL;
status_resp.buffer_occupancy_in_pdus = 0;
status_resp.buffer_occupancy_in_bytes = 0;
status_resp.head_sdu_remaining_size_to_send = 0;
status_resp.head_sdu_creation_time = 0;
status_resp.head_sdu_is_segmented = 0;
if (rlc_pP) {
rlc_p = (rlc_um_entity_t *) rlc_pP;
status_resp.rlc_info.rlc_protocol_state = rlc_p->protocol_state;
status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p);
}
return status_resp;
}
#endif /* FAPI */
//-----------------------------------------------------------------------------
struct mac_data_req
rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP)
......
......@@ -195,6 +195,10 @@ protected_rlc_um( void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_
*/
public_rlc_um( struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
#if FAPI
public_rlc_um( struct mac_status_resp rlc_um_mac_get_buffer_occupancy(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP);)
#endif
/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
* \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context.
......
......@@ -463,6 +463,11 @@ public_rlc_mac(void mac_rlc_data_ind (const module_id_t, co
* \return The maximum number of bytes that the RLC instance can send in the next transmission sequence.
*/
public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t );)
#if FAPI
public_rlc_mac(mac_rlc_status_resp_t mac_rlc_get_buffer_occupancy(const module_id_t, const rnti_t, const frame_t, logical_chan_id_t);)
#endif
//-----------------------------------------------------------------------------
// RLC methods
//-----------------------------------------------------------------------------
......
......@@ -449,3 +449,69 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
return mac_rlc_status_resp;
}
#if FAPI
//-----------------------------------------------------------------------------
mac_rlc_status_resp_t mac_rlc_get_buffer_occupancy(
const module_id_t module_idP,
const rnti_t rntiP,
const frame_t frameP,
const logical_chan_id_t channel_idP)
{
//-----------------------------------------------------------------------------
mac_rlc_status_resp_t mac_rlc_status_resp;
struct mac_status_resp status_resp;
rb_id_t rb_id = 0;
rlc_mode_t rlc_mode = RLC_MODE_NONE;
rlc_union_t *rlc_union_p = NULL;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
srb_flag_t srb_flag = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, 1 /* enb flag */, rntiP, frameP, 0, module_idP /* eNB_index */);
memset (&mac_rlc_status_resp, 0, sizeof(mac_rlc_status_resp_t));
if (channel_idP > 2) {
rb_id = channel_idP - 2;
} else {
rb_id = channel_idP;
}
key = RLC_COLL_KEY_VALUE(module_idP, rntiP, 1, rb_id, srb_flag);
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
rlc_mode = rlc_union_p->mode;
} else {
rlc_mode = RLC_MODE_NONE;
}
switch (rlc_mode) {
default:
case RLC_MODE_NONE:
mac_rlc_status_resp.bytes_in_buffer = 0;
break;
case RLC_MODE_AM:
status_resp = rlc_am_mac_get_buffer_occupancy(&ctxt, &rlc_union_p->rlc.am);
mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
break;
case RLC_MODE_UM:
status_resp = rlc_um_mac_get_buffer_occupancy(&ctxt, &rlc_union_p->rlc.um);
mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
break;
case RLC_MODE_TM:
status_resp = rlc_tm_mac_get_buffer_occupancy(&ctxt, &rlc_union_p->rlc.tm);
mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
break;
}
return mac_rlc_status_resp;
}
#endif /* FAPI */
......@@ -336,6 +336,11 @@ typedef struct {
uint8_t (*get_SB_size)(uint8_t n_rb_dl);
///end ALU's algo
#if FAPI
void (*fapi_ul_ack_nack)(int frame, int subframe, int rnti, int ack);
void (*fapi_dl_ack_nack)(int rnti, int harq_pid, int transport_block, int ack);
#endif
} MAC_xface;
......
......@@ -41,6 +41,24 @@
#include "COMMON/mac_rrc_primitives.h"
#include "COMMON/platform_types.h"
#if FAPI
int mac_rrc_get_SIB1(
const module_id_t mod_id,
const int CC_id,
uint8_t * const buffer);
int mac_rrc_get_SIB23(
const module_id_t mod_id,
const int CC_id,
uint8_t * const buffer);
int mac_rrc_get_ccch_size(
const module_id_t Mod_idP,
const int CC_id);
#endif /* FAPI */
int8_t
mac_rrc_data_req(
const module_id_t module_idP,
......
......@@ -65,6 +65,56 @@ extern UE_MAC_INST *UE_mac_inst;
mui_t mui=0;
#if FAPI
int mac_rrc_get_SIB1(
const module_id_t mod_id,
const int CC_id,
uint8_t * const buffer)
{
if (eNB_rrc_inst[mod_id].carrier[CC_id].SI.Active == 0)
return 0;
if (eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB1 == 255) {
LOG_E(RRC,"[eNB %d] MAC Request for SIB1 and SIB1 not initialized\n", mod_id);
mac_xface->macphy_exit("mac_rrc_lite_data_req: MAC Request for SIB1 and SIB1 not initialized");
}
memcpy(buffer,
eNB_rrc_inst[mod_id].carrier[CC_id].SIB1,
eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB1);
return eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB1;
}
int mac_rrc_get_SIB23(
const module_id_t mod_id,
const int CC_id,
uint8_t * const buffer)
{
if (eNB_rrc_inst[mod_id].carrier[CC_id].SI.Active == 0)
return 0;
if (eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB23 == 255) {
LOG_E(RRC,"[eNB %d] MAC Request for SIB23 and SIB23 not initialized\n", mod_id);
mac_xface->macphy_exit("mac_rrc_lite_data_req: MAC Request for SIB23 and SIB23 not initialized");
}
memcpy(buffer,
eNB_rrc_inst[mod_id].carrier[CC_id].SIB23,
eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB23);
return eNB_rrc_inst[mod_id].carrier[CC_id].sizeof_SIB23;
}
int mac_rrc_get_ccch_size(const module_id_t Mod_idP, const int CC_id)
{
if(eNB_rrc_inst[Mod_idP].carrier[CC_id].Srb0.Active == 0) return 0;
return eNB_rrc_inst[Mod_idP].carrier[CC_id].Srb0.Tx_buffer.payload_size;
}
#endif /* FAPI */
//------------------------------------------------------------------------------
int8_t
mac_rrc_lite_data_req(
......@@ -95,6 +145,7 @@ mac_rrc_lite_data_req(
return 0;
}
printf("XX frame %d %%2 %d %%8 %d\n", frameP, frameP % 2, frameP % 8);
// All even frames transmit SIB in SF 5
if (eNB_rrc_inst[Mod_idP].carrier[CC_id].sizeof_SIB1 == 255) {
LOG_E(RRC,"[eNB %d] MAC Request for SIB1 and SIB1 not initialized\n",Mod_idP);
......@@ -102,6 +153,7 @@ mac_rrc_lite_data_req(
}
if ((frameP%2) == 0) {
printf("XX throw SIB1\n");
memcpy(&buffer_pP[0],
eNB_rrc_inst[Mod_idP].carrier[CC_id].SIB1,
eNB_rrc_inst[Mod_idP].carrier[CC_id].sizeof_SIB1);
......@@ -143,6 +195,7 @@ mac_rrc_lite_data_req(
return (eNB_rrc_inst[Mod_idP].carrier[CC_id].sizeof_SIB1);
} // All RFN mod 8 transmit SIB2-3 in SF 5
else if ((frameP%8) == 1) {
printf("XX throw SIB2/3\n");
memcpy(&buffer_pP[0],
eNB_rrc_inst[Mod_idP].carrier[CC_id].SIB23,
eNB_rrc_inst[Mod_idP].carrier[CC_id].sizeof_SIB23);
......
......@@ -1698,6 +1698,7 @@ do_RRCConnectionSetup(
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message,
(void*)&dl_ccch_msg,
buffer,
......
......@@ -3819,6 +3819,10 @@ rrc_eNB_decode_ccch(
&DCCH_LCHAN_DESC,
LCHAN_DESC_SIZE);
#if FAPI
rrc_mac_fapi_configure_srb12(ctxt_pP->module_id, CC_id, ue_context_p->ue_context.rnti);
#endif
rrc_eNB_generate_RRCConnectionSetup(ctxt_pP, ue_context_p, CC_id);
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1 (rbid %d)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
......
......@@ -66,7 +66,7 @@ eNBs =
pusch_p0_Nominal = -108;
pusch_alpha = "AL1";
pucch_p0_Nominal = -108;
pucch_p0_Nominal = -96; //-108;
msg3_delta_Preamble = 6;
pucch_deltaF_Format1 = "deltaF2";
pucch_deltaF_Format1b = "deltaF3";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment