Files
openairinterface5g/openair2/LAYER2/MAC/eNB_scheduler.c
T
Melissa Elkadi 9b16c1d860 Merge branch 'eurecom-develop' into episys/merge_nsa_w_develop
At this point we are successfully able to build.
Additionally, we can run the scenario,
however, it does not pass. It seems that the gNB
is not connecting to the proxy correctly. Just
wanted to push the progress so far. FYI, the items
that had to be changed to correct the linking issues
were the following:

 - mac_rrc_data_ind_ue vs. nr_mac_rrc_data_ind_ue
 - rrc_data_req vs. nr_rrc_data_req
 - mac_rrc_data_req_ue vs. nr_mac_rrc_data_req_ue
 - rrc_data_req_ue vs. rrc_data_req_nr_ue
 - rrc_data_req vs. nr_rrc_data_req

The listed functions should be declard in the LTE/NR
UE directory depending on the functionality. Several
were mixed. i.e.: LTE functions being called in NR UE.

Also, removing siWindowLength, siWindowLength_int,
SIBType, SIBPeriod, and siPeriod_int from the NR UE RRC.
These variable were not used in the NR UE and are defined
for LTE only.

Lastly, in the NR_IF_Module.c of the NR UE, the global
variable def_dci_pdu_rel15 is not accessible. Need to
revisit this. For not it is commented out.
2021-08-11 10:23:42 -07:00

