merge develop
This commit is contained in:
@@ -1110,6 +1110,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
printf("minTXRXTIMEpdsch %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).minRXTXTIMEpdsch = *GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
|
||||
printf("minTXRXTIMEpdsch %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).minRXTXTIMEpdsch = *GNBParamList.paramarray[i][GNB_MINRXTXTIMEPDSCH_IDX].iptr;
|
||||
printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
|
||||
NRRRC_CONFIGURATION_REQ (msg_p).scc = scc;
|
||||
|
||||
@@ -149,7 +149,7 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \
|
||||
{GNB_CONFIG_STRING_MINRXTXTIMEPDSCH, NULL, 0, iptr:NULL, defintval:2, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0} \
|
||||
{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0} \
|
||||
}
|
||||
|
||||
#define GNB_GNB_ID_IDX 0
|
||||
|
||||
@@ -192,8 +192,13 @@ uint8_t get_transformPrecoding(const NR_BWP_UplinkCommon_t *initialUplinkBWP,
|
||||
uint8_t configuredGrant);
|
||||
|
||||
void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP,
|
||||
const int CC_idP,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const rnti_t rntiP) ;
|
||||
const int CC_idP,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const rnti_t rntiP);
|
||||
|
||||
void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const rnti_t rntiP);
|
||||
#endif
|
||||
|
||||
@@ -299,9 +299,6 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot);
|
||||
|
||||
void update_harq_status(nr_downlink_indication_t *dl_info,
|
||||
int pdu_id);
|
||||
|
||||
uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
|
||||
@@ -1232,14 +1232,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
uint8_t feedback_ti =
|
||||
ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0];
|
||||
|
||||
// set the harq status at MAC for feedback
|
||||
set_harq_status(mac,dci->pucch_resource_indicator,
|
||||
dci->harq_pid,
|
||||
dlsch_config_pdu_1_1->accumulated_delta_PUCCH,
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
dci_ind->n_CCE,dci_ind->N_CCE,0,
|
||||
frame,slot);
|
||||
AssertFatal(feedback_ti>=DURATION_RX_TO_TX,"PDSCH to HARQ feedback time (%d) cannot be less than DURATION_RX_TO_TX (%d)\n",
|
||||
feedback_ti,DURATION_RX_TO_TX);
|
||||
|
||||
// set the harq status at MAC for feedback
|
||||
set_harq_status(mac,dci->pucch_resource_indicator,
|
||||
dci->harq_pid,
|
||||
dlsch_config_pdu_1_1->accumulated_delta_PUCCH,
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
dci_ind->n_CCE,dci_ind->N_CCE,
|
||||
0, frame,slot);
|
||||
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
|
||||
LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
|
||||
@@ -1331,25 +1334,6 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
|
||||
|
||||
void update_harq_status(nr_downlink_indication_t *dl_info, int pdu_id) {
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id);
|
||||
uint8_t harq_pid = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid;
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid];
|
||||
|
||||
if (current_harq->active) {
|
||||
current_harq->ack = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack;
|
||||
current_harq->ack_received = true;
|
||||
LOG_D(PHY,"Updating harq_status for harq_id %d,ack/nak %d\n",harq_pid,current_harq->ack);
|
||||
|
||||
}
|
||||
else {
|
||||
//shouldn't get here
|
||||
LOG_E(MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
|
||||
int slot,
|
||||
uint16_t rnti,
|
||||
@@ -2123,7 +2107,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
|
||||
uint32_t V_temp = 0;
|
||||
uint32_t V_temp2 = 0;
|
||||
int O_ACK = 0;
|
||||
int o_ACK = 0;
|
||||
uint8_t o_ACK = 0;
|
||||
int O_bit_number_cw0 = 0;
|
||||
int O_bit_number_cw1 = 0;
|
||||
|
||||
@@ -2151,6 +2135,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
|
||||
o_ACK = o_ACK | (ack_data[0][m] << O_bit_number_cw0);
|
||||
LOG_D(MAC,"m %d bit number %d o_ACK %d\n",m,O_bit_number_cw0,o_ACK);
|
||||
}
|
||||
|
||||
if (V_temp2 < V_temp) {
|
||||
@@ -2169,8 +2154,11 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
|
||||
return (0);
|
||||
}
|
||||
|
||||
reverse_n_bits(&o_ACK,number_harq_feedback);
|
||||
pucch->ack_payload = o_ACK;
|
||||
|
||||
LOG_D(MAC,"frame %d slot %d pucch acknack payload %d\n",frame,slot,o_ACK);
|
||||
|
||||
return(number_harq_feedback);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,12 @@ static prach_association_pattern_t prach_assoc_pattern;
|
||||
static ssb_list_info_t ssb_list;
|
||||
|
||||
void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type){
|
||||
// clear ul_config for new frame/slot
|
||||
if ((ul_config->slot != slot_tx || ul_config->sfn != frame_tx) && ul_config->number_pdus != 0) {
|
||||
LOG_D(MAC, "%d.%d %d.%d f clear ul_config %p t %d pdu %d\n", frame_tx, slot_tx, ul_config->sfn, ul_config->slot, ul_config, pdu_type, ul_config->number_pdus);
|
||||
ul_config->number_pdus = 0;
|
||||
memset(ul_config->ul_config_list, 0, sizeof(ul_config->ul_config_list));
|
||||
}
|
||||
ul_config->ul_config_list[ul_config->number_pdus].pdu_type = pdu_type;
|
||||
ul_config->slot = slot_tx;
|
||||
ul_config->sfn = frame_tx;
|
||||
@@ -931,8 +937,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
} else if (ul_info) {
|
||||
|
||||
int cc_id = ul_info->cc_id;
|
||||
frame_t rx_frame = ul_info->frame_rx;
|
||||
slot_t rx_slot = ul_info->slot_rx;
|
||||
//frame_t rx_frame = ul_info->frame_rx;
|
||||
//slot_t rx_slot = ul_info->slot_rx;
|
||||
frame_t frame_tx = ul_info->frame_tx;
|
||||
slot_t slot_tx = ul_info->slot_tx;
|
||||
module_id_t mod_id = ul_info->module_id;
|
||||
@@ -1020,7 +1026,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
}
|
||||
pthread_mutex_unlock(&ul_config->mutex_ul_config); // avoid double lock
|
||||
|
||||
fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, rx_frame, rx_slot, ul_info->thread_id);
|
||||
fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, frame_tx, slot_tx, ul_info->thread_id);
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
@@ -2153,7 +2159,8 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in
|
||||
|
||||
if (N_UCI > 0) {
|
||||
|
||||
pucch->resource_set_id = find_pucch_resource_set(mac, N_UCI);
|
||||
LOG_D(NR_MAC,"%d.%d configure pucch, O_SR %d, O_ACK %d, O_CSI %d\n",frameP,slotP,O_SR,O_ACK,O_CSI);
|
||||
pucch->resource_set_id = find_pucch_resource_set(mac, O_ACK + O_CSI);
|
||||
select_pucch_resource(mac, pucch);
|
||||
fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP);
|
||||
pthread_mutex_lock(&ul_config->mutex_ul_config);
|
||||
|
||||
@@ -520,12 +520,13 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[0];
|
||||
RC.nrmac[Mod_idP]->sib1_tda = sib1_tda;
|
||||
for (int n=0;n<NR_NB_RA_PROC_MAX;n++ ) {
|
||||
cc->ra[n].cfra = false;
|
||||
cc->ra[n].rnti = 0;
|
||||
cc->ra[n].preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES;
|
||||
cc->ra[n].preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t));
|
||||
for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++)
|
||||
cc->ra[n].preambles.preamble_list[i] = i;
|
||||
cc->ra[n].cfra = false;
|
||||
cc->ra[n].msg3_dcch_dtch = false;
|
||||
cc->ra[n].rnti = 0;
|
||||
cc->ra[n].preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES;
|
||||
cc->ra[n].preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t));
|
||||
for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++)
|
||||
cc->ra[n].preambles.preamble_list[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,6 +604,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++)
|
||||
ra->preambles.preamble_list[i] = i;
|
||||
}
|
||||
ra->msg3_dcch_dtch = false;
|
||||
LOG_I(NR_MAC,"Added new RA process for UE RNTI %04x with initial CellGroup\n", rnti);
|
||||
} else { // CellGroup has been updated
|
||||
const int UE_id = find_nr_UE_id(Mod_idP,rnti);
|
||||
|
||||
@@ -373,7 +373,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
schedule_nr_prach(module_idP, f, s);
|
||||
}
|
||||
|
||||
// This schedule SR
|
||||
// This schedule SR
|
||||
nr_sr_reporting(module_idP, frame, slot);
|
||||
|
||||
// Schedule CSI-RS transmission
|
||||
|
||||
@@ -802,7 +802,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t
|
||||
AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n");
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac, NULL, coreset, aggregation_level, 0, 0, nr_of_candidates);
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1178,7 +1178,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n");
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac, bwp, coreset, aggregation_level,0,0,nr_of_candidates);
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1215,7 +1215,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
dl_req->nPDUs+=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
LOG_I(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%x, state %d, CoreSetType %d\n",
|
||||
LOG_I(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%04x, state %d, CoreSetType %d\n",
|
||||
module_idP, CC_id, frameP, slotP, ra->RA_rnti, ra->state,pdcch_pdu_rel15->CoreSetType);
|
||||
|
||||
// SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control
|
||||
@@ -1405,6 +1405,12 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
|
||||
AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n");
|
||||
|
||||
rnti_t tc_rnti = ra->rnti;
|
||||
// If UE is known by the network, C-RNTI to be used instead of TC-RNTI
|
||||
if(ra->msg3_dcch_dtch) {
|
||||
ra->rnti = ra->crnti;
|
||||
}
|
||||
|
||||
int UE_id = find_nr_UE_id(module_idP, ra->rnti);
|
||||
NR_UE_info_t *UE_info = &nr_mac->UE_info;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
@@ -1438,6 +1444,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
harq->is_waiting = true;
|
||||
ra->harq_pid = current_harq_pid;
|
||||
|
||||
// Remove UE associated to TC-RNTI
|
||||
if(harq->round==0 && ra->msg3_dcch_dtch) {
|
||||
mac_remove_nr_ue(module_idP, tc_rnti);
|
||||
}
|
||||
|
||||
// get CCEindex, needed also for PUCCH and then later for PDCCH
|
||||
uint8_t aggregation_level;
|
||||
uint8_t nr_of_candidates;
|
||||
@@ -1449,7 +1460,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n");
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac, bwp, coreset, aggregation_level,0,0,nr_of_candidates);
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1473,15 +1484,21 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
uint8_t *buf = (uint8_t *) harq->tb;
|
||||
// Bytes to be transmitted
|
||||
if (harq->round == 0) {
|
||||
uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id);
|
||||
LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length);
|
||||
uint16_t mac_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, CCCH, ra->rnti, 1, &buf[mac_pdu_length+2]);
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->R = 0;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->F = 0;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->LCID = DL_SCH_LCID_CCCH;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->L = mac_sdu_length;
|
||||
ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT);
|
||||
LOG_D(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, (int)sizeof(NR_MAC_SUBHEADER_SHORT), ra->mac_pdu_length);
|
||||
if (ra->msg3_dcch_dtch) {
|
||||
// If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful if the UE receives a PDCCH transmission which has its CRC bits scrambled by the C-RNTI
|
||||
// Just send padding LCID
|
||||
ra->mac_pdu_length = 0;
|
||||
} else {
|
||||
uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id);
|
||||
LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length);
|
||||
uint16_t mac_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, CCCH, ra->rnti, 1, &buf[mac_pdu_length+2]);
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->R = 0;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->F = 0;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->LCID = DL_SCH_LCID_CCCH;
|
||||
((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->L = mac_sdu_length;
|
||||
ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT);
|
||||
LOG_D(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, (int)sizeof(NR_MAC_SUBHEADER_SHORT), ra->mac_pdu_length);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate number of symbols
|
||||
@@ -1741,8 +1758,23 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
|
||||
LOG_D(NR_MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity);
|
||||
LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci);
|
||||
|
||||
ra->state = WAIT_Msg4_ACK;
|
||||
LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
if(ra->msg3_dcch_dtch) {
|
||||
// If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful upon transmission of PDCCH
|
||||
LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) CBRA procedure succeeded!\n", UE_id, ra->rnti);
|
||||
nr_clear_ra_proc(module_idP, CC_id, frameP, ra);
|
||||
UE_info->active[UE_id] = true;
|
||||
UE_info->Msg4_ACKed[UE_id] = true;
|
||||
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
add_tail_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid);
|
||||
harq->round = 0;
|
||||
harq->ndi ^= 1;
|
||||
} else {
|
||||
ra->state = WAIT_Msg4_ACK;
|
||||
LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1756,23 +1788,22 @@ void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_fram
|
||||
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
|
||||
NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
|
||||
|
||||
LOG_D(NR_MAC, "ue %d, rnti %d, harq is waiting %d, round %d, frame %d %d, harq id %d\n", UE_id, ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid);
|
||||
LOG_D(NR_MAC, "ue %d, rnti 0x%04x, harq is waiting %d, round %d, frame %d %d, harq id %d\n", UE_id, ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid);
|
||||
|
||||
if (harq->is_waiting == 0) {
|
||||
if (harq->round == 0) {
|
||||
if (stats->dlsch_errors == 0) {
|
||||
LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti);
|
||||
nr_clear_ra_proc(module_id, CC_id, frame, ra);
|
||||
UE_info->active[UE_id] = true;
|
||||
UE_info->Msg4_ACKed[UE_id] = true;
|
||||
if(sched_ctrl->retrans_dl_harq.head>=0)
|
||||
remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
|
||||
}
|
||||
else {
|
||||
LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) RA Procedure failed at Msg4!\n", UE_id, ra->rnti);
|
||||
nr_mac_remove_ra_rnti(module_id, ra->rnti);
|
||||
nr_clear_ra_proc(module_id, CC_id, frame, ra);
|
||||
mac_remove_nr_ue(module_id, ra->rnti);
|
||||
}
|
||||
|
||||
nr_clear_ra_proc(module_id, CC_id, frame, ra);
|
||||
if(sched_ctrl->retrans_dl_harq.head >= 0) {
|
||||
remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1790,6 +1821,8 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t
|
||||
ra->timing_offset = 0;
|
||||
ra->RRC_timer = 20;
|
||||
ra->msg3_round = 0;
|
||||
ra->msg3_dcch_dtch = false;
|
||||
ra->crnti = 0;
|
||||
if(ra->cfra == false) {
|
||||
ra->rnti = 0;
|
||||
}
|
||||
|
||||
@@ -753,7 +753,7 @@ void pf_dl(module_id_t module_id,
|
||||
|
||||
/* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
|
||||
* allocation after CCE alloc fail would be more complex) */
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1,0);
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1, 0);
|
||||
if (alloc<0) {
|
||||
LOG_D(NR_MAC,
|
||||
"%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
|
||||
@@ -348,7 +348,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
__func__,
|
||||
UE_id);
|
||||
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1,0);
|
||||
const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(MAC,
|
||||
"%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
|
||||
@@ -1925,7 +1925,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG
|
||||
{
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_idP]->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info;
|
||||
LOG_I(NR_MAC, "[gNB %d] Adding UE with rnti %x (num_UEs %d)\n",
|
||||
LOG_I(NR_MAC, "[gNB %d] Adding UE with rnti 0x%04x (num_UEs %d)\n",
|
||||
mod_idP,
|
||||
rntiP,
|
||||
UE_info->num_UEs);
|
||||
@@ -2063,7 +2063,7 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
|
||||
destroy_nr_list(&sched_ctrl->available_ul_harq);
|
||||
destroy_nr_list(&sched_ctrl->feedback_ul_harq);
|
||||
destroy_nr_list(&sched_ctrl->retrans_ul_harq);
|
||||
LOG_I(NR_MAC, "[gNB %d] Remove NR UE_id %d : rnti %x\n",
|
||||
LOG_I(NR_MAC, "[gNB %d] Remove NR UE_id %d: rnti 0x%04x\n",
|
||||
mod_id,
|
||||
UE_id,
|
||||
rnti);
|
||||
@@ -2203,6 +2203,7 @@ void get_pdsch_to_harq_feedback(int Mod_idP,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nr_csirs_scheduling(int Mod_idP,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
|
||||
@@ -1099,6 +1099,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
DevAssert(harq->is_waiting);
|
||||
const int8_t pid = sched_ctrl->feedback_dl_harq.head;
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
LOG_D(NR_MAC,"bit %d pid %d ack/nack %d\n",harq_bit,pid,harq_value);
|
||||
handle_dl_harq(mod_id, UE_id, pid, harq_value == 0 && harq_confidence == 0);
|
||||
if (harq_confidence == 1) UE_info->mac_stats[UE_id].pucch0_DTX++;
|
||||
}
|
||||
@@ -1187,7 +1188,7 @@ int nr_acknack_scheduling(int mod_id,
|
||||
const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
|
||||
const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots;
|
||||
const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period);
|
||||
const int first_ul_slot_period = first_ul_slot_tdd%nr_slots_period;
|
||||
const int first_ul_slot_period = tdd->nrofDownlinkSlots;
|
||||
const int CC_id = 0;
|
||||
NR_sched_pucch_t *csi_pucch;
|
||||
|
||||
@@ -1236,11 +1237,11 @@ int nr_acknack_scheduling(int mod_id,
|
||||
&& !csi_pucch->simultaneous_harqcsi) {
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
||||
memset(csi_pucch, 0, sizeof(*csi_pucch));
|
||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||
if(((s + 1)%nr_slots_period) == 0)
|
||||
pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame;
|
||||
pucch->frame = pucch->ul_slot == n_slots_frame - 1 ? (pucch->frame + 1) % 1024 : pucch->frame;
|
||||
if(((pucch->ul_slot + 1)%nr_slots_period) == 0)
|
||||
pucch->ul_slot = (pucch->ul_slot + 1 + first_ul_slot_period) % n_slots_frame;
|
||||
else
|
||||
pucch->ul_slot = (s + 1) % n_slots_frame;
|
||||
pucch->ul_slot = (pucch->ul_slot + 1) % n_slots_frame;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1264,7 +1265,6 @@ int nr_acknack_scheduling(int mod_id,
|
||||
|
||||
int max_fb_time = 0;
|
||||
get_pdsch_to_harq_feedback(mod_id, UE_id, bwp_Id, ss_type, &max_fb_time, pdsch_to_harq_feedback);
|
||||
int max_absslot = frame*n_slots_frame + slot + max_fb_time;
|
||||
|
||||
LOG_D(NR_MAC,"pucch_acknak 1b. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n",frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c);
|
||||
/* there is a HARQ. Check whether we can use it for this ACKNACK */
|
||||
@@ -1273,7 +1273,10 @@ int nr_acknack_scheduling(int mod_id,
|
||||
// Find the right timing_indicator value.
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot)
|
||||
int diff = pucch->ul_slot - slot;
|
||||
if (diff<0)
|
||||
diff += n_slots_frame;
|
||||
if (pdsch_to_harq_feedback[i] == diff)
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
@@ -1303,8 +1306,10 @@ int nr_acknack_scheduling(int mod_id,
|
||||
LOG_D(NR_MAC,"pucch_acknak : %d.%d DAI = 0, looking for new pucch occasion\n",frame,slot);
|
||||
/* we need to find a new PUCCH occasion */
|
||||
|
||||
/*Inizialization of timing information*/
|
||||
if (pucch->frame == 0 && pucch->ul_slot == 0) {
|
||||
/*(Re)Inizialization of timing information*/
|
||||
if ((pucch->frame == 0 && pucch->ul_slot == 0) ||
|
||||
((pucch->frame*n_slots_frame + pucch->ul_slot) <
|
||||
(frame*n_slots_frame + slot))) {
|
||||
AssertFatal(pucch->sr_flag + pucch->dai_c == 0,
|
||||
"expected no SR/AckNack for UE %d in %4d.%2d, but has %d/%d for %4d.%2d\n",
|
||||
UE_id, frame, slot, pucch->sr_flag, pucch->dai_c, pucch->frame, pucch->ul_slot);
|
||||
@@ -1314,13 +1319,16 @@ int nr_acknack_scheduling(int mod_id,
|
||||
|
||||
// Find the right timing_indicator value.
|
||||
int ind_found = -1;
|
||||
// while we are within the feedback limits and it has not been
|
||||
while ((pucch->frame*n_slots_frame + pucch->ul_slot) <= max_absslot) {
|
||||
// while we are within the feedback limits
|
||||
while ((n_slots_frame + pucch->ul_slot - slot) % n_slots_frame <= max_fb_time) {
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
LOG_D(NR_MAC,"pdsch_to_harq_feedback[%d] = %d (pucch->ul_slot %d - slot %d)\n",
|
||||
i,pdsch_to_harq_feedback[i],pucch->ul_slot,slot);
|
||||
if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot) {
|
||||
int diff = pucch->ul_slot - slot;
|
||||
if (diff<0)
|
||||
diff += n_slots_frame;
|
||||
if (pdsch_to_harq_feedback[i] == diff) {
|
||||
ind_found = i;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -298,6 +298,17 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_C_RNTI:
|
||||
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
|
||||
if (ra->state >= WAIT_Msg3 && ra->rnti == UE_info->rnti[UE_id]) {
|
||||
ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF);
|
||||
ra->msg3_dcch_dtch = true;
|
||||
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//38.321 section 6.1.3.2
|
||||
//fixed length
|
||||
mac_ce_len = 2;
|
||||
@@ -365,10 +376,25 @@ int nr_process_mac_pdu(module_id_t module_idP,
|
||||
mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L;
|
||||
mac_subheader_len = 2;
|
||||
}
|
||||
if (UE_info->CellGroup[UE_id]) {
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: %d \n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len, UE_info->rnti[UE_id]);
|
||||
|
||||
rnti_t crnti = UE_info->rnti[UE_id];
|
||||
int UE_idx = UE_id;
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
|
||||
if (ra->state >= WAIT_Msg3 && ra->rnti == UE_info->rnti[UE_id]) {
|
||||
uint8_t *next_subpduP = pduP + mac_subheader_len + mac_sdu_len;
|
||||
if ((pduP[mac_subheader_len+mac_sdu_len] & 0x3F) == UL_SCH_LCID_C_RNTI) {
|
||||
crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF);
|
||||
UE_idx = find_nr_UE_id(module_idP, crnti);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UE_info->CellGroup[UE_idx]) {
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: 0x%04x \n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len, crnti);
|
||||
mac_rlc_data_ind(module_idP,
|
||||
UE_info->rnti[UE_id],
|
||||
crnti,
|
||||
module_idP,
|
||||
frameP,
|
||||
ENB_FLAG_YES,
|
||||
@@ -533,7 +559,7 @@ void handle_nr_ul_harq(const int CC_idP,
|
||||
ra->rnti == crc_pdu->rnti)
|
||||
return;
|
||||
}
|
||||
LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUSCH\n", __func__, crc_pdu->rnti);
|
||||
LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti);
|
||||
return;
|
||||
}
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
@@ -541,7 +567,7 @@ void handle_nr_ul_harq(const int CC_idP,
|
||||
int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
|
||||
while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
|
||||
LOG_W(NR_MAC,
|
||||
"Unexpected ULSCH HARQ PID %d (have %d) for RNTI %04x (ignore this warning for RA)\n",
|
||||
"Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x (ignore this warning for RA)\n",
|
||||
crc_pdu->harq_id,
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
@@ -752,13 +778,13 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"reset RA state information for RA-RNTI %04x/index %d\n",
|
||||
"reset RA state information for RA-RNTI 0x%04x/index %d\n",
|
||||
ra->rnti,
|
||||
i);
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI %04x\n",
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI 0x%04x\n",
|
||||
gnb_mod_idP,
|
||||
current_rnti,
|
||||
UE_id,
|
||||
@@ -796,7 +822,26 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
ra->state = Msg4;
|
||||
ra->Msg4_frame = (frameP + 2) % 1024;
|
||||
ra->Msg4_slot = 1;
|
||||
LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI %04x (state %d, frame %d, slot %d)\n", ra->rnti, ra->state, ra->Msg4_frame, ra->Msg4_slot);
|
||||
|
||||
if (ra->msg3_dcch_dtch) {
|
||||
// Check if the UE identified by C-RNTI still exists at the gNB
|
||||
int UE_id_C = find_nr_UE_id(gnb_mod_idP, ra->crnti);
|
||||
if (UE_id_C < 0) {
|
||||
// The UE identified by C-RNTI no longer exists at the gNB
|
||||
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented
|
||||
mac_remove_nr_ue(gnb_mod_idP, ra->rnti);
|
||||
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
|
||||
return;
|
||||
} else {
|
||||
// The UE identified by C-RNTI still exists at the gNB
|
||||
// Reset uplink failure flags/counters/timers at MAC and at RRC so gNB will resume again scheduling resources for this UE
|
||||
UE_info->UE_sched_ctrl[UE_id_C].pusch_consecutive_dtx_cnt = 0;
|
||||
UE_info->UE_sched_ctrl[UE_id_C].ul_failure = 0;
|
||||
nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->crnti);
|
||||
}
|
||||
}
|
||||
LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d, frame %d, slot %d)\n",
|
||||
(ra->msg3_dcch_dtch?ra->crnti:ra->rnti), ra->state, ra->Msg4_frame, ra->Msg4_slot);
|
||||
}
|
||||
else {
|
||||
nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti);
|
||||
|
||||
@@ -155,6 +155,8 @@ typedef struct {
|
||||
uint8_t msg3_cqireq;
|
||||
/// Round of Msg3 HARQ
|
||||
uint8_t msg3_round;
|
||||
/// Flag to indicate if Msg3 carries a DCCH or DTCH message
|
||||
bool msg3_dcch_dtch;
|
||||
/// TBS used for Msg4
|
||||
int msg4_TBsize;
|
||||
/// MCS used for Msg4
|
||||
|
||||
@@ -215,6 +215,182 @@ void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
|
||||
/* rlc_data_req queue - end */
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* pdcp_data_ind thread - begin */
|
||||
/****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
protocol_ctxt_t ctxt_pP;
|
||||
srb_flag_t srb_flagP;
|
||||
MBMS_flag_t MBMS_flagP;
|
||||
rb_id_t rb_id;
|
||||
sdu_size_t sdu_buffer_size;
|
||||
mem_block_t *sdu_buffer;
|
||||
} pdcp_data_ind_queue_item;
|
||||
|
||||
#define PDCP_DATA_IND_QUEUE_SIZE 10000
|
||||
|
||||
typedef struct {
|
||||
pdcp_data_ind_queue_item q[PDCP_DATA_IND_QUEUE_SIZE];
|
||||
volatile int start;
|
||||
volatile int length;
|
||||
pthread_mutex_t m;
|
||||
pthread_cond_t c;
|
||||
} pdcp_data_ind_queue;
|
||||
|
||||
static pdcp_data_ind_queue pq;
|
||||
|
||||
static void do_pdcp_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
{
|
||||
nr_pdcp_ue_t *ue;
|
||||
nr_pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
//ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 ||
|
||||
ctxt_pP->configured != 1 ||
|
||||
ctxt_pP->brOption != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti),
|
||||
T_INT(rb_id), T_INT(sdu_buffer_size));
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti);
|
||||
|
||||
if (srb_flagP == 1) {
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
} else {
|
||||
if (rb_id < 1 || rb_id > 5)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size);
|
||||
} else {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %ld, srb_flag %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
|
||||
free_mem_block(sdu_buffer, __FUNCTION__);
|
||||
}
|
||||
|
||||
static void *pdcp_data_ind_thread(void *_)
|
||||
{
|
||||
int i;
|
||||
|
||||
pthread_setname_np(pthread_self(), "PDCP data ind");
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&pq.m) != 0) abort();
|
||||
while (pq.length == 0)
|
||||
if (pthread_cond_wait(&pq.c, &pq.m) != 0) abort();
|
||||
i = pq.start;
|
||||
if (pthread_mutex_unlock(&pq.m) != 0) abort();
|
||||
|
||||
do_pdcp_data_ind(&pq.q[i].ctxt_pP,
|
||||
pq.q[i].srb_flagP,
|
||||
pq.q[i].MBMS_flagP,
|
||||
pq.q[i].rb_id,
|
||||
pq.q[i].sdu_buffer_size,
|
||||
pq.q[i].sdu_buffer);
|
||||
|
||||
if (pthread_mutex_lock(&pq.m) != 0) abort();
|
||||
|
||||
pq.length--;
|
||||
pq.start = (pq.start + 1) % PDCP_DATA_IND_QUEUE_SIZE;
|
||||
|
||||
if (pthread_cond_signal(&pq.c) != 0) abort();
|
||||
if (pthread_mutex_unlock(&pq.m) != 0) abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void init_nr_pdcp_data_ind_queue(void)
|
||||
{
|
||||
pthread_t t;
|
||||
|
||||
pthread_mutex_init(&pq.m, NULL);
|
||||
pthread_cond_init(&pq.c, NULL);
|
||||
|
||||
if (pthread_create(&t, NULL, pdcp_data_ind_thread, NULL) != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void enqueue_pdcp_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
{
|
||||
int i;
|
||||
int logged = 0;
|
||||
|
||||
if (pthread_mutex_lock(&pq.m) != 0) abort();
|
||||
while (pq.length == PDCP_DATA_IND_QUEUE_SIZE) {
|
||||
if (!logged) {
|
||||
logged = 1;
|
||||
LOG_W(PDCP, "%s: pdcp_data_ind queue is full\n", __FUNCTION__);
|
||||
}
|
||||
if (pthread_cond_wait(&pq.c, &pq.m) != 0) abort();
|
||||
}
|
||||
|
||||
i = (pq.start + pq.length) % PDCP_DATA_IND_QUEUE_SIZE;
|
||||
pq.length++;
|
||||
|
||||
pq.q[i].ctxt_pP = *ctxt_pP;
|
||||
pq.q[i].srb_flagP = srb_flagP;
|
||||
pq.q[i].MBMS_flagP = MBMS_flagP;
|
||||
pq.q[i].rb_id = rb_id;
|
||||
pq.q[i].sdu_buffer_size = sdu_buffer_size;
|
||||
pq.q[i].sdu_buffer = sdu_buffer;
|
||||
|
||||
if (pthread_cond_signal(&pq.c) != 0) abort();
|
||||
if (pthread_mutex_unlock(&pq.m) != 0) abort();
|
||||
}
|
||||
|
||||
boolean_t pdcp_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
{
|
||||
enqueue_pdcp_data_ind(ctxt_pP,
|
||||
srb_flagP,
|
||||
MBMS_flagP,
|
||||
rb_id,
|
||||
sdu_buffer_size,
|
||||
sdu_buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* pdcp_data_ind thread - end */
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/* hacks to be cleaned up at some point - begin */
|
||||
/****************************************************************************/
|
||||
@@ -375,6 +551,7 @@ void pdcp_layer_init(void)
|
||||
init_nr_rlc_data_req_queue();
|
||||
}
|
||||
|
||||
init_nr_pdcp_data_ind_queue();
|
||||
nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
@@ -639,62 +816,6 @@ srb_found:
|
||||
}
|
||||
}
|
||||
|
||||
boolean_t pdcp_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
{
|
||||
nr_pdcp_ue_t *ue;
|
||||
nr_pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
//ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 ||
|
||||
ctxt_pP->configured != 1 ||
|
||||
ctxt_pP->brOption != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti),
|
||||
T_INT(rb_id), T_INT(sdu_buffer_size));
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti);
|
||||
|
||||
if (srb_flagP == 1) {
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
} else {
|
||||
if (rb_id < 1 || rb_id > 5)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size);
|
||||
} else {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %ld, srb_flag %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
|
||||
free_mem_block(sdu_buffer, __FUNCTION__);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
|
||||
{
|
||||
MessageDef *msg_p;
|
||||
|
||||
@@ -63,6 +63,8 @@ typedef struct nr_rlc_entity_t {
|
||||
void (*max_retx_reached)(void *max_retx_reached_data,
|
||||
struct nr_rlc_entity_t *entity);
|
||||
void *max_retx_reached_data;
|
||||
/* buffer status computation */
|
||||
nr_rlc_entity_buffer_status_t bstatus;
|
||||
} nr_rlc_entity_t;
|
||||
|
||||
nr_rlc_entity_t *new_nr_rlc_entity_am(
|
||||
|
||||
@@ -28,6 +28,19 @@
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
|
||||
static int compute_pdu_header_size(nr_rlc_entity_am_t *entity,
|
||||
nr_rlc_sdu_segment_t *sdu)
|
||||
{
|
||||
int header_size = 2;
|
||||
/* one more byte if SN field length is 18 */
|
||||
if (entity->sn_field_length == 18)
|
||||
header_size++;
|
||||
/* two more bytes for SO if SDU segment is not the first */
|
||||
if (!sdu->is_first) header_size += 2;
|
||||
return header_size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* PDU RX functions */
|
||||
/*************************************************************************/
|
||||
@@ -114,6 +127,10 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity,
|
||||
nr_rlc_sdu_segment_list_append(&entity->retransmit_list,
|
||||
&entity->retransmit_end,
|
||||
cur);
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.retx_size += compute_pdu_header_size(entity, cur)
|
||||
+ cur->size;
|
||||
}
|
||||
|
||||
/* checks that all the bytes of the SDU sn have been received (but SDU
|
||||
@@ -351,6 +368,9 @@ static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn)
|
||||
}
|
||||
/* remove from retransmit list */
|
||||
prev->next = cur->next;
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.retx_size -= compute_pdu_header_size(entity, cur)
|
||||
+ cur->size;
|
||||
/* put the PDU in the ack list */
|
||||
entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity,
|
||||
entity->ack_list, cur);
|
||||
@@ -840,19 +860,6 @@ static int serialize_sdu(nr_rlc_entity_am_t *entity,
|
||||
return encoder.byte + sdu->size;
|
||||
}
|
||||
|
||||
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
|
||||
static int compute_pdu_header_size(nr_rlc_entity_am_t *entity,
|
||||
nr_rlc_sdu_segment_t *sdu)
|
||||
{
|
||||
int header_size = 2;
|
||||
/* one more byte if SN field length is 18 */
|
||||
if (entity->sn_field_length == 18)
|
||||
header_size++;
|
||||
/* two more bytes for SO if SDU segment is not the first */
|
||||
if (!sdu->is_first) header_size += 2;
|
||||
return header_size;
|
||||
}
|
||||
|
||||
/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
|
||||
* bytes
|
||||
* - modifies SDU/SDU segment to become an SDU segment
|
||||
@@ -1426,8 +1433,12 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer,
|
||||
|
||||
sdu->next = NULL;
|
||||
|
||||
/* segment if necessary */
|
||||
pdu_size = pdu_header_size + sdu->size;
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.retx_size -= pdu_size;
|
||||
|
||||
/* segment if necessary */
|
||||
if (pdu_size > size) {
|
||||
nr_rlc_sdu_segment_t *next_sdu;
|
||||
next_sdu = resegment(sdu, entity, size);
|
||||
@@ -1436,6 +1447,9 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer,
|
||||
entity->retransmit_list = next_sdu;
|
||||
if (entity->retransmit_end == NULL)
|
||||
entity->retransmit_end = entity->retransmit_list;
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.retx_size += compute_pdu_header_size(entity, next_sdu)
|
||||
+ next_sdu->size;
|
||||
}
|
||||
|
||||
/* put SDU/SDU segment in the wait list */
|
||||
@@ -1479,11 +1493,15 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
|
||||
|
||||
sdu->next = NULL;
|
||||
|
||||
pdu_size = pdu_header_size + sdu->size;
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= pdu_size;
|
||||
|
||||
/* assign SN to SDU */
|
||||
sdu->sdu->sn = entity->tx_next;
|
||||
|
||||
/* segment if necessary */
|
||||
pdu_size = pdu_header_size + sdu->size;
|
||||
if (pdu_size > size) {
|
||||
nr_rlc_sdu_segment_t *next_sdu;
|
||||
next_sdu = resegment(sdu, entity, size);
|
||||
@@ -1492,6 +1510,9 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
|
||||
entity->tx_list = next_sdu;
|
||||
if (entity->tx_end == NULL)
|
||||
entity->tx_end = entity->tx_list;
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu)
|
||||
+ next_sdu->size;
|
||||
}
|
||||
|
||||
/* update tx_next if the SDU segment is the last */
|
||||
@@ -1520,24 +1541,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
|
||||
return serialize_sdu(entity, sdu, buffer, size, p);
|
||||
}
|
||||
|
||||
/* Pretend to serialize all the SDUs in a list and return the size
|
||||
* of all the PDUs it would produce, limited to 'maxsize'.
|
||||
* Used for buffer status reporting.
|
||||
*/
|
||||
static int tx_list_size(nr_rlc_entity_am_t *entity,
|
||||
nr_rlc_sdu_segment_t *l, int maxsize)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (l != NULL && ret < maxsize) {
|
||||
ret += compute_pdu_header_size(entity, l) + l->size;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (ret > maxsize) ret = maxsize;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
|
||||
nr_rlc_entity_t *_entity, int maxsize)
|
||||
{
|
||||
@@ -1549,8 +1552,8 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
|
||||
else
|
||||
ret.status_size = 0;
|
||||
|
||||
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
|
||||
ret.retx_size = tx_list_size(entity, entity->retransmit_list, maxsize);
|
||||
ret.tx_size = entity->common.bstatus.tx_size;
|
||||
ret.retx_size = entity->common.bstatus.retx_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1593,9 +1596,18 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* log SDUs rejected, at most once per second */
|
||||
if (entity->sdu_rejected != 0
|
||||
&& entity->t_current > entity->t_log_buffer_full + 1000) {
|
||||
LOG_E(RLC, "%s:%d:%s: warning: %d SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
entity->sdu_rejected);
|
||||
entity->sdu_rejected = 0;
|
||||
entity->t_log_buffer_full = entity->t_current;
|
||||
}
|
||||
|
||||
if (entity->tx_size + size > entity->tx_maxsize) {
|
||||
LOG_E(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
entity->sdu_rejected++;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1606,6 +1618,10 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n");
|
||||
|
||||
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu)
|
||||
+ sdu->size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -1735,6 +1751,9 @@ static void check_t_reassembly(nr_rlc_entity_am_t *entity)
|
||||
sn = (sn + 1) % entity->sn_modulus;
|
||||
entity->rx_highest_status = sn;
|
||||
|
||||
/* trigger status report */
|
||||
entity->status_triggered = 1;
|
||||
|
||||
if (sn_compare_rx(entity, entity->rx_next_highest,
|
||||
(entity->rx_highest_status+1) % entity->sn_modulus) > 0 ||
|
||||
(entity->rx_next_highest ==
|
||||
@@ -1793,6 +1812,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
|
||||
entity->tx_end = NULL;
|
||||
}
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur)
|
||||
+ cur->size;
|
||||
|
||||
nr_rlc_free_sdu_segment(cur);
|
||||
}
|
||||
|
||||
@@ -1816,6 +1839,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity)
|
||||
|
||||
entity->t_current = 0;
|
||||
|
||||
entity->t_log_buffer_full = 0;
|
||||
entity->sdu_rejected = 0;
|
||||
|
||||
entity->t_poll_retransmit_start = 0;
|
||||
entity->t_reassembly_start = 0;
|
||||
entity->t_status_prohibit_start = 0;
|
||||
@@ -1845,6 +1871,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity)
|
||||
entity->retransmit_end = NULL;
|
||||
|
||||
entity->ack_list = NULL;
|
||||
|
||||
entity->common.bstatus.tx_size = 0;
|
||||
entity->common.bstatus.retx_size = 0;
|
||||
}
|
||||
|
||||
void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity)
|
||||
|
||||
@@ -60,6 +60,10 @@ typedef struct {
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* deal with logging of buffer full */
|
||||
uint64_t t_log_buffer_full;
|
||||
int sdu_rejected;
|
||||
|
||||
/* timers (stores the TTI of activation, 0 means not active) */
|
||||
uint64_t t_poll_retransmit_start;
|
||||
uint64_t t_reassembly_start;
|
||||
|
||||
@@ -68,25 +68,15 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
|
||||
memcpy(buffer, sdu->sdu->data, sdu->size);
|
||||
|
||||
entity->tx_size -= sdu->size;
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= sdu->size;
|
||||
|
||||
nr_rlc_free_sdu_segment(sdu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tx_list_size(nr_rlc_entity_tm_t *entity,
|
||||
nr_rlc_sdu_segment_t *l, int maxsize)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (l != NULL && ret < maxsize) {
|
||||
ret += l->size;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (ret > maxsize) ret = maxsize;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(
|
||||
nr_rlc_entity_t *_entity, int maxsize)
|
||||
{
|
||||
@@ -94,7 +84,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(
|
||||
nr_rlc_entity_buffer_status_t ret;
|
||||
|
||||
ret.status_size = 0;
|
||||
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
|
||||
ret.tx_size = entity->common.bstatus.tx_size;
|
||||
ret.retx_size = 0;
|
||||
|
||||
return ret;
|
||||
@@ -136,6 +126,9 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
|
||||
|
||||
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size += sdu->size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -165,6 +158,8 @@ static void clear_entity(nr_rlc_entity_tm_t *entity)
|
||||
entity->tx_list = NULL;
|
||||
entity->tx_end = NULL;
|
||||
entity->tx_size = 0;
|
||||
|
||||
entity->common.bstatus.tx_size = 0;
|
||||
}
|
||||
|
||||
void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity)
|
||||
|
||||
@@ -28,6 +28,20 @@
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
|
||||
static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
|
||||
nr_rlc_sdu_segment_t *sdu)
|
||||
{
|
||||
int header_size = 1;
|
||||
|
||||
/* if SN to be included then one more byte if SN field length is 12 */
|
||||
if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12)
|
||||
header_size++;
|
||||
/* two more bytes for SO if SDU segment is not the first */
|
||||
if (!sdu->is_first) header_size += 2;
|
||||
return header_size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* PDU RX functions */
|
||||
/*************************************************************************/
|
||||
@@ -375,20 +389,6 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity,
|
||||
return encoder.byte + sdu->size;
|
||||
}
|
||||
|
||||
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
|
||||
static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
|
||||
nr_rlc_sdu_segment_t *sdu)
|
||||
{
|
||||
int header_size = 1;
|
||||
|
||||
/* if SN to be included then one more byte if SN field length is 12 */
|
||||
if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12)
|
||||
header_size++;
|
||||
/* two more bytes for SO if SDU segment is not the first */
|
||||
if (!sdu->is_first) header_size += 2;
|
||||
return header_size;
|
||||
}
|
||||
|
||||
/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
|
||||
* bytes
|
||||
* - modifies SDU/SDU segment to become an SDU segment
|
||||
@@ -462,8 +462,12 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
/* assign SN to SDU */
|
||||
sdu->sdu->sn = entity->tx_next;
|
||||
|
||||
/* segment if necessary */
|
||||
pdu_size = pdu_header_size + sdu->size;
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= pdu_size;
|
||||
|
||||
/* segment if necessary */
|
||||
if (pdu_size > size) {
|
||||
nr_rlc_sdu_segment_t *next_sdu;
|
||||
next_sdu = resegment(sdu, entity, size);
|
||||
@@ -474,6 +478,9 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
entity->tx_list = next_sdu;
|
||||
if (entity->tx_end == NULL)
|
||||
entity->tx_end = entity->tx_list;
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu)
|
||||
+ next_sdu->size;
|
||||
}
|
||||
|
||||
/* update tx_next if the SDU is an SDU segment and is the last */
|
||||
@@ -488,24 +495,6 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Pretend to serialize all the SDUs in a list and return the size
|
||||
* of all the PDUs it would produce, limited to 'maxsize'.
|
||||
* Used for buffer status reporting.
|
||||
*/
|
||||
static int tx_list_size(nr_rlc_entity_um_t *entity,
|
||||
nr_rlc_sdu_segment_t *l, int maxsize)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (l != NULL && ret < maxsize) {
|
||||
ret += compute_pdu_header_size(entity, l) + l->size;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (ret > maxsize) ret = maxsize;
|
||||
return ret;
|
||||
}
|
||||
|
||||
nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
|
||||
nr_rlc_entity_t *_entity, int maxsize)
|
||||
{
|
||||
@@ -513,7 +502,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
|
||||
nr_rlc_entity_buffer_status_t ret;
|
||||
|
||||
ret.status_size = 0;
|
||||
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
|
||||
ret.tx_size = entity->common.bstatus.tx_size;
|
||||
ret.retx_size = 0;
|
||||
|
||||
return ret;
|
||||
@@ -555,6 +544,10 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
|
||||
|
||||
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu)
|
||||
+ sdu->size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -650,6 +643,10 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
|
||||
entity->tx_end = NULL;
|
||||
}
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur)
|
||||
+ cur->size;
|
||||
|
||||
nr_rlc_free_sdu_segment(cur);
|
||||
}
|
||||
|
||||
@@ -682,6 +679,8 @@ static void clear_entity(nr_rlc_entity_um_t *entity)
|
||||
entity->tx_list = NULL;
|
||||
entity->tx_end = NULL;
|
||||
entity->tx_size = 0;
|
||||
|
||||
entity->common.bstatus.tx_size = 0;
|
||||
}
|
||||
|
||||
void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -81,13 +81,32 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t
|
||||
// Note: sdu should always be processed because data and timing advance updates are transmitted by the UE
|
||||
int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
|
||||
|
||||
update_harq_status(dl_info, pdu_id);
|
||||
update_harq_status(dl_info->module_id,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
|
||||
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
|
||||
nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nack) {
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid];
|
||||
|
||||
if (current_harq->active) {
|
||||
current_harq->ack = ack_nack;
|
||||
current_harq->ack_received = true;
|
||||
LOG_D(PHY,"Updating harq_status for harq_id %d,ack/nak %d\n",harq_pid,current_harq->ack);
|
||||
}
|
||||
else {
|
||||
//shouldn't get here
|
||||
LOG_E(MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
|
||||
|
||||
NR_UE_L2_STATE_t ret;
|
||||
|
||||
@@ -68,64 +68,6 @@ typedef enum {
|
||||
} UE_MAC_Tx_ind_type_e;
|
||||
|
||||
|
||||
|
||||
// *** UE_UL_Config.request related structures
|
||||
|
||||
|
||||
typedef struct{
|
||||
//module_id_t module_idP;
|
||||
//int CC_id;
|
||||
//frame_t frameP;
|
||||
uint8_t eNB_id;
|
||||
//uint16_t rnti;
|
||||
//sub_frame_t subframe_tx;
|
||||
uint32_t SR_payload; //0 or 1
|
||||
}UE_MAC_ul_config_SR;
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
//module_id_t module_idP;
|
||||
//int CC_id;
|
||||
//frame_t frameP;
|
||||
uint8_t eNB_indexP;
|
||||
//sub_frame_t subframeP;
|
||||
|
||||
uint8_t ra_RACH_MaskIndex;
|
||||
int8_t ra_PREAMBLE_RECEIVED_TARGET_POWER;
|
||||
uint8_t ra_TDD_map_index;
|
||||
uint16_t ra_RNTI;
|
||||
uint8_t *Msg3;
|
||||
}UE_MAC_ul_config_rach;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
UE_MAC_ul_config_rach ue_rach_config;
|
||||
//UE_MAC_ul_config_ULSCH ue_ULSCH_pdu;
|
||||
UE_MAC_ul_config_SR ue_SR_config;
|
||||
};
|
||||
} UE_MAC_ul_config_request_list;
|
||||
|
||||
typedef struct {
|
||||
nfapi_tl_t tl;
|
||||
uint16_t length_list;
|
||||
UE_MAC_ul_config_request_list* ue_ul_config_list;
|
||||
} UE_MAC_ul_config_request_body_t;
|
||||
|
||||
typedef struct {
|
||||
//nfapi_p7_message_header_t header;
|
||||
uint16_t sfn_sf;
|
||||
UE_MAC_ul_config_request_body_t ue_ul_config_request_body; //nfapi_dl_config_request_body_t
|
||||
} UE_MAC_ul_config_request_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// *** UE_Tx.request related structures
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -383,3 +383,17 @@ void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP,
|
||||
LOG_D(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const rnti_t rntiP) {
|
||||
struct rrc_gNB_ue_context_s *ue_context_p = NULL;
|
||||
ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[Mod_instP], rntiP);
|
||||
if (ue_context_p != NULL) {
|
||||
LOG_W(RRC,"Frame %d, Subframe %d: UE %x UL failure reset, deactivating timer\n",frameP,subframeP,rntiP);
|
||||
ue_context_p->ue_context.ul_failure_timer=0;
|
||||
} else {
|
||||
LOG_W(RRC,"Frame %d, Subframe %d: UL failure reset: UE %x unknown \n",frameP,subframeP,rntiP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
int dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int initial_csi_index,
|
||||
int uid);
|
||||
@@ -90,6 +91,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
int dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int initial_csi_index,
|
||||
int uid);
|
||||
|
||||
@@ -241,6 +241,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
carrier->pdsch_AntennaPorts,
|
||||
carrier->minRXTXTIMEpdsch,
|
||||
carrier->do_CSIRS,
|
||||
carrier->initial_csi_index[ue_context_p->local_uid + 1],
|
||||
ue_context_p->local_uid);
|
||||
@@ -250,6 +251,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
carrier->pdsch_AntennaPorts,
|
||||
carrier->minRXTXTIMEpdsch,
|
||||
carrier->do_CSIRS,
|
||||
carrier->initial_csi_index[ue_context_p->local_uid + 1],
|
||||
ue_context_p->local_uid);
|
||||
|
||||
@@ -55,6 +55,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
int dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int initial_csi_index,
|
||||
int uid) {
|
||||
@@ -945,7 +946,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
long *delay[8];
|
||||
for (int i=0;i<8;i++) {
|
||||
delay[i] = calloc(1,sizeof(*delay[i]));
|
||||
*delay[i] = (i<6) ? (i+2) : 0;
|
||||
*delay[i] = i+minRXTXTIMEpdsch;
|
||||
ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]);
|
||||
}
|
||||
pucch_Config->spatialRelationInfoToAddModList = calloc(1,sizeof(*pucch_Config->spatialRelationInfoToAddModList));
|
||||
@@ -1348,6 +1349,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
int dl_antenna_ports,
|
||||
int minRXTXTIMEpdsch,
|
||||
int do_csirs,
|
||||
int initial_csi_index,
|
||||
int uid) {
|
||||
@@ -1363,6 +1365,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
1,
|
||||
1,
|
||||
dl_antenna_ports,
|
||||
minRXTXTIMEpdsch,
|
||||
do_csirs,
|
||||
initial_csi_index,
|
||||
uid);
|
||||
|
||||
@@ -512,8 +512,8 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
|
||||
return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data);
|
||||
}
|
||||
|
||||
const char *X2AP_cause_str1[4]={"radioNetwork","transport","protocol","misc"};
|
||||
const char *X2AP_case_str_radio[50]={" X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons",
|
||||
const char *X2AP_ResetRequest_str[2]={"X2AP_ResetRequest_IEs__value_PR_Cause","X2AP_ResetRequest_IEs__value_PR_InterfaceInstanceIndication"};
|
||||
const char *X2AP_case_str_radio[50]={"X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons",
|
||||
"X2AP_CauseRadioNetwork_time_critical_handover",
|
||||
"X2AP_CauseRadioNetwork_resource_optimisation_handover",
|
||||
"X2AP_CauseRadioNetwork_reduce_load_in_serving_cell",
|
||||
@@ -617,8 +617,9 @@ x2ap_eNB_handle_x2_reset_request(instance_t instance,
|
||||
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
|
||||
return -1;
|
||||
} else {
|
||||
AssertFatal(ie->value.present <= X2AP_Cause_PR_misc && ie->value.present > 0,"Cause value %d, is impossible\n",ie->value.present);
|
||||
LOG_I(X2AP,"Received X2AP Reset Request with Cause Type %s\n",X2AP_cause_str1[ie->value.present-1]);
|
||||
AssertFatal(ie->value.present <= X2AP_ResetRequest_IEs__value_PR_InterfaceInstanceIndication && ie->value.present > 0,
|
||||
"Cause value %d, is impossible\n",ie->value.present);
|
||||
LOG_I(X2AP,"Received X2AP Reset Request with Cause Type %s\n",X2AP_ResetRequest_str[ie->value.present-1]);
|
||||
}
|
||||
|
||||
X2AP_DEBUG("Adding eNB to the list of associated eNBs\n");
|
||||
|
||||
Reference in New Issue
Block a user