Generate the DCCH and send from pdcp
This commit is contained in:
@@ -264,7 +264,7 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(instance_t instance,
|
||||
//ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 123L;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
}
|
||||
|
||||
|
||||
/* encode */
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(CU_F1AP, "Failed to encode F1 setup request\n");
|
||||
@@ -365,15 +365,17 @@ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance,
|
||||
*/
|
||||
protocol_ctxt_t ctxt;
|
||||
ctxt.module_id = instance;
|
||||
ctxt.instance = instance;
|
||||
ctxt.rnti = f1ap_get_rnti_by_cu_id(&f1ap_cu_ue[instance],cu_ue_f1ap_id);
|
||||
ctxt.enb_flag = 1;
|
||||
mem_block_t *mb = get_free_mem_block(ie->value.choice.RRCContainer.size,__func__);
|
||||
memcpy((void*)mb->data,(void*)ie->value.choice.RRCContainer.buf,ie->value.choice.RRCContainer.size);
|
||||
LOG_I(CU_F1AP, "Calling pdcp_data_ind for UE RNTI %x srb_id %lu with size %d (DCCH) \n", ctxt.rnti, srb_id, ie->value.choice.RRCContainer.size);
|
||||
pdcp_data_ind (&ctxt,
|
||||
1,
|
||||
0,
|
||||
srb_id,
|
||||
ie->value.choice.RRCContainer.size,
|
||||
mb);
|
||||
1, // srb_flag
|
||||
0, // embms_flag
|
||||
srb_id,
|
||||
ie->value.choice.RRCContainer.size,
|
||||
mb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -175,153 +175,208 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance,
|
||||
// decode RRC Container and act on the message type
|
||||
AssertFatal(srb_id<3,"illegal srb_id\n");
|
||||
|
||||
protocol_ctxt_t ctxt;
|
||||
ctxt.rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id);
|
||||
ctxt.module_id = instance;
|
||||
ctxt.instance = instance;
|
||||
ctxt.enb_flag = 1;
|
||||
|
||||
if (srb_id == 0) {
|
||||
DL_CCCH_Message_t* dl_ccch_msg=NULL;
|
||||
asn_dec_rval_t dec_rval;
|
||||
dec_rval = uper_decode(NULL,
|
||||
&asn_DEF_DL_CCCH_Message,
|
||||
(void**)&dl_ccch_msg,
|
||||
ie->value.choice.RRCContainer.buf,
|
||||
rrc_dl_sdu_len,0,0);
|
||||
&asn_DEF_DL_CCCH_Message,
|
||||
(void**)&dl_ccch_msg,
|
||||
ie->value.choice.RRCContainer.buf,
|
||||
rrc_dl_sdu_len,0,0);
|
||||
switch (dl_ccch_msg->message.choice.c1.present) {
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_NOTHING:
|
||||
LOG_I(RRC, "Received PR_NOTHING on DL-CCCH-Message\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n");
|
||||
break;
|
||||
case DL_CCCH_MessageType__c1_PR_NOTHING:
|
||||
LOG_I(RRC, "Received PR_NOTHING on DL-CCCH-Message\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n");
|
||||
break;
|
||||
|
||||
case DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
|
||||
{
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup DU_ID %x/RNTI %x\n",
|
||||
du_ue_f1ap_id,
|
||||
f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id));
|
||||
// Get configuration
|
||||
LOG_I(RRC,
|
||||
"Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup DU_ID %x/RNTI %x\n",
|
||||
du_ue_f1ap_id,
|
||||
f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id));
|
||||
// Get configuration
|
||||
|
||||
RRCConnectionSetup_t* rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
|
||||
// eNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
AssertFatal(rrcConnectionSetup!=NULL,"rrcConnectionSetup is null\n");
|
||||
RadioResourceConfigDedicated_t* radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
|
||||
|
||||
// get SRB logical channel information
|
||||
SRB_ToAddModList_t *SRB_configList;
|
||||
SRB_ToAddMod_t *SRB1_config;
|
||||
LogicalChannelConfig_t *SRB1_logicalChannelConfig; //,*SRB2_logicalChannelConfig;
|
||||
SRB_configList = radioResourceConfigDedicated->srb_ToAddModList;
|
||||
RRCConnectionSetup_t* rrcConnectionSetup = &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup;
|
||||
// eNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
AssertFatal(rrcConnectionSetup!=NULL,"rrcConnectionSetup is null\n");
|
||||
RadioResourceConfigDedicated_t* radioResourceConfigDedicated = &rrcConnectionSetup->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated;
|
||||
|
||||
AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
|
||||
for (int cnt = 0; cnt < (SRB_configList)->list.count; cnt++) {
|
||||
if ((SRB_configList)->list.array[cnt]->srb_Identity == 1) {
|
||||
SRB1_config = (SRB_configList)->list.array[cnt];
|
||||
|
||||
if (SRB1_config->logicalChannelConfig) {
|
||||
if (SRB1_config->logicalChannelConfig->present ==
|
||||
SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
|
||||
SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue;
|
||||
} else {
|
||||
SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
|
||||
}
|
||||
} else {
|
||||
SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// get SRB logical channel information
|
||||
SRB_ToAddModList_t *SRB_configList;
|
||||
SRB_ToAddMod_t *SRB1_config;
|
||||
LogicalChannelConfig_t *SRB1_logicalChannelConfig; //,*SRB2_logicalChannelConfig;
|
||||
SRB_configList = radioResourceConfigDedicated->srb_ToAddModList;
|
||||
|
||||
protocol_ctxt_t ctxt;
|
||||
ctxt.rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[instance],du_ue_f1ap_id);
|
||||
ctxt.module_id = instance;
|
||||
ctxt.enb_flag = 1;
|
||||
rrc_rlc_config_asn1_req(&ctxt,
|
||||
SRB_configList,
|
||||
(DRB_ToAddModList_t*) NULL,
|
||||
(DRB_ToReleaseList_t*) NULL
|
||||
AssertFatal(SRB_configList!=NULL,"SRB_configList is null\n");
|
||||
for (int cnt = 0; cnt < (SRB_configList)->list.count; cnt++) {
|
||||
if ((SRB_configList)->list.array[cnt]->srb_Identity == 1) {
|
||||
SRB1_config = (SRB_configList)->list.array[cnt];
|
||||
|
||||
if (SRB1_config->logicalChannelConfig) {
|
||||
if (SRB1_config->logicalChannelConfig->present ==
|
||||
SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
|
||||
SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue;
|
||||
} else {
|
||||
SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
|
||||
}
|
||||
} else {
|
||||
SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
|
||||
}
|
||||
}
|
||||
} // for
|
||||
rrc_rlc_config_asn1_req(&ctxt,
|
||||
SRB_configList,
|
||||
(DRB_ToAddModList_t*) NULL,
|
||||
(DRB_ToReleaseList_t*) NULL
|
||||
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
, (PMCH_InfoList_r9_t *) NULL,
|
||||
0,0
|
||||
, (PMCH_InfoList_r9_t *) NULL,
|
||||
0,0
|
||||
# endif
|
||||
);
|
||||
|
||||
// This should be somewhere in the f1ap_cudu_ue_inst_t
|
||||
int macrlc_instance = 0;
|
||||
);
|
||||
|
||||
rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[0],du_ue_f1ap_id);
|
||||
struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
|
||||
|
||||
eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context;
|
||||
AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
|
||||
// This should be somewhere in the f1ap_cudu_ue_inst_t
|
||||
int macrlc_instance = 0;
|
||||
|
||||
memcpy((void*)ue_p->Srb0.Tx_buffer.Payload,
|
||||
(void*)ie->value.choice.RRCContainer.buf,
|
||||
rrc_dl_sdu_len);
|
||||
rnti_t rnti = f1ap_get_rnti_by_du_id(&f1ap_du_ue[0],du_ue_f1ap_id);
|
||||
struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[macrlc_instance],rnti);
|
||||
|
||||
eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context;
|
||||
AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n");
|
||||
|
||||
ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
|
||||
memcpy((void*)ue_p->Srb0.Tx_buffer.Payload,
|
||||
(void*)ie->value.choice.RRCContainer.buf,
|
||||
rrc_dl_sdu_len);
|
||||
|
||||
rrc_mac_config_req_eNB(
|
||||
macrlc_instance,
|
||||
0, //primaryCC_id,
|
||||
0,0,0,0,0,
|
||||
ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len;
|
||||
|
||||
rrc_mac_config_req_eNB(
|
||||
macrlc_instance,
|
||||
0, //primaryCC_id,
|
||||
0,0,0,0,0,
|
||||
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
rnti,
|
||||
(BCCH_BCH_Message_t *) NULL,
|
||||
(RadioResourceConfigCommonSIB_t *) NULL,
|
||||
rnti,
|
||||
(BCCH_BCH_Message_t *) NULL,
|
||||
(RadioResourceConfigCommonSIB_t *) NULL,
|
||||
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
(RadioResourceConfigCommonSIB_t *) NULL,
|
||||
(RadioResourceConfigCommonSIB_t *) NULL,
|
||||
#endif
|
||||
radioResourceConfigDedicated->physicalConfigDedicated,
|
||||
radioResourceConfigDedicated->physicalConfigDedicated,
|
||||
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
|
||||
(SCellToAddMod_r10_t *)NULL,
|
||||
//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
|
||||
(SCellToAddMod_r10_t *)NULL,
|
||||
//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
|
||||
#endif
|
||||
(MeasObjectToAddMod_t **) NULL,
|
||||
radioResourceConfigDedicated->mac_MainConfig,
|
||||
1,
|
||||
SRB1_logicalChannelConfig,
|
||||
NULL, // measGapConfig,
|
||||
(TDD_Config_t *) NULL,
|
||||
NULL,
|
||||
(SchedulingInfoList_t *) NULL,
|
||||
0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL
|
||||
(MeasObjectToAddMod_t **) NULL,
|
||||
radioResourceConfigDedicated->mac_MainConfig,
|
||||
1,
|
||||
SRB1_logicalChannelConfig,
|
||||
NULL, // measGapConfig,
|
||||
(TDD_Config_t *) NULL,
|
||||
NULL,
|
||||
(SchedulingInfoList_t *) NULL,
|
||||
0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL
|
||||
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
, 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
|
||||
, 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
|
||||
#endif
|
||||
#if (RRC_VERSION >= MAKE_VERSION(13, 0, 0))
|
||||
,
|
||||
(SystemInformationBlockType1_v1310_IEs_t *)NULL
|
||||
,
|
||||
(SystemInformationBlockType1_v1310_IEs_t *)NULL
|
||||
#endif
|
||||
);
|
||||
break;
|
||||
);
|
||||
break;
|
||||
} // case
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,
|
||||
"Unknown message\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AssertFatal(1==0,
|
||||
"Unknown message\n");
|
||||
break;
|
||||
}// switch case
|
||||
} else if (srb_id == 1) {
|
||||
// rrc_rlc_config_asn1_req(&ctxt,
|
||||
// SRB_configList,
|
||||
// (DRB_ToAddModList_t*) NULL,
|
||||
// (DRB_ToReleaseList_t*) NULL
|
||||
// #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
// , (PMCH_InfoList_r9_t *) NULL,
|
||||
// 0,0
|
||||
// # endif
|
||||
// );
|
||||
|
||||
}
|
||||
}
|
||||
else if (srb_id == 1){
|
||||
LOG_I(DU_F1AP, "Received DL RRC Transfer on srb_id 1\n");
|
||||
rlc_op_status_t rlc_status;
|
||||
boolean_t ret = TRUE;
|
||||
mem_block_t *pdcp_pdu_p = NULL;
|
||||
pdcp_pdu_p = get_free_mem_block(rrc_dl_sdu_len, __func__);
|
||||
memset(&pdcp_pdu_p->data[0], 0, rrc_dl_sdu_len);
|
||||
memcpy(&pdcp_pdu_p->data[0], ie->value.choice.RRCContainer.buf, rrc_dl_sdu_len);
|
||||
|
||||
}
|
||||
if (pdcp_pdu_p != NULL) {
|
||||
rlc_status = rlc_data_req(&ctxt
|
||||
, 1
|
||||
, MBMS_FLAG_NO
|
||||
, srb_id
|
||||
, 0
|
||||
, 0
|
||||
, rrc_dl_sdu_len
|
||||
, pdcp_pdu_p
|
||||
#ifdef Rel14
|
||||
,NULL
|
||||
,NULL
|
||||
#endif
|
||||
);
|
||||
switch (rlc_status) {
|
||||
case RLC_OP_STATUS_OK:
|
||||
LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
|
||||
ret=TRUE;
|
||||
break;
|
||||
|
||||
else if (srb_id == 2){
|
||||
case RLC_OP_STATUS_BAD_PARAMETER:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_INTERNAL_ERROR:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_OUT_OF_RESSOURCES:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
|
||||
ret= FALSE;
|
||||
break;
|
||||
} // switch case
|
||||
return ret;
|
||||
} // if pdcp_pdu_p
|
||||
|
||||
} else if (srb_id == 2) {
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -336,7 +391,6 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(const protocol_ctxt_t* const ctxt_pP,
|
||||
) {
|
||||
|
||||
|
||||
|
||||
rnti_t rnti = ctxt_pP->rnti;
|
||||
|
||||
F1AP_F1AP_PDU_t pdu;
|
||||
@@ -402,6 +456,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(const protocol_ctxt_t* const ctxt_pP,
|
||||
LOG_E(DU_F1AP, "Failed to encode F1 setup request\n");
|
||||
return -1;
|
||||
}
|
||||
LOG_W(DU_F1AP, "DU_send_UL_RRC_MESSAGE_TRANSFER on SRB %d for UE %x \n", rb_idP, rnti);
|
||||
|
||||
du_f1ap_itti_send_sctp_data_req(instance, f1ap_du_data->assoc_id, buffer, len, f1ap_du_data->default_sctp_stream_id);
|
||||
return 0;
|
||||
|
||||
@@ -175,8 +175,9 @@ void *F1AP_DU_task(void *arg) {
|
||||
|
||||
case F1AP_UL_RRC_MESSAGE: // from rrc
|
||||
LOG_I(DU_F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n");
|
||||
DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&F1AP_UL_RRC_MESSAGE(received_msg));
|
||||
AssertFatal (1 == 0, "Should not be here!\n" );
|
||||
//DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
// &F1AP_UL_RRC_MESSAGE(received_msg));
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE:
|
||||
|
||||
@@ -119,7 +119,7 @@ int f1ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
|
||||
}
|
||||
|
||||
/* Calling the right handler */
|
||||
LOG_I(DU_F1AP, "Calling handler with instance %d\n",instance);
|
||||
LOG_I(F1AP, "Calling handler with instance %d\n",instance);
|
||||
ret = (*f1ap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])
|
||||
(instance, assoc_id, stream, &pdu);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_F1AP_F1AP_PDU, &pdu);
|
||||
|
||||
@@ -49,9 +49,7 @@
|
||||
#include "platform_constants.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "msc.h"
|
||||
|
||||
|
||||
|
||||
#include "common/ngran_types.h"
|
||||
|
||||
#if defined(ENABLE_SECURITY)
|
||||
# include "UTIL/OSA/osa_defs.h"
|
||||
@@ -411,53 +409,75 @@ boolean_t pdcp_data_req(
|
||||
free_mem_block(pdcp_pdu_p, __FUNCTION__);
|
||||
rlc_status = ack_result;
|
||||
}
|
||||
|
||||
else
|
||||
else // SRB
|
||||
#endif /*UETARGET*/
|
||||
{
|
||||
LOG_I(PDCP, "Sending F1AP_DL_RRC_MESSAGE with ITTI\n");
|
||||
|
||||
//It should never get here
|
||||
rlc_status = rlc_data_req(ctxt_pP
|
||||
, srb_flagP
|
||||
, MBMS_FLAG_NO
|
||||
, rb_idP
|
||||
, muiP
|
||||
, confirmP
|
||||
, pdcp_pdu_size
|
||||
, pdcp_pdu_p
|
||||
#ifdef Rel14
|
||||
,NULL
|
||||
,NULL
|
||||
#endif
|
||||
);
|
||||
if ((RC.rrc[ctxt_pP->module_id]->node_type == ngran_eNB_CU) ||
|
||||
(RC.rrc[ctxt_pP->module_id]->node_type == ngran_ng_eNB_CU)||
|
||||
(RC.rrc[ctxt_pP->module_id]->node_type == ngran_gNB_CU) ) {
|
||||
// DL transfer
|
||||
MessageDef *message_p;
|
||||
// Note: the acyual task must be TASK_PDCP_ENB, but this task is not created
|
||||
message_p = itti_alloc_new_message (TASK_PDCP_ENB, F1AP_DL_RRC_MESSAGE);
|
||||
F1AP_DL_RRC_MESSAGE (message_p).rrc_container = &pdcp_pdu_p->data[0] ;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id = 0;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id = 0xFFFFFFFF; // unknown
|
||||
F1AP_DL_RRC_MESSAGE (message_p).rnti = ctxt_pP->rnti;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).srb_id = rb_idP;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).execute_duplication = 1;
|
||||
F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc = 0;
|
||||
itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
|
||||
//CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p);
|
||||
LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n");
|
||||
ret=TRUE;
|
||||
|
||||
} else{
|
||||
rlc_status = rlc_data_req(ctxt_pP
|
||||
, srb_flagP
|
||||
, MBMS_FLAG_NO
|
||||
, rb_idP
|
||||
, muiP
|
||||
, confirmP
|
||||
, pdcp_pdu_size
|
||||
, pdcp_pdu_p
|
||||
#ifdef Rel14
|
||||
,NULL
|
||||
,NULL
|
||||
#endif
|
||||
);
|
||||
switch (rlc_status) {
|
||||
case RLC_OP_STATUS_OK:
|
||||
LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
|
||||
ret=TRUE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_BAD_PARAMETER:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_INTERNAL_ERROR:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_OUT_OF_RESSOURCES:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
|
||||
ret= FALSE;
|
||||
break;
|
||||
} // switch case
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (rlc_status) {
|
||||
case RLC_OP_STATUS_OK:
|
||||
LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
|
||||
ret=TRUE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_BAD_PARAMETER:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_INTERNAL_ERROR:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
case RLC_OP_STATUS_OUT_OF_RESSOURCES:
|
||||
LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
|
||||
ret= FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
|
||||
ret= FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
|
||||
@@ -978,6 +998,8 @@ void pdcp_update_stats(const protocol_ctxt_t* const ctxt_pP){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
pdcp_run (
|
||||
@@ -1020,6 +1042,7 @@ pdcp_run (
|
||||
RRC_DCCH_DATA_REQ (msg_p).frame,
|
||||
0,
|
||||
RRC_DCCH_DATA_REQ (msg_p).eNB_index);
|
||||
|
||||
LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
|
||||
PROTOCOL_CTXT_ARGS(&ctxt),
|
||||
ITTI_MSG_NAME (msg_p),
|
||||
@@ -1030,6 +1053,8 @@ pdcp_run (
|
||||
RRC_DCCH_DATA_REQ (msg_p).confirmp,
|
||||
RRC_DCCH_DATA_REQ (msg_p).mode);
|
||||
|
||||
log_dump(PDCP, RRC_DCCH_DATA_REQ (msg_p).sdu_p, RRC_DCCH_DATA_REQ (msg_p).sdu_size, LOG_DUMP_CHAR,"[MSG] pdcp run\n");
|
||||
|
||||
result = pdcp_data_req (&ctxt,
|
||||
SRB_FLAG_YES,
|
||||
RRC_DCCH_DATA_REQ (msg_p).rb_id,
|
||||
|
||||
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_RECEIVER_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "assertions.h"
|
||||
#include "msc.h"
|
||||
#include "rlc.h"
|
||||
#include "rlc_am.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_get_data_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t* header_pP,
|
||||
int16_t total_sizeP,
|
||||
rlc_am_pdu_info_t* pdu_info_pP)
|
||||
{
|
||||
memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
|
||||
|
||||
int16_t sum_li = 0;
|
||||
pdu_info_pP->d_c = header_pP->b1 >> 7;
|
||||
pdu_info_pP->num_li = 0;
|
||||
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.766
|
||||
if(pdu_info_pP->d_c == 0)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
|
||||
return -2;
|
||||
}
|
||||
/*
|
||||
AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
|
||||
*/
|
||||
pdu_info_pP->rf = (header_pP->b1 >> 6) & 0x01;
|
||||
pdu_info_pP->p = (header_pP->b1 >> 5) & 0x01;
|
||||
pdu_info_pP->fi = (header_pP->b1 >> 3) & 0x03;
|
||||
pdu_info_pP->e = (header_pP->b1 >> 2) & 0x01;
|
||||
pdu_info_pP->sn = header_pP->b2 + (((uint16_t)(header_pP->b1 & 0x03)) << 8);
|
||||
|
||||
pdu_info_pP->header_size = 2;
|
||||
|
||||
if (pdu_info_pP->rf) {
|
||||
pdu_info_pP->lsf = (header_pP->data[0] >> 7) & 0x01;
|
||||
pdu_info_pP->so = header_pP->data[1] + (((uint16_t)(header_pP->data[0] & 0x7F)) << 8);
|
||||
pdu_info_pP->payload = &header_pP->data[2];
|
||||
pdu_info_pP->header_size += 2;
|
||||
} else {
|
||||
pdu_info_pP->payload = &header_pP->data[0];
|
||||
}
|
||||
|
||||
if (pdu_info_pP->e) {
|
||||
rlc_am_e_li_t *e_li;
|
||||
unsigned int li_length_in_bytes = 1;
|
||||
unsigned int li_to_read = 1;
|
||||
|
||||
if (pdu_info_pP->rf) {
|
||||
e_li = (rlc_am_e_li_t*)(&header_pP->data[2]);
|
||||
} else {
|
||||
e_li = (rlc_am_e_li_t*)(header_pP->data);
|
||||
}
|
||||
|
||||
while (li_to_read) {
|
||||
li_length_in_bytes = li_length_in_bytes ^ 3;
|
||||
|
||||
if (li_length_in_bytes == 2) {
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b1 << 4)) & 0x07F0;
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] |= (((uint8_t)(e_li->b2 >> 4)) & 0x000F);
|
||||
li_to_read = e_li->b1 & 0x80;
|
||||
pdu_info_pP->header_size += 2;
|
||||
} else {
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b2 << 8)) & 0x0700;
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] |= e_li->b3;
|
||||
li_to_read = e_li->b2 & 0x08;
|
||||
e_li++;
|
||||
pdu_info_pP->header_size += 1;
|
||||
}
|
||||
|
||||
sum_li += pdu_info_pP->li_list[pdu_info_pP->num_li];
|
||||
pdu_info_pP->num_li = pdu_info_pP->num_li + 1;
|
||||
|
||||
if (pdu_info_pP->num_li > RLC_AM_MAX_SDU_IN_PDU) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET PDU INFO] SN %04d TOO MANY LIs ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (li_length_in_bytes == 2) {
|
||||
pdu_info_pP->payload = &e_li->b3;
|
||||
} else {
|
||||
pdu_info_pP->payload = &e_li->b1;
|
||||
}
|
||||
}
|
||||
|
||||
pdu_info_pP->payload_size = total_sizeP - pdu_info_pP->header_size;
|
||||
|
||||
if (pdu_info_pP->payload_size > sum_li) {
|
||||
pdu_info_pP->hidden_size = pdu_info_pP->payload_size - sum_li;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_display_data_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
rlc_am_pdu_info_t* pdu_info_pP)
|
||||
{
|
||||
int num_li;
|
||||
|
||||
if (pdu_info_pP->d_c) {
|
||||
if (pdu_info_pP->rf) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d SO %05d LSF %01d POLL %1d ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn,
|
||||
pdu_info_pP->fi,
|
||||
pdu_info_pP->so,
|
||||
pdu_info_pP->lsf, pdu_info_pP->p);
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d POLL %1d ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn,
|
||||
pdu_info_pP->fi,
|
||||
pdu_info_pP->p);
|
||||
}
|
||||
|
||||
for (num_li = 0; num_li < pdu_info_pP->num_li; num_li++) {
|
||||
LOG_D(RLC, "LI %05d ", pdu_info_pP->li_list[num_li]);
|
||||
}
|
||||
|
||||
if (pdu_info_pP->hidden_size > 0) {
|
||||
LOG_D(RLC, "hidden size %05d ", pdu_info_pP->hidden_size);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] ERROR RX CONTROL PDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
}
|
||||
// assumed the sn of the tb_p is equal to VR(MS)
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_rx_update_vr_ms(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP)
|
||||
{
|
||||
//rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
|
||||
rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
|
||||
mem_block_t* cursor_p;
|
||||
|
||||
cursor_p = tb_pP;
|
||||
|
||||
if (cursor_p) {
|
||||
do {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
|
||||
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
|
||||
(rlc_pP->vr_ms != pdu_info_cursor_p->sn)) {
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_ms, pdu_info_cursor_p->sn);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn);
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h));
|
||||
|
||||
}
|
||||
}
|
||||
// assumed the sn of the tb_p is equal to VR(R)
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_rx_update_vr_r(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP)
|
||||
{
|
||||
rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
|
||||
mem_block_t* cursor_p;
|
||||
|
||||
cursor_p = tb_pP;
|
||||
|
||||
if (cursor_p) {
|
||||
do {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
|
||||
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
|
||||
(rlc_pP->vr_r != pdu_info_cursor_p->sn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(R)] UPDATED VR(R) %04d -> %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_r,
|
||||
(pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK);
|
||||
#endif
|
||||
|
||||
if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.rf == 1) {
|
||||
if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.lsf == 1) {
|
||||
rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
} else {
|
||||
rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
|
||||
cursor_p = cursor_p->next;
|
||||
} while (cursor_p != NULL);
|
||||
|
||||
//rlc_pP->vr_r = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_routing (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
struct mac_data_ind data_indP)
|
||||
{
|
||||
mem_block_t *tb_p = NULL;
|
||||
uint8_t *first_byte_p = NULL;
|
||||
sdu_size_t tb_size_in_bytes;
|
||||
RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
|
||||
|
||||
while ((tb_p = list_remove_head (&data_indP.data))) {
|
||||
first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
|
||||
tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
|
||||
|
||||
if (tb_size_in_bytes > 0) {
|
||||
if ((*first_byte_p & 0x80) == 0x80) {
|
||||
rlc_pP->stat_rx_data_bytes += tb_size_in_bytes;
|
||||
rlc_pP->stat_rx_data_pdu += 1;
|
||||
rlc_am_receive_process_data_pdu (ctxt_pP, rlc_pP, tb_p, first_byte_p, tb_size_in_bytes);
|
||||
} else {
|
||||
rlc_pP->stat_rx_control_bytes += tb_size_in_bytes;
|
||||
rlc_pP->stat_rx_control_pdu += 1;
|
||||
rlc_am_receive_process_control_pdu (ctxt_pP, rlc_pP, tb_p, &first_byte_p, &tb_size_in_bytes);
|
||||
// Test if remaining bytes not processed (up to know, highest probability is bug in MAC)
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.767
|
||||
if(tb_size_in_bytes != 0)
|
||||
{
|
||||
LOG_E(RLC, "Remaining %d bytes following a control PDU\n",
|
||||
tb_size_in_bytes);
|
||||
}
|
||||
/*
|
||||
AssertFatal( tb_size_in_bytes == 0,
|
||||
"Remaining %d bytes following a control PDU",
|
||||
tb_size_in_bytes);
|
||||
*/
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RX ROUTING] VR(R)=%03d VR(MR)=%03d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_mr);
|
||||
}
|
||||
} // end while
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_process_data_pdu (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP,
|
||||
uint8_t* first_byte_pP,
|
||||
uint16_t tb_size_in_bytesP)
|
||||
{
|
||||
// 5.1.3.2 Receive operations
|
||||
// 5.1.3.2.1 General
|
||||
// The receiving side of an AM RLC entity shall maintain a receiving window according to state variables VR(R) and
|
||||
// VR(MR) as follows:
|
||||
// - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
|
||||
// - a SN falls outside of the receiving window otherwise.
|
||||
//
|
||||
// When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
|
||||
// - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
|
||||
// - if the received RLC data PDU was placed in the reception buffer:
|
||||
// - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as
|
||||
// needed (see sub clause 5.1.3.2.3).
|
||||
// When t-Reordering expires, the receiving side of an AM RLC entity shall:
|
||||
// - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
|
||||
|
||||
|
||||
// 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
|
||||
// When a RLC data PDU is received from lower layer, where the RLC data PDU contains byte segment numbers y to z of
|
||||
// an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
|
||||
// - if x falls outside of the receiving window; or
|
||||
// - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
|
||||
// - discard the received RLC data PDU;
|
||||
// - else:
|
||||
// - place the received RLC data PDU in the reception buffer;
|
||||
// - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
|
||||
// - discard the duplicate byte segments.
|
||||
rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
|
||||
rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP;
|
||||
rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK;
|
||||
boolean_t reassemble = false;
|
||||
|
||||
if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) {
|
||||
|
||||
((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0;
|
||||
|
||||
if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) {
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_p->sn,
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_h,
|
||||
rlc_pP->vr_mr,
|
||||
rlc_pP->vr_ms,
|
||||
rlc_pP->vr_x);
|
||||
|
||||
pdu_status = rlc_am_rx_list_check_duplicate_insert_pdu(ctxt_pP, rlc_pP,tb_pP);
|
||||
if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
|
||||
rlc_pP->stat_rx_data_pdu_dropped += 1;
|
||||
rlc_pP->stat_rx_data_bytes_dropped += tb_size_in_bytesP;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED CAUSE=%d SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_status,pdu_info_p->sn);
|
||||
#if RLC_STOP_ON_LOST_PDU
|
||||
AssertFatal( 0 == 1,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
} else {
|
||||
// 5.1.3.2.3
|
||||
// Actions when a RLC data PDU is placed in the reception buffer
|
||||
//
|
||||
// When a RLC data PDU with SN = x is placed in the reception buffer, the receiving side of an AM RLC entity shall:
|
||||
// - if x >= VR(H)
|
||||
// - update VR(H) to x+ 1;
|
||||
//
|
||||
// - if all byte segments of the AMD PDU with SN = VR(MS) are received:
|
||||
// - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for which not all byte segments
|
||||
// have been received;
|
||||
//
|
||||
// - if x = VR(R):
|
||||
// - if all byte segments of the AMD PDU with SN = VR(R) are received:
|
||||
// - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments
|
||||
// have been received;
|
||||
// - update VR(MR) to the updated VR(R) + AM_Window_Size;
|
||||
//
|
||||
// - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving
|
||||
// window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when
|
||||
// doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before;
|
||||
//
|
||||
// - if t-Reordering is running:
|
||||
// - if VR(X) = VR(R); or
|
||||
// - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
|
||||
// - stop and reset t-Reordering;
|
||||
//
|
||||
// - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
|
||||
// - if VR (H) > VR(R):
|
||||
// - start t-Reordering;
|
||||
// - set VR(X) to VR(H).
|
||||
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] RX LIST AFTER INSERTION:\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION ");
|
||||
#endif
|
||||
|
||||
/* 1) Update vrH if sn >= vrH */
|
||||
if (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_h,rlc_pP->vr_r))
|
||||
{
|
||||
rlc_pP->vr_h = RLC_AM_NEXT_SN(pdu_info_p->sn);
|
||||
}
|
||||
|
||||
rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP);
|
||||
|
||||
/* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */
|
||||
if ((pdu_info_p->sn == rlc_pP->vr_ms) && (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received)) {
|
||||
rlc_am_rx_update_vr_ms(ctxt_pP, rlc_pP, tb_pP);
|
||||
}
|
||||
|
||||
if (pdu_info_p->sn == rlc_pP->vr_r) {
|
||||
mem_block_t* cursor_p = rlc_pP->receiver_buffer.head;
|
||||
rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data);
|
||||
if( (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) == (pdu_cursor_mgnt_p->all_segments_received)){
|
||||
if (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) {
|
||||
rlc_am_rx_update_vr_r(ctxt_pP, rlc_pP, tb_pP);
|
||||
rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
|
||||
}
|
||||
reassemble = rlc_am_rx_check_vr_reassemble(ctxt_pP, rlc_pP);
|
||||
//TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc...
|
||||
}else{
|
||||
LOG_E(RLC, "BAD all_segments_received!!! discard buffer!!!\n");
|
||||
/* Discard received block if out of window, duplicate or header error */
|
||||
free_mem_block (tb_pP, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
//FNA: fix check VrX out of receiving window
|
||||
if ((rlc_pP->t_reordering.running) || ((rlc_pP->t_reordering.ms_duration == 0) && (rlc_pP->vr_x != RLC_SN_UNDEFINED))) {
|
||||
if ((rlc_pP->vr_x == rlc_pP->vr_r) || (!(RLC_AM_SN_IN_WINDOW(rlc_pP->vr_x, rlc_pP->vr_r)) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
|
||||
rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
|
||||
rlc_pP->vr_x = RLC_SN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(rlc_pP->t_reordering.running)) {
|
||||
if (rlc_pP->vr_h != rlc_pP->vr_r) { // - if VR (H) > VR(R) translated to - if VR (H) != VR(R)
|
||||
rlc_pP->vr_x = rlc_pP->vr_h;
|
||||
if (rlc_pP->t_reordering.ms_duration != 0) {
|
||||
rlc_am_start_timer_reordering(ctxt_pP, rlc_pP);
|
||||
}
|
||||
else {
|
||||
/* specific case for no timer reordering configured */
|
||||
/* reordering window directly advances with vrH */
|
||||
rlc_pP->vr_ms = rlc_pP->vr_h;
|
||||
|
||||
/* Trigger a Status and clear any existing Delay Flag */
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] NEW VR(R) %04d VR(H) %04d VR(MS) %04d VR(MR) %04d VR(X) %04d reassemble=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_p->sn,
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_h,
|
||||
rlc_pP->vr_ms,
|
||||
rlc_pP->vr_mr,
|
||||
rlc_pP->vr_x,
|
||||
reassemble);
|
||||
} else {
|
||||
rlc_pP->stat_rx_data_pdu_out_of_window += 1;
|
||||
rlc_pP->stat_rx_data_bytes_out_of_window += tb_size_in_bytesP;
|
||||
pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU OUT OF RX WINDOW, DISCARDED, SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
|
||||
}
|
||||
|
||||
/* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */
|
||||
if ((pdu_info_p->p) && (pdu_status < RLC_AM_DATA_PDU_STATUS_BUFFER_FULL)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
/* Polling Info Saving for In and Out of Window PDU */
|
||||
/* avoid multi status trigger */
|
||||
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) ||
|
||||
!(RLC_AM_GET_STATUS(rlc_pP->status_requested,(RLC_AM_STATUS_TRIGGERED_POLL | RLC_AM_STATUS_TRIGGERED_T_REORDERING))))
|
||||
{
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_POLL);
|
||||
|
||||
if ((pdu_status != RLC_AM_DATA_PDU_STATUS_OK) || ((pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
|
||||
(!(RLC_AM_SN_IN_WINDOW(pdu_info_p->sn,rlc_pP->vr_r)) ||
|
||||
(RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
|
||||
)
|
||||
)
|
||||
{
|
||||
/* Conditions are met for sending a Status Report */
|
||||
/* Then clear Delay Flag and reset its corresponding sn */
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
else if (rlc_pP->sn_status_triggered_delayed == RLC_SN_UNDEFINED)
|
||||
{
|
||||
/* Delay status trigger if pdustatus OK and sn>= vr_ms */
|
||||
/* Note: vr_r and vr_ms have been updated */
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = pdu_info_p->sn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ReEnable a previously delayed Status Trigger if PDU discarded or */
|
||||
/* sn no more in RxWindow due to RxWindow advance or sn < vr_ms */
|
||||
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) &&
|
||||
(pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
|
||||
(!(RLC_AM_SN_IN_WINDOW(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r)) ||
|
||||
(RLC_AM_DIFF_SN(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
|
||||
)
|
||||
{
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED BAD HEADER FORMAT SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
|
||||
}
|
||||
|
||||
if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
|
||||
/* Discard received block if out of window, duplicate or header error */
|
||||
free_mem_block (tb_pP, __func__);
|
||||
}
|
||||
else if (reassemble) {
|
||||
/* Reassemble SDUs */
|
||||
rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
|
||||
}
|
||||
}
|
||||
@@ -260,12 +260,12 @@ void mac_rlc_data_ind (
|
||||
#ifdef DEBUG_MAC_INTERFACE
|
||||
|
||||
if (num_tbP) {
|
||||
LOG_I(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, Num_tb %d\n",
|
||||
LOG_I(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, tb_sizeP %d\n",
|
||||
PROTOCOL_CTXT_ARGS(&ctxt),
|
||||
channel_idP,
|
||||
RLC_MAX_LC,
|
||||
NB_RB_MAX,
|
||||
num_tbP);
|
||||
tb_sizeP);
|
||||
}
|
||||
|
||||
#endif // DEBUG_MAC_INTERFACE
|
||||
|
||||
@@ -94,6 +94,8 @@ rrc_data_req(
|
||||
RRC_DCCH_DATA_REQ (message_p).confirmp = confirmP;
|
||||
RRC_DCCH_DATA_REQ (message_p).sdu_size = sdu_sizeP;
|
||||
RRC_DCCH_DATA_REQ (message_p).sdu_p = message_buffer;
|
||||
//memcpy (RRC_DCCH_DATA_REQ (message_p).sdu_p, buffer_pP, sdu_sizeP);
|
||||
|
||||
RRC_DCCH_DATA_REQ (message_p).mode = modeP;
|
||||
RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id;
|
||||
RRC_DCCH_DATA_REQ (message_p).rnti = ctxt_pP->rnti;
|
||||
@@ -103,6 +105,10 @@ rrc_data_req(
|
||||
ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE,
|
||||
ctxt_pP->instance,
|
||||
message_p);
|
||||
LOG_I(RRC,"sent RRC_DCCH_DATA_REQ to TASK_PDCP_ENB\n");
|
||||
// RS/BK: Fix ME
|
||||
pdcp_run(ctxt_pP);
|
||||
|
||||
return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
|
||||
|
||||
}
|
||||
|
||||
@@ -1167,8 +1167,10 @@ rrc_eNB_generate_SecurityModeCommand(
|
||||
rrc_eNB_mui,
|
||||
size);
|
||||
|
||||
if ((RC.rrc[ctxt_pP->module_id]->node_type == ngran_eNB) ||
|
||||
(RC.rrc[ctxt_pP->module_id]->node_type == ngran_ng_eNB)) {
|
||||
if ((RC.rrc[ctxt_pP->module_id]->node_type != ngran_eNB_DU) ||
|
||||
(RC.rrc[ctxt_pP->module_id]->node_type != ngran_gNB_DU)) {
|
||||
LOG_I(RRC,"calling rrc_data_req :securityModeCommand\n");
|
||||
|
||||
rrc_data_req(
|
||||
ctxt_pP,
|
||||
DCCH,
|
||||
|
||||
@@ -923,7 +923,6 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS(
|
||||
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
|
||||
|
||||
LOG_DUMPMSG(RRC,DEBUG_RRC,buffer,length,"[MSG] RRC DL Information Transfer\n");
|
||||
|
||||
/*
|
||||
* switch UL or DL NAS message without RRC piggybacked to SRB2 if active.
|
||||
*/
|
||||
|
||||
@@ -85,6 +85,10 @@ int create_tasks(uint32_t enb_nb)
|
||||
if (enb_nb > 0) {
|
||||
rc = itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL);
|
||||
AssertFatal(rc >= 0, "Create task for CU F1AP failed\n");
|
||||
//RS/BK: Fix me!
|
||||
rc = itti_create_task (TASK_L2L1, l2l1_task, NULL);
|
||||
AssertFatal(rc >= 0, "Create task for L2L1 failed\n");
|
||||
|
||||
}
|
||||
/* fall through */
|
||||
case ngran_eNB:
|
||||
|
||||
@@ -1082,6 +1082,16 @@ int main( int argc, char **argv )
|
||||
RCconfig_L1();
|
||||
}
|
||||
|
||||
|
||||
if (RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU) {
|
||||
protocol_ctxt_t ctxt;
|
||||
ctxt.module_id = 0 ;
|
||||
ctxt.instance = 0;
|
||||
ctxt.rnti = 0;
|
||||
ctxt.enb_flag = 1;
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
|
||||
/* start threads if only L1 or not a CU */
|
||||
if (RC.nb_inst == 0 ||
|
||||
!(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
|
||||
|
||||
Reference in New Issue
Block a user