1102 lines
54 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file eNB_scheduler.c
* \brief eNB scheduler top level function operates on per subframe basis
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 0.5
* @ingroup _mac
*/
#include "assertions.h"
#include "targets/RT/USER/lte-softmodem.h"
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "common/utils/LOG/log.h"
#include "nfapi/oai_integration/vendor_ext.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LTE/rrc_extern.h"
#include "RRC/NR/nr_rrc_extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
//Agent-related headers
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
/* for fair round robin SCHED */
#include "eNB_scheduler_fairRR.h"
#include "intertask_interface.h"
#include "assertions.h"
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
extern RAN_CONTEXT_t RC;
uint16_t pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
//-----------------------------------------------------------------------------
/*
* Schedule periodic SRS
*/
void schedule_SRS(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP)
//-----------------------------------------------------------------------------
{
int CC_id = 0;
int UE_id = -1;
uint8_t TSFC = 0;
uint8_t srs_SubframeConfig = 0;
uint16_t srsPeriodicity = 0;
uint16_t srsOffset = 0;
uint16_t deltaTSFC = 0; // bitmap
// table for TSFC (Period) and deltaSFC (offset)
const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD
const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD
eNB_MAC_INST *eNB = RC.mac[module_idP];
UE_info_t *UE_info = &eNB->UE_info;
nfapi_ul_config_request_body_t *ul_req = NULL;
UE_sched_ctrl_t *UE_scheduling_control = NULL;
COMMON_channels_t *cc = eNB->common_channels;
LTE_SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon = NULL;
struct LTE_SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated = NULL;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
soundingRS_UL_ConfigCommon = &(cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon);
/* Check if SRS is enabled in this frame/subframe */
if (soundingRS_UL_ConfigCommon) {
srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
if (cc[CC_id].tdd_Config == NULL) { // FDD
deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
} else { // TDD
deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
}
/* Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC) */
uint16_t tmp = (subframeP % TSFC);
if ((1 << tmp) & deltaTSFC) {
/* This is an SRS subframe, loop over UEs */
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (!UE_info->active[UE_id]) {
continue;
}
/* Drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet */
if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) {
continue;
}
if(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) {
LOG_E(MAC,"physicalConfigDedicated is null for UE %d\n",UE_id);
printf("physicalConfigDedicated is null for UE %d\n",UE_id);
return;
}
/* CDRX condition on Active Time and SRS type-0 report (36.321 5.7) */
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
/* Test if Active Time not running since 6+ subframes */
if (UE_scheduling_control->cdrx_configured == TRUE && UE_scheduling_control->in_active_time == FALSE) {
/*
* TODO: 6+ subframes condition not checked here
*/
continue;
}
ul_req = &(eNB->UL_req[CC_id].ul_config_request_body);
if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
if (soundingRS_UL_ConfigDedicated->present == LTE_SoundingRS_UL_ConfigDedicated_PR_setup) {
get_srs_pos(&cc[CC_id],
soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex,
&srsPeriodicity,
&srsOffset);
if (((10 * frameP + subframeP) % srsPeriodicity) == srsOffset) {
// Program SRS
ul_req->srs_present = 1;
nfapi_ul_config_request_pdu_t *ul_config_pdu = &(ul_req->ul_config_pdu_list[ul_req->number_of_pdus]);
memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_SRS_PDU_TYPE;
ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu));
ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
eNB->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
ul_req->number_of_pdus++;
} // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
} // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
} // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
} // end for loop on UE_id
} // if((1<<tmp) & deltaTSFC)
} // SRS config not NULL
} // end for loop on CC_id
}
//-----------------------------------------------------------------------------
/*
* Schedule the CSI (CQI/PMI/RI/PTI/CRI) periodic reception
*/
void schedule_CSI(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP)
//-----------------------------------------------------------------------------
{
int CC_id = 0;
int UE_id = 0;
int H = 0;
uint16_t Npd = 0;
uint16_t N_OFFSET_CQI = 0;
struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = NULL;
eNB_MAC_INST *eNB = RC.mac[module_idP];
UE_info_t *UE_info = &eNB->UE_info;
COMMON_channels_t *cc = NULL;
nfapi_ul_config_request_body_t *ul_req = NULL;
UE_sched_ctrl_t *UE_scheduling_control = NULL;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (UE_info->active[UE_id] == FALSE) {
continue;
}
/* Drop the allocation if the UE hasn't sent RRCConnectionSetupComplete yet */
if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) {
continue;
}
AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
"physicalConfigDedicated is null for UE %d\n",
UE_id);
/*
* CDRX condition on Active Time and CSI report on PUCCH (36.321 5.7).
* Here we consider classic periodic reports on PUCCH without PUSCH simultaneous transmission condition.
* TODO: add the handling or test on simultaneous PUCCH/PUSCH transmission
*/
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
if (UE_scheduling_control->cdrx_configured == TRUE) {
/* Test if CQI masking activated */
if (UE_scheduling_control->cqi_mask_boolean == TRUE) {
// CQI masking => test if onDurationTime not running since 6+ subframe
if (UE_scheduling_control->on_duration_timer == 0) {
/*
* TODO: 6+ subframes condition not checked here
*/
continue;
}
} else { // No CQI masking => test if Active Time not running since 6+ subframe
if (UE_scheduling_control->in_active_time == FALSE) {
/*
* TODO: 6+ subframes condition not checked here
*/
continue;
}
}
}
ul_req = &(eNB->UL_req[CC_id].ul_config_request_body);
if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) {
cqi_ReportPeriodic = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic;
if (cqi_ReportPeriodic != NULL) {
/* Rel8 Periodic CSI (CQI/PMI/RI) reporting */
if (cqi_ReportPeriodic->present != LTE_CQI_ReportPeriodic_PR_release) {
get_csi_params(cc, cqi_ReportPeriodic, &Npd, &N_OFFSET_CQI, &H);
if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) { // CQI periodic opportunity
UE_scheduling_control->feedback_cnt[CC_id] = (((frameP * 10) + subframeP) / Npd) % H;
// Program CQI
nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_info->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id),
cqi_ReportPeriodic);
ul_req->number_of_pdus++;
ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
// PUT rel10-13 UCI options here
} else if (cqi_ReportPeriodic->choice.setup.ri_ConfigIndex != NULL) {
if ((((frameP * 10) + subframeP) % ((H * Npd) << (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex / 161))) ==
N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex % 161)) { // RI opportunity
// Program RI
nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = (cc->p_eNB == 2) ? 1 : 2;
RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
ul_req->number_of_pdus++;
ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
}
}
} // if CSI Periodic is not release state
} // if (cqi_ReportPeriodic != NULL)
} // if cqi_ReportConfig != NULL
} // for (UE_id=UE_info->head; UE_id>=0; UE_id=UE_info->next[UE_id]) {
} // for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
}
//-----------------------------------------------------------------------------
/*
* Schedule a possible Scheduling Request reception
*/
void
schedule_SR (module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP)
//-----------------------------------------------------------------------------
{
int skip_ue = 0;
int is_harq = 0;
int pdu_list_index = 0;
eNB_MAC_INST *eNB = RC.mac[module_idP];
UE_info_t *UE_info = &eNB->UE_info;
nfapi_ul_config_request_t *ul_req = NULL;
nfapi_ul_config_request_body_t *ul_req_body = NULL;
LTE_SchedulingRequestConfig_t *SRconfig = NULL;
nfapi_ul_config_sr_information sr;
memset(&sr, 0, sizeof(sr));
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (!UE_info->active[UE_id]) {
continue;
}
if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue;
if ((SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) {
if (SRconfig->present == LTE_SchedulingRequestConfig_PR_setup) {
if (SRconfig->choice.setup.sr_ConfigIndex <= 4) { // 5 ms SR period
if ((subframeP % 5) != SRconfig->choice.setup.sr_ConfigIndex) continue;
} else if (SRconfig->choice.setup.sr_ConfigIndex <= 14) { // 10 ms SR period
if (subframeP != (SRconfig->choice.setup.sr_ConfigIndex - 5)) continue;
} else if (SRconfig->choice.setup.sr_ConfigIndex <= 34) { // 20 ms SR period
if ((10 * (frameP & 1) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 15)) continue;
} else if (SRconfig->choice.setup.sr_ConfigIndex <= 74) { // 40 ms SR period
if ((10 * (frameP & 3) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 35)) continue;
} else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period
if ((10 * (frameP & 7) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 75)) continue;
} else if (SRconfig->choice.setup.sr_ConfigIndex <= 156) { // 2ms SR period
if ((subframeP % 2) != (SRconfig->choice.setup.sr_ConfigIndex - 155)) continue;
}
} // SRconfig->present == SchedulingRequestConfig_PR_setup)
} // SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL)
/* If we get here there is some PUCCH1 reception to schedule for SR */
ul_req = &(eNB->UL_req[CC_id]);
ul_req_body = &(ul_req->ul_config_request_body);
skip_ue = 0;
is_harq = 0;
pdu_list_index = 0;
/* Check that there is no existing UL grant for ULSCH which overrides the SR */
for (int i = 0; i < ul_req_body->number_of_pdus; i++) {
if (((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) ||
(ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) ||
(ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) ||
(ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)) &&
(ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) {
skip_ue = 1;
pdu_list_index = i;
break;
}
/* If there is already an HARQ pdu, convert to SR_HARQ */
else if ((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) &&
(ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) {
is_harq = 1;
pdu_list_index = i;
break;
}
}
/* Drop the allocation because ULSCH will handle it with BSR */
if (skip_ue == 1) continue;
LOG_D(MAC, "Frame %d, Subframe %d : Scheduling SR for UE %d/%x is_harq:%d \n",
frameP,
subframeP,
UE_id,
UE_info->UE_template[CC_id][UE_id].rnti,
is_harq);
/* Check Rel10 or Rel8 SR */
if ((UE_info-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) &&
(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) &&
(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) {
sr.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
sr.sr_information_rel10.number_of_pucch_resources = 1;
sr.sr_information_rel10.pucch_index_p1 = *UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10;
LOG_D(MAC, "REL10 PUCCH INDEX P1:%d \n", sr.sr_information_rel10.pucch_index_p1);
} else {
sr.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
sr.sr_information_rel8.pucch_index = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
LOG_D(MAC, "REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index);
}
/* If there is already an HARQ pdu, convert to SR_HARQ */
if (is_harq) {
nfapi_ul_config_harq_information harq = ul_req_body->ul_config_pdu_list[pdu_list_index].uci_harq_pdu.harq_information;
ul_req_body->ul_config_pdu_list[pdu_list_index].pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
ul_req_body->ul_config_pdu_list[pdu_list_index].uci_sr_harq_pdu.sr_information = sr;
ul_req_body->ul_config_pdu_list[pdu_list_index].uci_sr_harq_pdu.harq_information = harq;
} else {
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE;
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti;
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel11.tl.tag = 0;
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel13.tl.tag = 0;
ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.sr_information = sr;
ul_req_body->number_of_pdus++;
} // if (is_harq)
ul_req_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
} // for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++)
} // for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
}
void
check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
frame_t frameP, sub_frame_t subframeP) {
UE_info_t *UE_info = &RC.mac[module_idP]->UE_info;
nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0];
uint16_t rnti = UE_RNTI(module_idP, UE_id);
COMMON_channels_t *cc = RC.mac[module_idP]->common_channels;
// check uplink failure
if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) &&
(UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) {
if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 1)
LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti,
UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) {
UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1;
// add a format 1A dci for this UE to request an RA procedure (only one UE per subframe)
nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu];
memset((void *) dl_config_pdu, 0,sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP, CC_id),
UE_info->UE_sched_ctrl[UE_id].
dl_cqi[CC_id], format1A);
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power
AssertFatal((cc[CC_id].mib->message.dl_Bandwidth >= 0) && (cc[CC_id].mib->message.dl_Bandwidth < 6),
"illegal dl_Bandwidth %d\n",
(int) cc[CC_id].mib->message.dl_Bandwidth);
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = pdcch_order_table[cc[CC_id].mib->message.dl_Bandwidth];
DL_req[CC_id].dl_config_request_body.number_dci++;
DL_req[CC_id].dl_config_request_body.number_pdu++;
DL_req[CC_id].dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
LOG_D(MAC,
"UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",
UE_id, rnti,
UE_info->UE_sched_ctrl[UE_id].ul_failure_timer,
dl_config_pdu->dci_dl_pdu.
dci_dl_pdu_rel8.resource_block_coding);
} else { // ra_pdcch_sent==1
LOG_D(MAC,
"UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n",
UE_id, rnti,
UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 8 frames
}
UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++;
// check threshold
if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) {
// note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311)
if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
F1AP_UE_CONTEXT_RELEASE_REQ(m).rnti = rnti;
F1AP_UE_CONTEXT_RELEASE_REQ(m).cause = F1AP_CAUSE_RADIO_NETWORK;
F1AP_UE_CONTEXT_RELEASE_REQ(m).cause_value = 1; // 1 = F1AP_CauseRadioNetwork_rl_failure
F1AP_UE_CONTEXT_RELEASE_REQ(m).rrc_container = NULL;
F1AP_UE_CONTEXT_RELEASE_REQ(m).rrc_container_length = 0;
itti_send_msg_to_task(TASK_DU_F1, module_idP, m);
} else {
// inform RRC of failure and clear timer
LOG_I(MAC, "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",
UE_id,
rnti);
mac_eNB_rrc_ul_failure(module_idP,
CC_id,
frameP,
subframeP,
rnti);
}
UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync = 1;
}
} // ul_failure_timer>0
UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer++;
if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) {
LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti);
mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti);
UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
}// time > 60s
}
void
clear_nfapi_information(eNB_MAC_INST *eNB, int CC_idP,
frame_t frameP, sub_frame_t subframeP) {
nfapi_dl_config_request_t *DL_req = &eNB->DL_req[0];
nfapi_ul_config_request_t *UL_req = &eNB->UL_req[0];
nfapi_hi_dci0_request_t *HI_DCI0_req = &eNB->HI_DCI0_req[CC_idP][subframeP];
nfapi_tx_request_t *TX_req = &eNB->TX_req[0];
eNB->pdu_index[CC_idP] = 0;
if (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MONOLITHIC) { // monolithic or PNF
DL_req[CC_idP].dl_config_request_body.number_pdcch_ofdm_symbols = 1;
DL_req[CC_idP].dl_config_request_body.number_dci = 0;
DL_req[CC_idP].dl_config_request_body.number_pdu = 0;
DL_req[CC_idP].dl_config_request_body.number_pdsch_rnti = 0;
DL_req[CC_idP].dl_config_request_body.transmission_power_pcfich = 6000;
DL_req[CC_idP].sfn_sf = subframeP + (frameP<<4);
HI_DCI0_req->hi_dci0_request_body.sfnsf = subframeP + (frameP<<4);
HI_DCI0_req->hi_dci0_request_body.number_of_dci = 0;
UL_req[CC_idP].ul_config_request_body.number_of_pdus = 0;
UL_req[CC_idP].ul_config_request_body.rach_prach_frequency_resources = 0; // ignored, handled by PHY for now
UL_req[CC_idP].ul_config_request_body.srs_present = 0; // ignored, handled by PHY for now
TX_req[CC_idP].tx_request_body.number_of_pdus = 0;
}
}
void
copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
int CC_id;
eNB_MAC_INST *mac = RC.mac[module_idP];
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
nfapi_ul_config_request_t *ul_req_tmp = &mac->UL_req_tmp[CC_id][subframeP];
nfapi_ul_config_request_t *ul_req = &mac->UL_req[CC_id];
nfapi_ul_config_request_pdu_t *ul_req_pdu = ul_req->ul_config_request_body.ul_config_pdu_list;
*ul_req = *ul_req_tmp;
// Restore the pointer
ul_req->ul_config_request_body.ul_config_pdu_list = ul_req_pdu;
ul_req->sfn_sf = (frameP<<4) + subframeP;
ul_req_tmp->ul_config_request_body.number_of_pdus = 0;
if (ul_req->ul_config_request_body.number_of_pdus>0) {
LOG_D(MAC, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
}
memcpy((void *)ul_req->ul_config_request_body.ul_config_pdu_list,
(void *)ul_req_tmp->ul_config_request_body.ul_config_pdu_list,
ul_req->ul_config_request_body.number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t));
}
}
extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
void
eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP) {
int mbsfn_status[MAX_NUM_CCs];
protocol_ctxt_t ctxt;
rnti_t rnti = 0;
int CC_id = 0;
int UE_id = -1;
eNB_MAC_INST *eNB = RC.mac[module_idP];
UE_info_t *UE_info = &(eNB->UE_info);
COMMON_channels_t *cc = eNB->common_channels;
UE_sched_ctrl_t *UE_scheduling_control = NULL;
start_meas(&(eNB->eNB_scheduler));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_IN);
// TODO: Better solution needed this is the first
// 3 indications of this function on startup
// 1303275.278188 [MAC] XXX 0.0 -> 0.4 = 4
// 1303275.279443 [MAC] XXX 0.4 -> 639.5 = 6391
// 1303275.348686 [MAC] XXX 646.3 -> 646.3 = 0
int delta = (frameP * 10 + subframeP) - (eNB->frame * 10 + eNB->subframe);
if (delta < 0)
{
delta += 10240; // sfn_sf decimal values range from 0 to 10239
}
// If we ever see a difference this big something is very wrong
// This threshold is arbitrary
if (delta > 8500 || delta == 0) // 850 frames
{
LOG_I(MAC, "scheduler ignoring outerspace %d.%d -> %d.%d = %d\n",
eNB->frame, eNB->subframe, frameP, subframeP, delta);
return;
}
LOG_I(MAC, "Entering dlsch_ulsch scheduler %d.%d -> %d.%d = %d\n",
eNB->frame, eNB->subframe, frameP, subframeP, delta);
eNB->frame = frameP;
eNB->subframe = subframeP;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
mbsfn_status[CC_id] = 0;
/* Clear vrb_maps */
memset(cc[CC_id].vrb_map, 0, 100);
memset(cc[CC_id].vrb_map_UL, 0, 100);
cc[CC_id].mcch_active = 0;
clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, subframeP);
/* hack: skip BCH RBs in subframe 0 for DL scheduling,
* because with high MCS we may exceed code rate 0.93
* when using those RBs (36.213 7.1.7 says the UE may
* skip decoding if the code rate is higher than 0.93)
* TODO: remove this hack, deal with physical bits properly
* i.e. reduce MCS in the scheduler if code rate > 0.93
*/
if (subframeP == 0) {
int i;
int bw = cc[CC_id].mib->message.dl_Bandwidth;
/* start and count defined for RBs: 6, 15, 25, 50, 75, 100 */
int start[6] = { 0, 4, 9, 22, 34, 47 };
int count[6] = { 6, 7, 7, 6, 7, 6 };
for (i = 0; i < count[bw]; i++)
cc[CC_id].vrb_map[start[bw] + i] = 1;
}
}
/* Refresh UE list based on UEs dropped by PHY in previous subframe */
for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (UE_info->active[UE_id]) {
rnti = UE_RNTI(module_idP, UE_id);
CC_id = UE_PCCID(module_idP, UE_id);
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
/* to be merged with MAC_stats.log generation. probably redundant
if (((frameP & 127) == 0) && (subframeP == 0)) {
double total_bler;
if(UE_scheduling_control->pusch_rx_num[CC_id] == 0 && UE_scheduling_control->pusch_rx_error_num[CC_id] == 0) {
total_bler = 0;
}
else {
total_bler = (double)UE_scheduling_control->pusch_rx_error_num[CC_id] / (double)(UE_scheduling_control->pusch_rx_error_num[CC_id] + UE_scheduling_control->pusch_rx_num[CC_id]) * 100;
}
LOG_I(MAC,"UE %x : %s, PHR %d DLCQI %d PUSCH %d PUCCH %d RLC disc %d UL-stat rcv %lu err %lu bler %lf mcsoff %d bsr %u sched %u tbs %lu cnt %u , DL-stat tbs %lu cnt %u rb %u buf %u 1st %u ret %u ri %d\n",
rnti,
UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync",
UE_info->UE_template[CC_id][UE_id].phr_info,
UE_scheduling_control->dl_cqi[CC_id],
UE_scheduling_control->pusch_snr_avg[CC_id],
UE_scheduling_control->pucch1_snr[CC_id],
UE_scheduling_control->rlc_out_of_resources_cnt,
UE_scheduling_control->pusch_rx_num[CC_id],
UE_scheduling_control->pusch_rx_error_num[CC_id],
total_bler,
UE_scheduling_control->mcs_offset[CC_id],
UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer,
UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes,
UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx,
UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx,
UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes,
UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus,
UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used,
#if defined(PRE_SCD_THREAD)
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
#else
0,
#endif
UE_scheduling_control->first_cnt[CC_id],
UE_scheduling_control->ret_cnt[CC_id],
UE_scheduling_control->aperiodic_ri_received[CC_id]
);
}
*/
RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = -63;
if (UE_id == UE_info->list.head) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP]);
}
/* Set and increment CDRX related timers */
if (UE_scheduling_control->cdrx_configured == TRUE) {
boolean_t harq_active_time_condition = FALSE;
UE_TEMPLATE *UE_template = NULL;
unsigned long active_time_condition = 0; // variable used only for tracing purpose
/* (UL and DL) HARQ RTT timers and DRX retransmission timers */
for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
/* DL asynchronous HARQ process */
if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > 0) {
UE_scheduling_control->drx_retransmission_timer[harq_process_id]++;
if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > UE_scheduling_control->drx_retransmission_timer_thres[harq_process_id]) {
UE_scheduling_control->drx_retransmission_timer[harq_process_id] = 0;
}
}
if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 0) {
UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id]++;
if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 8) {
/* Note: here drx_retransmission_timer is restarted instead of started in the specification */
UE_scheduling_control->drx_retransmission_timer[harq_process_id] = 1; // started when HARQ RTT timer expires
UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] = 0;
}
}
/* UL asynchronous HARQ process: only UL HARQ RTT timer is implemented (hence not implemented) */
if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 0) {
UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id]++;
if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 4) {
/*
* TODO: implement the handling of UL asynchronous HARQ
* drx_ULRetransmissionTimer should be (re)started here
*/
UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] = 0;
}
}
/* UL synchronous HARQ process */
if (UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] > 0) {
UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id]++;
if (UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] > 5) {
harq_active_time_condition = TRUE;
UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] = 0;
active_time_condition = 5; // for tracing purpose
}
}
}
/* On duration timer */
if (UE_scheduling_control->on_duration_timer > 0) {
UE_scheduling_control->on_duration_timer++;
if (UE_scheduling_control->on_duration_timer > UE_scheduling_control->on_duration_timer_thres) {
UE_scheduling_control->on_duration_timer = 0;
}
}
/* DRX inactivity timer */
if (UE_scheduling_control->drx_inactivity_timer > 0) {
UE_scheduling_control->drx_inactivity_timer++;
if (UE_scheduling_control->drx_inactivity_timer > (UE_scheduling_control->drx_inactivity_timer_thres + 1)) {
/* Note: the +1 on the threshold is due to information in table C-1 of 36.321 */
UE_scheduling_control->drx_inactivity_timer = 0;
/* When timer expires switch into short or long DRX cycle */
if (UE_scheduling_control->drx_shortCycle_timer_thres > 0) {
UE_scheduling_control->in_short_drx_cycle = TRUE;
UE_scheduling_control->drx_shortCycle_timer = 0;
UE_scheduling_control->in_long_drx_cycle = FALSE;
} else {
UE_scheduling_control->in_long_drx_cycle = TRUE;
}
}
}
/* Short DRX Cycle */
if (UE_scheduling_control->in_short_drx_cycle == TRUE) {
UE_scheduling_control->drx_shortCycle_timer++;
/* When the Short DRX cycles are over, switch to long DRX cycle */
if (UE_scheduling_control->drx_shortCycle_timer > UE_scheduling_control->drx_shortCycle_timer_thres) {
UE_scheduling_control->drx_shortCycle_timer = 0;
UE_scheduling_control->in_short_drx_cycle = FALSE;
UE_scheduling_control->in_long_drx_cycle = TRUE;
UE_scheduling_control->drx_longCycle_timer = 0;
}
} else {
UE_scheduling_control->drx_shortCycle_timer = 0;
}
/* Long DRX Cycle */
if (UE_scheduling_control->in_long_drx_cycle == TRUE) {
UE_scheduling_control->drx_longCycle_timer++;
if (UE_scheduling_control->drx_longCycle_timer > UE_scheduling_control->drx_longCycle_timer_thres) {
UE_scheduling_control->drx_longCycle_timer = 1;
}
} else {
UE_scheduling_control->drx_longCycle_timer = 0;
}
/* Check for error cases */
if ((UE_scheduling_control->in_short_drx_cycle == TRUE) && (UE_scheduling_control->in_long_drx_cycle == TRUE)) {
LOG_E(MAC, "Error in C-DRX: UE id %d is in both short and long DRX cycle. Should not happen. Back it to long cycle only\n", UE_id);
UE_scheduling_control->in_short_drx_cycle = FALSE;
}
/* Condition to start On Duration Timer */
if (UE_scheduling_control->in_short_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) {
if (((frameP * 10) + subframeP) % (UE_scheduling_control->short_drx_cycle_duration) ==
(UE_scheduling_control->drx_start_offset) % (UE_scheduling_control->short_drx_cycle_duration)) {
UE_scheduling_control->on_duration_timer = 1;
}
} else if (UE_scheduling_control->in_long_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) {
if (((frameP * 10) + subframeP) % (UE_scheduling_control->drx_longCycle_timer_thres) ==
(UE_scheduling_control->drx_start_offset)) {
UE_scheduling_control->on_duration_timer = 1;
}
}
/* Update Active Time status of UE
* Based on 36.321 5.7 the differents conditions for the UE to be in Acttive Should be check ONLY
* here for the current subframe. The variable 'UE_scheduling_control->in_active_time' should be updated
* ONLY here. The variable can then be used for testing the actual state of the UE for scheduling purpose.
*/
UE_template = &(UE_info->UE_template[CC_id][UE_id]);
/* (a)synchronous HARQ processes handling for Active Time */
for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > 0) {
harq_active_time_condition = TRUE;
active_time_condition = 2; // for tracing purpose
break;
}
}
/* Active time conditions */
if (UE_scheduling_control->on_duration_timer > 0 ||
UE_scheduling_control->drx_inactivity_timer > 1 ||
harq_active_time_condition ||
UE_template->ul_SR > 0) {
UE_scheduling_control->in_active_time = TRUE;
} else {
UE_scheduling_control->in_active_time = FALSE;
}
/* BEGIN VCD */
if (UE_id == 0) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_ON_DURATION_TIMER, (unsigned long) UE_scheduling_control->on_duration_timer);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) UE_scheduling_control->drx_inactivity_timer);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_SHORT_CYCLE, (unsigned long) UE_scheduling_control->drx_shortCycle_timer);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_LONG_CYCLE, (unsigned long) UE_scheduling_control->drx_longCycle_timer);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) UE_scheduling_control->drx_retransmission_timer[0]);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME, (unsigned long) UE_scheduling_control->in_active_time);
/* For tracing purpose */
if (UE_template->ul_SR > 0) {
active_time_condition = 1;
} else if ((UE_scheduling_control->on_duration_timer > 0) && (active_time_condition == 0)) {
active_time_condition = 3;
} else if ((UE_scheduling_control->drx_inactivity_timer > 1) && (active_time_condition == 0)) {
active_time_condition = 4;
}
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME_CONDITION, (unsigned long) active_time_condition);
}
/* END VCD */
/* DCI0 ongoing timer */
if (UE_scheduling_control->dci0_ongoing_timer > 0) {
if (UE_scheduling_control->dci0_ongoing_timer > 7) {
UE_scheduling_control->dci0_ongoing_timer = 0;
} else {
UE_scheduling_control->dci0_ongoing_timer++;
}
}
} else { // else: CDRX not configured
/* Note: (UL) HARQ RTT timers processing is done here and can be used by other features than CDRX */
/* HARQ RTT timers */
for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) {
if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 0) {
UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id]++;
if (UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] > 8) {
UE_scheduling_control->harq_rtt_timer[CC_id][harq_process_id] = 0;
}
}
if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 0) {
UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id]++;
if (UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] > 4) {
UE_scheduling_control->ul_harq_rtt_timer[CC_id][harq_process_id] = 0;
}
}
} // end loop harq process
} // end else CDRX not configured
/* Increment these timers, they are cleared when we receive an sdu */
UE_scheduling_control->ul_inactivity_timer++;
UE_scheduling_control->cqi_req_timer++;
LOG_D(MAC, "UE %d/%x : ul_inactivity %d, cqi_req %d\n",
UE_id,
rnti,
UE_scheduling_control->ul_inactivity_timer,
UE_scheduling_control->cqi_req_timer);
check_ul_failure(module_idP, CC_id, UE_id, frameP, subframeP);
if (UE_scheduling_control->ue_reestablishment_reject_timer > 0) {
UE_scheduling_control->ue_reestablishment_reject_timer++;
if (UE_scheduling_control->ue_reestablishment_reject_timer >= UE_scheduling_control->ue_reestablishment_reject_timer_thres) {
UE_scheduling_control->ue_reestablishment_reject_timer = 0;
/* Clear reestablish_rnti_map */
if (UE_scheduling_control->ue_reestablishment_reject_timer_thres > 20) {
for (int ue_id_l = 0; ue_id_l < MAX_MOBILES_PER_ENB; ue_id_l++) {
if (reestablish_rnti_map[ue_id_l][0] == rnti) {
/* Clear currentC-RNTI from map */
reestablish_rnti_map[ue_id_l][0] = 0;
reestablish_rnti_map[ue_id_l][1] = 0;
break;
}
}
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rnti, 0, 0,module_idP);
rrc_rlc_remove_ue(&ctxt);
pdcp_remove_UE(&ctxt);
}
/* Note: This should not be done in the MAC! */
/*
for (int ii=0; ii<MAX_MOBILES_PER_ENB; ii++) {
LTE_eNB_ULSCH_t *ulsch = RC.eNB[module_idP][CC_id]->ulsch[ii];
if((ulsch != NULL) && (ulsch->rnti == rnti)) {
void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti);
clean_eNb_ulsch(ulsch);
}
}
for (int ii=0; ii<MAX_MOBILES_PER_ENB; ii++) {
LTE_eNB_DLSCH_t *dlsch = RC.eNB[module_idP][CC_id]->dlsch[ii][0];
if((dlsch != NULL) && (dlsch->rnti == rnti)) {
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti);
clean_eNb_dlsch(dlsch);
}
}
*/
int id;
// clean ULSCH entries for rnti
id = find_ulsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
if (id>=0) clean_eNb_ulsch(RC.eNB[module_idP][CC_id]->ulsch[id]);
// clean DLSCH entries for rnti
id = find_dlsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
if (id>=0) clean_eNb_dlsch(RC.eNB[module_idP][CC_id]->dlsch[id][0]);
for (int j = 0; j < 10; j++) {
nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
ul_req_tmp = &(eNB->UL_req_tmp[CC_id][j].ul_config_request_body);
if (ul_req_tmp) {
int pdu_number = ul_req_tmp->number_of_pdus;
for (int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--) {
if (ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti) {
LOG_I(MAC, "remove UE %x from ul_config_pdu_list %d/%d\n",
rnti,
pdu_index,
pdu_number);
if (pdu_index < pdu_number -1) {
memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index],
&ul_req_tmp->ul_config_pdu_list[pdu_index+1],
(pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
}
ul_req_tmp->number_of_pdus--;
}
} // end for pdu_index
} // end if (ul_req_tmp)
} // end for j
rrc_mac_remove_ue(module_idP,rnti);
} // end if (UE_scheduling_control->ue_reestablishment_reject_timer >= UE_scheduling_control->ue_reestablishment_reject_timer_thres)
} // end if (UE_scheduling_control->ue_reestablishment_reject_timer > 0)
} // end if UE active
} // end for loop on UE_id
#if (!defined(PRE_SCD_THREAD))
if (!NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
void rlc_tick(int, int);
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP);
rlc_tick(frameP, subframeP);
pdcp_run(&ctxt);
pdcp_mbms_run(&ctxt);
rrc_rx_tx(&ctxt, CC_id);
}
#endif
int do_fembms_si=0;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (cc[CC_id].MBMS_flag > 0) {
start_meas(&RC.mac[module_idP]->schedule_mch);
int(*schedule_mch)(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframe) = NULL;
schedule_mch = schedule_MBMS_NFAPI;
if(schedule_mch){
mbsfn_status[CC_id] = schedule_mch(module_idP, CC_id, frameP, subframeP);
}
stop_meas(&RC.mac[module_idP]->schedule_mch);
}
if (cc[CC_id].FeMBMS_flag > 0) {
do_fembms_si = 1;
}
}
static int debug_flag = 0;
void (*schedule_ulsch_p)(module_id_t module_idP, frame_t frameP, sub_frame_t subframe) = NULL;
void (*schedule_ue_spec_p)(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int *mbsfn_flag) = NULL;
if (eNB->scheduler_mode == SCHED_MODE_DEFAULT) {
schedule_ulsch_p = schedule_ulsch;
schedule_ue_spec_p = schedule_dlsch;
} else if (eNB->scheduler_mode == SCHED_MODE_FAIR_RR) {
memset(dlsch_ue_select, 0, sizeof(dlsch_ue_select));
schedule_ulsch_p = schedule_ulsch_fairRR;
schedule_ue_spec_p = schedule_ue_spec_fairRR;
}
if(debug_flag == 0) {
LOG_E(MAC,"SCHED_MODE = %d\n", eNB->scheduler_mode);
debug_flag = 1;
}
/* This schedules MIB */
if(!do_fembms_si/*get_softmodem_params()->fembms*/){
if ((subframeP == 0) && (frameP & 3) == 0)
schedule_mib(module_idP, frameP, subframeP);
}else{
if ((subframeP == 0) && (frameP & 15) == 0 ){
schedule_fembms_mib(module_idP, frameP, subframeP);
//schedule_SI_MBMS(module_idP, frameP, subframeP);
}
}
if (get_softmodem_params()->phy_test == 0) {
/* This schedules SI for legacy LTE and eMTC starting in subframeP */
if(!do_fembms_si/*get_softmodem_params()->fembms*/)
schedule_SI(module_idP, frameP, subframeP);
else
schedule_SI_MBMS(module_idP, frameP, subframeP);
/* This schedules Paging in subframeP */
schedule_PCH(module_idP,frameP,subframeP);
/* This schedules Random-Access for legacy LTE and eMTC starting in subframeP */
schedule_RA(module_idP, frameP, subframeP);
/* Copy previously scheduled UL resources (ULSCH + HARQ) */
copy_ulreq(module_idP, frameP, subframeP);
/* This schedules SRS in subframeP */
schedule_SRS(module_idP, frameP, subframeP);
/* This schedules ULSCH in subframeP (dci0) */
if (schedule_ulsch_p != NULL) {
schedule_ulsch_p(module_idP, frameP, subframeP);
} else {
LOG_E(MAC," %s %d: schedule_ulsch_p is NULL, function not called\n",
__FILE__,
__LINE__);
}
/* This schedules UCI_SR in subframeP */
schedule_SR(module_idP, frameP, subframeP);
/* This schedules UCI_CSI in subframeP */
schedule_CSI(module_idP, frameP, subframeP);
/* This schedules DLSCH in subframeP for BR UE*/
schedule_ue_spec_br(module_idP, frameP, subframeP);
/* This schedules DLSCH in subframeP */
if (schedule_ue_spec_p != NULL) {
schedule_ue_spec_p(module_idP, frameP, subframeP, mbsfn_status);
} else {
LOG_E(MAC," %s %d: schedule_ue_spec_p is NULL, function not called\n",
__FILE__,
__LINE__);
}
} else {
schedule_ulsch_phy_test(module_idP,frameP,subframeP);
schedule_ue_spec_phy_test(module_idP,frameP,subframeP,mbsfn_status);
}
/* Allocate CCEs for good after scheduling is done */
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (cc[CC_id].tdd_Config == NULL || !(is_UL_sf(&cc[CC_id],subframeP))) {
int rc = allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2);
if (rc < 0)
LOG_E(MAC, "%s() %4d.%d ERROR ALLOCATING CCEs\n", __func__, frameP, subframeP);
}
}
if (flexran_agent_get_mac_xface(module_idP) && subframeP == 9) {
flexran_agent_slice_update(module_idP);
}
if (flexran_agent_get_mac_xface(module_idP))
flexran_agent_get_mac_xface(module_idP)->flexran_agent_notify_tick(module_idP);
stop_meas(&(eNB->eNB_scheduler));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_OUT);
}