Commit 4bb802d9 authored by Anton Kozhemiachenko's avatar Anton Kozhemiachenko

bug#123699 (issue#108): NR TC_7.1.2.2.1 - DRB support

* part 2 (the test is pass with some hacks)
parent 36d05ea5
...@@ -226,7 +226,7 @@ SSConfig = ( ...@@ -226,7 +226,7 @@ SSConfig = (
Vng_port = 7779; #Port Number for System Simulator VNG Port Vng_port = 7779; #Port Number for System Simulator VNG Port
Vtp_port = 7780; #Port Number for System Simulator VTP Port Vtp_port = 7780; #Port Number for System Simulator VTP Port
Drb_port = 7781; #Port Number for System Simulator DRB Port Drb_port = 7781; #Port Number for System Simulator DRB Port
SSMode = 2; #SSMode: 0 - eNB , 1- SYS_PORT test , 2- Only SRB_PORT test SSMode = 1; #SSMode: 0 - eNB , 1- SYS_PORT test , 2- Only SRB_PORT test
} }
); );
......
...@@ -2355,6 +2355,8 @@ set(libnrnas_emm_msg_OBJS ...@@ -2355,6 +2355,8 @@ set(libnrnas_emm_msg_OBJS
${NAS_SRC}COMMON/EMM/MSG/FGSServiceRequest.c ${NAS_SRC}COMMON/EMM/MSG/FGSServiceRequest.c
${NAS_SRC}COMMON/EMM/MSG/ActivateTestModeComplete.c ${NAS_SRC}COMMON/EMM/MSG/ActivateTestModeComplete.c
${NAS_SRC}COMMON/EMM/MSG/CloseUeTestLoopComplete.c ${NAS_SRC}COMMON/EMM/MSG/CloseUeTestLoopComplete.c
${NAS_SRC}COMMON/EMM/MSG/OpenUeTestLoopComplete.c
${NAS_SRC}COMMON/EMM/MSG/DeactivateTestModeComplete.c
${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c
) )
......
...@@ -384,7 +384,10 @@ int create_gNB_tasks(uint32_t gnb_nb) { ...@@ -384,7 +384,10 @@ int create_gNB_tasks(uint32_t gnb_nb) {
return -1; return -1;
} }
if(itti_create_task(TASK_RLC_ENB, rlc_enb_task, NULL) < 0) {
LOG_E(RLC, "Create task for RLC eNB failed\n");
return -1;
}
} }
if(itti_create_task(TASK_SS_DRB, ss_gNB_drb_task, NULL) < 0) { if(itti_create_task(TASK_SS_DRB, ss_gNB_drb_task, NULL) < 0) {
......
...@@ -37,3 +37,4 @@ MESSAGE_DEF(RRC_DCCH_DATA_COPY_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataIn ...@@ -37,3 +37,4 @@ MESSAGE_DEF(RRC_DCCH_DATA_COPY_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataIn
// gNB // gNB
MESSAGE_DEF(NR_RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataReq, nr_rrc_dcch_data_req) MESSAGE_DEF(NR_RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataReq, nr_rrc_dcch_data_req)
MESSAGE_DEF(NR_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataInd, nr_rrc_dcch_data_ind) MESSAGE_DEF(NR_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataInd, nr_rrc_dcch_data_ind)
MESSAGE_DEF(NR_DTCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, NRDtchDataReq, nr_dtch_data_req)
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
// gNB // gNB
#define NR_RRC_DCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_req #define NR_RRC_DCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_req
#define NR_RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_ind #define NR_RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_ind
#define NR_DTCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nr_dtch_data_req
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
// Messages between RRC and PDCP layers // Messages between RRC and PDCP layers
...@@ -107,4 +108,18 @@ typedef struct RrcPcchDataReq_s { ...@@ -107,4 +108,18 @@ typedef struct RrcPcchDataReq_s {
uint8_t CC_id; uint8_t CC_id;
} RrcPcchDataReq; } RrcPcchDataReq;
typedef struct NRDtchDataReq_s {
uint32_t frame;
uint8_t gnb_flag;
rb_id_t rb_id;
uint32_t muip;
uint32_t confirmp;
uint32_t sdu_size;
uint8_t *sdu_p;
uint8_t mode;
uint16_t rnti;
uint8_t module_id;
uint8_t gNB_index;
} NRDtchDataReq;
#endif /* PDCP_MESSAGES_TYPES_H_ */ #endif /* PDCP_MESSAGES_TYPES_H_ */
...@@ -3099,6 +3099,8 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, ...@@ -3099,6 +3099,8 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
buflen_remain); buflen_remain);
while (buflen_remain > 0){ while (buflen_remain > 0){
//// TODO: temporary hack to support TTCN TC_7_1_2_2_1_NR5GC test
static int tbs_tmp = 0; if (lcid == 5) { if (tbs_tmp == 1) buflen_remain = 26; if (tbs_tmp > 1) buflen_remain = 28; } //TODO: tmp
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU // Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu; NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
...@@ -3116,6 +3118,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, ...@@ -3116,6 +3118,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
(char *)pdu, (char *)pdu,
0, 0,
0); 0);
if (lcid == 5 && sdu_length != 0) tbs_tmp++; //TODO: TMP
AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n", AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
__FUNCTION__, __FUNCTION__,
......
...@@ -479,7 +479,7 @@ void nr_store_dlsch_buffer(module_id_t module_id, ...@@ -479,7 +479,7 @@ void nr_store_dlsch_buffer(module_id_t module_id,
int lcid; int lcid;
const uint16_t rnti = UE_info->rnti[UE_id]; const uint16_t rnti = UE_info->rnti[UE_id];
LOG_D(NR_MAC,"UE %d/%x : lcid_mask %x\n",UE_id,rnti,sched_ctrl->lcid_mask); LOG_D(NR_MAC,"UE %d/%x : lcid_mask %x\n",UE_id,rnti,sched_ctrl->lcid_mask);
if ((sched_ctrl->lcid_mask&(1<<2)) > 0) if ((sched_ctrl->lcid_mask&(1<<DL_SCH_LCID_DCCH1)) > 0)
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1] = mac_rlc_status_ind(module_id, sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1] = mac_rlc_status_ind(module_id,
rnti, rnti,
module_id, module_id,
...@@ -490,7 +490,7 @@ void nr_store_dlsch_buffer(module_id_t module_id, ...@@ -490,7 +490,7 @@ void nr_store_dlsch_buffer(module_id_t module_id,
DL_SCH_LCID_DCCH1, DL_SCH_LCID_DCCH1,
0, 0,
0); 0);
if ((sched_ctrl->lcid_mask&(1<<1)) > 0) if ((sched_ctrl->lcid_mask&(1<<DL_SCH_LCID_DCCH)) > 0)
sched_ctrl->rlc_status[DL_SCH_LCID_DCCH] = mac_rlc_status_ind(module_id, sched_ctrl->rlc_status[DL_SCH_LCID_DCCH] = mac_rlc_status_ind(module_id,
rnti, rnti,
module_id, module_id,
...@@ -501,30 +501,36 @@ void nr_store_dlsch_buffer(module_id_t module_id, ...@@ -501,30 +501,36 @@ void nr_store_dlsch_buffer(module_id_t module_id,
DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH,
0, 0,
0); 0);
if ((sched_ctrl->lcid_mask&(1<<4)) > 0) { int dtch_id = -1;
start_meas(&RC.nrmac[module_id]->rlc_status_ind); for (int dtch_lcid = DL_SCH_LCID_DTCH; dtch_lcid <= DL_SCH_LCID_DTCH + 4; dtch_lcid++) {
sched_ctrl->rlc_status[DL_SCH_LCID_DTCH] = mac_rlc_status_ind(module_id, if ((sched_ctrl->lcid_mask&(1<<dtch_lcid)) > 0) {
rnti, start_meas(&RC.nrmac[module_id]->rlc_status_ind);
module_id, sched_ctrl->rlc_status[dtch_lcid] = mac_rlc_status_ind(module_id,
frame, rnti,
slot, module_id,
ENB_FLAG_YES, frame,
MBMS_FLAG_NO, slot,
DL_SCH_LCID_DTCH, ENB_FLAG_YES,
0, MBMS_FLAG_NO,
0); dtch_lcid,
stop_meas(&RC.nrmac[module_id]->rlc_status_ind); 0,
0);
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
if ((dtch_id == -1) && (sched_ctrl->rlc_status[dtch_lcid].bytes_in_buffer > 0)) {
dtch_id = dtch_lcid;
}
}
} }
if(sched_ctrl->rlc_status[DL_SCH_LCID_DCCH].bytes_in_buffer > 0){ if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH].bytes_in_buffer > 0) {
lcid = DL_SCH_LCID_DCCH; lcid = DL_SCH_LCID_DCCH;
} } else if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1].bytes_in_buffer > 0) {
else if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1].bytes_in_buffer > 0) lcid = DL_SCH_LCID_DCCH1;
{ } else if (dtch_id != -1) {
lcid = DL_SCH_LCID_DCCH1; lcid = dtch_id;
}else{ } else {
lcid = DL_SCH_LCID_DTCH; lcid = DL_SCH_LCID_DTCH;
} }
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
//later multiplex here. Just select DCCH/SRB before DTCH/DRB //later multiplex here. Just select DCCH/SRB before DTCH/DRB
sched_ctrl->lcid_to_schedule = lcid; sched_ctrl->lcid_to_schedule = lcid;
......
...@@ -457,6 +457,11 @@ int nr_process_mac_pdu(module_id_t module_idP, ...@@ -457,6 +457,11 @@ int nr_process_mac_pdu(module_id_t module_idP,
mac_sdu_len = 8; mac_sdu_len = 8;
// Check if it is a valid CCCH1 message, we get all 00's messages very often // Check if it is a valid CCCH1 message, we get all 00's messages very often
if (pdu_len < mac_subheader_len + mac_sdu_len) {
LOG_E(NR_MAC, "pdu_len %d is invalid (prior to cast of size %d)\n",
pdu_len, mac_subheader_len + mac_sdu_len);
return 0;
}
int i = 0; int i = 0;
for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) { for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) {
if(pduP[i] != 0) { if(pduP[i] != 0) {
...@@ -488,7 +493,7 @@ int nr_process_mac_pdu(module_id_t module_idP, ...@@ -488,7 +493,7 @@ int nr_process_mac_pdu(module_id_t module_idP,
0); 0);
break; break;
case UL_SCH_LCID_DTCH: case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 4):
// check if LCID is valid at current time. // check if LCID is valid at current time.
if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT)) if (pdu_len < sizeof(NR_MAC_SUBHEADER_SHORT))
return 0; return 0;
...@@ -516,6 +521,9 @@ int nr_process_mac_pdu(module_id_t module_idP, ...@@ -516,6 +521,9 @@ int nr_process_mac_pdu(module_id_t module_idP,
mac_sdu_len); mac_sdu_len);
UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len; UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
if (pdu_len < mac_subheader_len + mac_ce_len + mac_sdu_len)
return 0;
mac_rlc_data_ind(module_idP, mac_rlc_data_ind(module_idP,
UE_info->rnti[UE_id], UE_info->rnti[UE_id],
module_idP, module_idP,
......
...@@ -643,6 +643,10 @@ rlc_op_status_t rlc_stat_req ( ...@@ -643,6 +643,10 @@ rlc_op_status_t rlc_stat_req (
unsigned int *const stat_timer_poll_retransmit_timed_out, unsigned int *const stat_timer_poll_retransmit_timed_out,
unsigned int *const stat_timer_status_prohibit_timed_out); unsigned int *const stat_timer_status_prohibit_timed_out);
/* RLC ITTI messaging related functions */
/* Main loop of RLC itti message handling */
void *rlc_enb_task(void *arg);
/*! \fn int rlc_module_init(int enb_flag) /*! \fn int rlc_module_init(int enb_flag)
* \brief RAZ the memory of the RLC layer, initialize the memory pool manager (mem_block_t structures mainly used in RLC module). * \brief RAZ the memory of the RLC layer, initialize the memory pool manager (mem_block_t structures mainly used in RLC module).
*/ */
......
...@@ -543,6 +543,47 @@ static void start_pdcp_tun_ue(void) ...@@ -543,6 +543,47 @@ static void start_pdcp_tun_ue(void)
/* hacks to be cleaned up at some point - end */ /* hacks to be cleaned up at some point - end */
/****************************************************************************/ /****************************************************************************/
static void enqueue_pdcp_data_req(
protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_size,
unsigned char *const sdu_buffer,
const pdcp_transmission_mode_t modeP)
{
if (!srb_flagP) {
MessageDef *message_p;
uint8_t *message_buffer = itti_malloc(
ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE,
ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE,
sdu_buffer_size);
memcpy(message_buffer, sdu_buffer, sdu_buffer_size);
message_p = itti_alloc_new_message(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, 0, NR_DTCH_DATA_REQ);
NR_DTCH_DATA_REQ (message_p).frame = ctxt_pP->frame;
NR_DTCH_DATA_REQ (message_p).gnb_flag = ctxt_pP->enb_flag;
NR_DTCH_DATA_REQ (message_p).rb_id = rb_idP;
NR_DTCH_DATA_REQ (message_p).muip = muiP;
NR_DTCH_DATA_REQ (message_p).confirmp = confirmP;
NR_DTCH_DATA_REQ (message_p).sdu_size = sdu_buffer_size;
NR_DTCH_DATA_REQ (message_p).sdu_p = message_buffer;
NR_DTCH_DATA_REQ (message_p).mode = modeP;
NR_DTCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id;
NR_DTCH_DATA_REQ (message_p).rnti = ctxt_pP->rnti;
NR_DTCH_DATA_REQ (message_p).gNB_index = ctxt_pP->eNB_index;
itti_send_msg_to_task(
ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE,
ctxt_pP->instance,
message_p);
LOG_I(PDCP, "send NR_DTCH_DATA_REQ to PDCP\n");
} else {
LOG_E(PDCP, "not implemented for srb flag\n");
LOG_E(PDCP, "%s:%d:%s: fatal, not implemented\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP)
{ {
return 0; return 0;
...@@ -606,6 +647,13 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id) ...@@ -606,6 +647,13 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id)
if (PDCP_USE_NETLINK) { if (PDCP_USE_NETLINK) {
nas_getparams(); nas_getparams();
/* TODO: TTCN support, disable TUN device.
* TTCN doesn't send correct IP packet, but random data for DATA loopback,
* need to choose correct flag in 'if' statement to identify that fact. */
if (IS_SOFTMODEM_NOS1 || (ENB_NAS_USE_TUN || UE_NAS_USE_TUN)) {
return pdcp_optmask;
}
if(UE_NAS_USE_TUN) { if(UE_NAS_USE_TUN) {
char *ifsuffix_ue = get_softmodem_params()->nsa ? "nrue" : "ue"; char *ifsuffix_ue = get_softmodem_params()->nsa ? "nrue" : "ue";
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 || NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF)? MAX_MOBILES_PER_ENB : 1; int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 || NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF)? MAX_MOBILES_PER_ENB : 1;
...@@ -641,6 +689,26 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, ...@@ -641,6 +689,26 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
int rb_id; int rb_id;
int i; int i;
/* TODO: TTCN support.
* Also TTCN doesn't send correct IP packet, but random data for DATA loopback,
* need to choose correct flag in 'if' statement to identify that fact. */
if (IS_SOFTMODEM_NOS1 || (ENB_NAS_USE_TUN || UE_NAS_USE_TUN)) {
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(
&ctxt,
0,
entity->is_gnb,
ue->rnti,
nr_pdcp_current_time_last_frame,
nr_pdcp_current_time_last_subframe,
0);
LOG_D(PDCP, "%s(): (drb %d) calling enqueue_pdcp_data_req size %d\n", __func__, entity->rb_id, size);
enqueue_pdcp_data_req(&ctxt, SRB_FLAG_NO, entity->rb_id,
RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO,
size, buf, PDCP_TRANSMISSION_MODE_DATA);
return;
}
if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) { if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) {
LOG_D(PDCP, "IP packet received, to be sent to TUN interface"); LOG_D(PDCP, "IP packet received, to be sent to TUN interface");
...@@ -719,15 +787,14 @@ static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity, ...@@ -719,15 +787,14 @@ static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity,
exit(1); exit(1);
rb_found: rb_found:
ctxt.module_id = 0; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,
ctxt.enb_flag = 1; 0,
ctxt.instance = 0; entity->is_gnb,
ctxt.frame = 0; ue->rnti,
ctxt.subframe = 0; nr_pdcp_current_time_last_frame,
ctxt.eNB_index = 0; nr_pdcp_current_time_last_subframe,
ctxt.brOption = 0; 0);
ctxt.rnti = ue->rnti;
if (RC.nrrrc != NULL && NODE_IS_CU(RC.nrrrc[0]->node_type)) { if (RC.nrrrc != NULL && NODE_IS_CU(RC.nrrrc[0]->node_type)) {
MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0,
GTPV1U_GNB_TUNNEL_DATA_REQ, GTPV1U_GNB_TUNNEL_DATA_REQ,
...@@ -925,10 +992,41 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP) ...@@ -925,10 +992,41 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p); result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
break; break;
case NR_DTCH_DATA_REQ:
LOG_D(PDCP, "Received NR_DTCH_DATA_REQ type at PDCP task \n");
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,
NR_DTCH_DATA_REQ(msg_p).module_id,
NR_DTCH_DATA_REQ(msg_p).gnb_flag,
NR_DTCH_DATA_REQ(msg_p).rnti,
NR_DTCH_DATA_REQ(msg_p).frame,
0,
NR_DTCH_DATA_REQ(msg_p).gNB_index);
LOG_A(PDCP, "Sending packet to PDCP, Calling pdcp_data_req ue %x drb id %ld len %u\n",
ctxt.rnti, NR_DTCH_DATA_REQ(msg_p).rb_id, NR_DTCH_DATA_REQ(msg_p).sdu_size);
result = pdcp_data_req(&ctxt,
SRB_FLAG_NO,
NR_DTCH_DATA_REQ(msg_p).rb_id,
NR_DTCH_DATA_REQ(msg_p).muip,
NR_DTCH_DATA_REQ(msg_p).confirmp,
NR_DTCH_DATA_REQ(msg_p).sdu_size,
NR_DTCH_DATA_REQ(msg_p).sdu_p,
NR_DTCH_DATA_REQ(msg_p).mode,
NULL, NULL);
if (result != TRUE)
LOG_E(PDCP, "PDCP data request failed!\n");
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), NR_DTCH_DATA_REQ(msg_p).sdu_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
break;
default: default:
LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p)); LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
break; break;
} }
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
msg_p = NULL;
} }
} }
......
...@@ -87,8 +87,6 @@ nr_rlc_entity_t *new_nr_rlc_entity_am( ...@@ -87,8 +87,6 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
ret->common.reestablishment = nr_rlc_entity_am_reestablishment; ret->common.reestablishment = nr_rlc_entity_am_reestablishment;
ret->common.delete = nr_rlc_entity_am_delete; ret->common.delete = nr_rlc_entity_am_delete;
ret->common.deliver_pdu = nr_rlc_entity_am_deliver_pdu;
ret->common.deliver_sdu = deliver_sdu; ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data; ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.sdu_successful_delivery = sdu_successful_delivery; ret->common.sdu_successful_delivery = sdu_successful_delivery;
...@@ -172,8 +170,6 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm( ...@@ -172,8 +170,6 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm(
ret->common.reestablishment = nr_rlc_entity_tm_reestablishment; ret->common.reestablishment = nr_rlc_entity_tm_reestablishment;
ret->common.delete = nr_rlc_entity_tm_delete; ret->common.delete = nr_rlc_entity_tm_delete;
/* ret->common.deliver_pdu = nr_rlc_entity_tm_deliver_pdu; */
ret->common.deliver_sdu = deliver_sdu; ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data; ret->common.deliver_sdu_data = deliver_sdu_data;
......
...@@ -83,11 +83,6 @@ static int sn_compare_tx(void *_entity, int a, int b) ...@@ -83,11 +83,6 @@ static int sn_compare_tx(void *_entity, int a, int b)
return modulus_tx(entity, a) - modulus_tx(entity, b); return modulus_tx(entity, a) - modulus_tx(entity, b);
} }
static int sn_compare_full_tx(void *_entity, int a, int b)
{
return 0;
}
static int segment_already_received(nr_rlc_entity_am_t *entity, static int segment_already_received(nr_rlc_entity_am_t *entity,
int sn, int so, int size) int sn, int so, int size)
{ {
...@@ -1570,40 +1565,6 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( ...@@ -1570,40 +1565,6 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
return ret; return ret;
} }
static int generate_tx_full_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
{
nr_rlc_pdu_t *pdu;
int ret;
int pdu_header_size;
int sdu_size;
pdu = entity->tx_extra_list;
/* AMD SN12 header length */
pdu_header_size = 2;
sdu_size = pdu->size - pdu_header_size;
if (pdu->size > size) {
LOG_E(RLC, "%s:%d:%s: buffer is small\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
/* update buffer status */
entity->common.bstatus.tx_size -= pdu->size;
/* deliver */
memcpy(buffer, pdu->data, pdu->size);
entity->tx_size -= sdu_size;
entity->tx_extra_list = pdu->next;
ret = pdu->size;
nr_rlc_free_pdu(pdu);
return ret;
}
int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *_entity, int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *_entity,
char *buffer, int size, nr_rlc_pkt_info_t *rlc_info) char *buffer, int size, nr_rlc_pkt_info_t *rlc_info)
...@@ -1628,54 +1589,11 @@ int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *_entity, ...@@ -1628,54 +1589,11 @@ int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *_entity,
return ret; return ret;
} }
if (RC.ss.mode > SS_GNB) {
if (entity->tx_extra_list != NULL) {
ret = generate_tx_full_pdu(entity, buffer, size);
rlc_info->pduLength = ret;
return ret;
}
}
ret = generate_tx_pdu(entity, buffer, size); ret = generate_tx_pdu(entity, buffer, size);
rlc_info->pduLength = ret; rlc_info->pduLength = ret;
return ret; return ret;
} }
void nr_rlc_entity_am_deliver_pdu(nr_rlc_entity_t *_entity, char *buffer, int size)
{
nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
nr_rlc_pdu_t *pdu;
int pdu_header_size;
int sdu_size;
/* AMD SN12 header length */
pdu_header_size = 2;
sdu_size = size - pdu_header_size;
if (sdu_size > NR_SDU_MAX) {
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
__FILE__, __LINE__, __FUNCTION__, sdu_size);
exit(1);
}
if (entity->tx_size + sdu_size > entity->tx_maxsize) {
LOG_W(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
__FILE__, __LINE__, __FUNCTION__);
return;
}
entity->tx_size += sdu_size;
/* PDU contains full RLC PDU with header */
pdu = nr_rlc_new_pdu(0, 0, 1, 1, buffer, size);
entity->tx_extra_list = nr_rlc_pdu_list_add(sn_compare_full_tx, entity,
entity->tx_extra_list, pdu);
/* update buffer status */
entity->common.bstatus.tx_size += size;
}
/*************************************************************************/ /*************************************************************************/
/* SDU RX functions */ /* SDU RX functions */
/*************************************************************************/ /*************************************************************************/
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "nr_rlc_entity.h" #include "nr_rlc_entity.h"
#include "nr_rlc_sdu.h" #include "nr_rlc_sdu.h"
#include "nr_rlc_pdu.h"
typedef struct { typedef struct {
nr_rlc_entity_t common; nr_rlc_entity_t common;
...@@ -37,9 +36,6 @@ typedef struct { ...@@ -37,9 +36,6 @@ typedef struct {
nr_rlc_sdu_segment_t *tx_end; nr_rlc_sdu_segment_t *tx_end;
int tx_size; int tx_size;
int tx_maxsize; int tx_maxsize;
/* TTCN DRB support: contains the RLC PDU list to be sent to MAC directly */
nr_rlc_pdu_t *tx_extra_list;
} nr_rlc_entity_tm_t; } nr_rlc_entity_tm_t;
void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *entity, void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *entity,
......
...@@ -45,6 +45,19 @@ static int compute_pdu_header_size(nr_rlc_entity_um_t *entity, ...@@ -45,6 +45,19 @@ static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
return header_size; return header_size;
} }
static int compute_extra_pdu_header_size(nr_rlc_entity_um_t *entity,
nr_rlc_pdu_t *pdu)
{
int header_size = 1;
/* if SN to be included then one more byte if SN field length is 12 */
if (!(pdu->is_first && pdu->is_last) && entity->sn_field_length == 12)
header_size++;
/* two more bytes for SO if SDU segment is not the first */
if (!pdu->is_first) header_size += 2;
return header_size;
}
/*************************************************************************/ /*************************************************************************/
/* PDU RX functions */ /* PDU RX functions */
/*************************************************************************/ /*************************************************************************/
...@@ -63,7 +76,7 @@ static int sn_compare_rx(void *_entity, int a, int b) ...@@ -63,7 +76,7 @@ static int sn_compare_rx(void *_entity, int a, int b)
return modulus_rx(entity, a) - modulus_rx(entity, b); return modulus_rx(entity, a) - modulus_rx(entity, b);
} }
static int sn_compare_full_tx(void *_entity, int a, int b) static int sn_compare_extra_tx(void *_entity, int a, int b)
{ {
return 0; return 0;
} }
...@@ -403,6 +416,36 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity, ...@@ -403,6 +416,36 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity,
return encoder.byte + sdu->size; return encoder.byte + sdu->size;
} }
static int serialize_pdu(nr_rlc_entity_um_t *entity,
nr_rlc_pdu_t *pdu, char *buffer, int bufsize)
{
nr_rlc_pdu_encoder_t encoder;
/* generate header */
nr_rlc_pdu_encoder_init(&encoder, buffer, bufsize);
nr_rlc_pdu_encoder_put_bits(&encoder, 1-pdu->is_first,1);/* 1st bit of SI */
nr_rlc_pdu_encoder_put_bits(&encoder, 1-pdu->is_last,1); /* 2nd bit of SI */
/* SN, if required */
if (pdu->is_first == 1 && pdu->is_last == 1) {
nr_rlc_pdu_encoder_put_bits(&encoder, 0, 6); /* R */
} else {
if (entity->sn_field_length == 12)
nr_rlc_pdu_encoder_put_bits(&encoder, 0, 2); /* R */
nr_rlc_pdu_encoder_put_bits(&encoder, pdu->sn,
entity->sn_field_length); /* SN */
}
if (!pdu->is_first)
nr_rlc_pdu_encoder_put_bits(&encoder, pdu->so, 16); /* SO */
/* data */
memcpy(buffer + encoder.byte, pdu->data, pdu->size);
return encoder.byte + pdu->size;
}
/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size' /* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
* bytes * bytes
* - modifies SDU/SDU segment to become an SDU segment * - modifies SDU/SDU segment to become an SDU segment
...@@ -522,36 +565,34 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( ...@@ -522,36 +565,34 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
return ret; return ret;
} }
static int generate_tx_full_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) static int generate_tx_extra_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
{ {
nr_rlc_pdu_t *pdu; nr_rlc_pdu_t *pdu;
int ret;
int pdu_header_size; int pdu_header_size;
int sdu_size; int pdu_size;
int ret;
pdu = entity->tx_extra_list; if (entity->tx_extra_list == NULL)
return 0;
/* UMD NoSN header length */ pdu = entity->tx_extra_list;
pdu_header_size = 1;
sdu_size = pdu->size - pdu_header_size; pdu_header_size = compute_extra_pdu_header_size(entity, pdu);
if (pdu->size > size) { /* not enough room for at least one byte of data? do nothing */
LOG_E(RLC, "%s:%d:%s: buffer is small\n", __FILE__, __LINE__, __FUNCTION__); if (pdu_header_size + 1 > size)
exit(1); return 0;
}
/* update buffer status */ entity->tx_extra_list = pdu->next;
entity->common.bstatus.tx_size -= pdu->size;
/* deliver */ pdu_size = pdu_header_size + pdu->size;
memcpy(buffer, pdu->data, pdu->size);
entity->tx_size -= sdu_size; /* update buffer status */
entity->common.bstatus.tx_size -= pdu_size;
entity->tx_extra_list = pdu->next; ret = serialize_pdu(entity, pdu, buffer, size);
ret = pdu->size;
entity->tx_size -= pdu->size;
nr_rlc_free_pdu(pdu); nr_rlc_free_pdu(pdu);
return ret; return ret;
...@@ -565,7 +606,7 @@ int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity, ...@@ -565,7 +606,7 @@ int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity,
if (RC.ss.mode > SS_GNB) { if (RC.ss.mode > SS_GNB) {
if (entity->tx_extra_list != NULL) { if (entity->tx_extra_list != NULL) {
ret = generate_tx_full_pdu(entity, buffer, size); ret = generate_tx_extra_pdu(entity, buffer, size);
rlc_info->rlcMode = 2; /** UM Mode */ rlc_info->rlcMode = 2; /** UM Mode */
rlc_info->sequenceNumberLength = entity->sn_field_length; rlc_info->sequenceNumberLength = entity->sn_field_length;
rlc_info->pduLength = ret; rlc_info->pduLength = ret;
...@@ -580,39 +621,82 @@ int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity, ...@@ -580,39 +621,82 @@ int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity,
return ret; return ret;
} }
void nr_rlc_entity_um_deliver_pdu(nr_rlc_entity_t *_entity, char *buffer, int size) static void deliver_extra_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
{ {
nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity; #define R(d) do { if (nr_rlc_pdu_decoder_in_error(&d)) goto err; } while (0)
nr_rlc_pdu_decoder_t decoder;
nr_rlc_pdu_t *pdu; nr_rlc_pdu_t *pdu;
int pdu_header_size; int si;
int sdu_size; int sn;
int so = 0;
int data_size;
int is_first;
int is_last;
/* UMD NoSN header length */ nr_rlc_pdu_decoder_init(&decoder, buffer, size);
pdu_header_size = 1;
sdu_size = size - pdu_header_size; si = nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
if (sdu_size > NR_SDU_MAX) { is_first = (si & 0x2) == 0;
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n", is_last = (si & 0x1) == 0;
__FILE__, __LINE__, __FUNCTION__, sdu_size);
exit(1); if (entity->sn_field_length == 12) {
nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
} }
if (entity->tx_size + sdu_size > entity->tx_maxsize) { sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length);
LOG_W(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", R(decoder);
if (!is_first) {
so = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
if (so == 0) {
LOG_E(RLC, "%s:%d:%s: warning: discard PDU, bad so\n",
__FILE__, __LINE__, __FUNCTION__);
goto discard;
}
}
data_size = size - decoder.byte;
/* dicard PDU if no data */
if (data_size <= 0) {
LOG_W(RLC, "%s:%d:%s: warning: discard PDU, no data\n",
__FILE__, __LINE__, __FUNCTION__); __FILE__, __LINE__, __FUNCTION__);
return; goto discard;
} }
entity->tx_size += sdu_size; /* dicard PDU if tx buffer is full */
if (entity->tx_size + data_size > entity->tx_maxsize) {
LOG_W(RLC, "%s:%d:%s: warning: discard PDU, TX buffer full\n",
__FILE__, __LINE__, __FUNCTION__);
goto discard;
}
entity->tx_size += data_size;
/* PDU contains full RLC PDU with header */ pdu = nr_rlc_new_pdu(sn, so, is_first, is_last,
pdu = nr_rlc_new_pdu(0, 0, 1, 1, buffer, size); buffer + size - data_size, data_size);
entity->tx_extra_list = nr_rlc_pdu_list_add(sn_compare_full_tx, entity, entity->tx_extra_list = nr_rlc_pdu_list_add(sn_compare_extra_tx, entity,
entity->tx_extra_list, pdu); entity->tx_extra_list, pdu);
/* update buffer status */ /* update buffer status */
entity->common.bstatus.tx_size += size; entity->common.bstatus.tx_size += size;
return;
err:
LOG_W(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__);
goto discard;
discard:
return;
#undef R
}
void nr_rlc_entity_um_deliver_pdu(nr_rlc_entity_t *_entity, char *buffer, int size)
{
deliver_extra_pdu((nr_rlc_entity_um_t *)_entity, buffer, size);
} }
/*************************************************************************/ /*************************************************************************/
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#include "openair2/F1AP/f1ap_du_rrc_message_transfer.h" #include "openair2/F1AP/f1ap_du_rrc_message_transfer.h"
#include "LAYER2/MAC/mac_extern.h"
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
#include <stdint.h> #include <stdint.h>
...@@ -157,6 +159,32 @@ void mac_rlc_data_ind ( ...@@ -157,6 +159,32 @@ void mac_rlc_data_ind (
T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP), T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP),
T_INT(channel_idP), T_INT(tb_sizeP)); T_INT(channel_idP), T_INT(tb_sizeP));
if (RC.ss.mode >= SS_SOFTMODEM) {
if ((tb_sizeP != 0) && (TRUE == enb_flagP) && (channel_idP >= 4)) {
int drb_id = channel_idP - 3;
int result;
LOG_A(RLC, "Sending packet to SS, Calling SS_DRB_PDU_IND ue %x drb id %ld size %u\n",
rntiP, drb_id, tb_sizeP);
MessageDef *message_p = itti_alloc_new_message (TASK_SS_DRB, 0, SS_DRB_PDU_IND);
if (message_p) {
SS_DRB_PDU_IND (message_p).drb_id = drb_id;
SS_DRB_PDU_IND (message_p).frame = frameP;
SS_DRB_PDU_IND (message_p).subframe = 0;
SS_DRB_PDU_IND (message_p).physCellId = RC.nrrrc[module_idP]->carrier.physCellId;
SS_DRB_PDU_IND (message_p).sdu_size = tb_sizeP;
memcpy(SS_DRB_PDU_IND (message_p).sdu, buffer_pP, tb_sizeP);
result = itti_send_msg_to_task (TASK_SS_DRB, ENB_MODULE_ID_TO_INSTANCE(module_idP), message_p);
if (result < 0) {
LOG_E(RLC, "Error in itti_send_msg_to_task!\n");
}
}
return;
}
}
// Trace UL RLC PDU Here // Trace UL RLC PDU Here
nr_rlc_pkt_info_t rlc_pkt; nr_rlc_pkt_info_t rlc_pkt;
rlc_pkt.direction = DIRECTION_UPLINK; rlc_pkt.direction = DIRECTION_UPLINK;
...@@ -476,6 +504,7 @@ rlc_op_status_t enqueue_mac_rlc_data_req( ...@@ -476,6 +504,7 @@ rlc_op_status_t enqueue_mac_rlc_data_req(
} }
if (rb != NULL) { if (rb != NULL) {
DevAssert(rb->deliver_pdu != NULL);
rb->deliver_pdu(rb, (char *)sdu_pP->data, sdu_sizeP); rb->deliver_pdu(rb, (char *)sdu_pP->data, sdu_sizeP);
} else { } else {
LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__);
...@@ -744,6 +773,70 @@ rb_found: ...@@ -744,6 +773,70 @@ rb_found:
#endif #endif
} }
void *rlc_enb_task(void *arg)
//-----------------------------------------------------------------------------
{
MessageDef *received_msg = NULL;
int result;
itti_mark_task_ready(TASK_RLC_ENB);
LOG_I(RLC, "Starting main loop of RLC message task\n");
while (1) {
itti_receive_msg(TASK_RLC_ENB, &received_msg);
switch (ITTI_MSG_ID(received_msg)) {
case SS_DRB_PDU_REQ:
if (RC.ss.mode >= SS_SOFTMODEM) {
protocol_ctxt_t ctxt;
instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(received_msg);
LOG_D(RLC, "RLC received SS_DRB_PDU_REQ DRB_ID:%d SDU_SIZE:%d\n",
SS_DRB_PDU_REQ(received_msg).drb_id, SS_DRB_PDU_REQ(received_msg).sdu_size);
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
GNB_FLAG_YES,
SS_DRB_PDU_REQ(received_msg).rnti,
received_msg->ittiMsgHeader.lte_time.frame,
received_msg->ittiMsgHeader.lte_time.slot);
mem_block_t *sdu = get_free_mem_block(SS_DRB_PDU_REQ(received_msg).sdu_size, __func__);
memcpy(sdu->data, SS_DRB_PDU_REQ(received_msg).sdu, SS_DRB_PDU_REQ(received_msg).sdu_size);
enqueue_mac_rlc_data_req(&ctxt,
SRB_FLAG_NO,
MBMS_FLAG_NO,
SS_DRB_PDU_REQ(received_msg).drb_id,
0,
0,
SS_DRB_PDU_REQ(received_msg).sdu_size,
sdu,
NULL,
NULL);
/* rlc_data_req(&ctxt, SRB_FLAG_NO, MBMS_FLAG_NO, SS_DRB_PDU_REQ(received_msg).drb_id, 0, 0, SS_DRB_PDU_REQ(received_msg).sdu_size, sdu, NULL, NULL); */
} else {
LOG_E(RLC, "Received unexpected message %s\n", ITTI_MSG_NAME(received_msg));
}
break;
case TERMINATE_MESSAGE:
LOG_W(RLC, " *** Exiting RLC thread\n");
itti_exit_task();
break;
default:
LOG_E(RLC, "Received unexpected message %s\n", ITTI_MSG_NAME(received_msg));
break;
} // end switch
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
received_msg = NULL;
} // end while
return NULL;
}
static void add_rlc_srb(int rnti, struct NR_SRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) static void add_rlc_srb(int rnti, struct NR_SRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig)
{ {
nr_rlc_entity_t *nr_rlc_am; nr_rlc_entity_t *nr_rlc_am;
......
...@@ -3991,26 +3991,6 @@ void *rrc_gnb_task(void *args_p) { ...@@ -3991,26 +3991,6 @@ void *rrc_gnb_task(void *args_p) {
} }
break; break;
case SS_DRB_PDU_REQ:
LOG_A(NR_RRC, "NR RRC received SS_DRB_PDU_REQ DRB_ID:%d SDU_SIZE:%d\n", SS_DRB_PDU_REQ(msg_p).drb_id, SS_DRB_PDU_REQ(msg_p).sdu_size);
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
GNB_FLAG_YES,
SS_DRB_PDU_REQ(msg_p).rnti,
msg_p->ittiMsgHeader.lte_time.frame,
msg_p->ittiMsgHeader.lte_time.slot);
/* skip RLC header from DRB port */
mem_block_t *sdu = get_free_mem_block(SS_DRB_PDU_REQ(msg_p).sdu_size - 1, __func__);
memcpy(sdu->data, SS_DRB_PDU_REQ(msg_p).sdu + 1, SS_DRB_PDU_REQ(msg_p).sdu_size - 1);
rlc_data_req(&ctxt, SRB_FLAG_NO, MBMS_FLAG_NO, SS_DRB_PDU_REQ(msg_p).drb_id, 0, 0, SS_DRB_PDU_REQ(msg_p).sdu_size - 1, sdu, NULL, NULL);
/* mem_block_t *sdu = get_free_mem_block(SS_DRB_PDU_REQ(msg_p).sdu_size, __func__); */
/* memcpy(sdu->data, SS_DRB_PDU_REQ(msg_p).sdu, SS_DRB_PDU_REQ(msg_p).sdu_size); */
/* enqueue_mac_rlc_data_req(&ctxt, SRB_FLAG_NO, MBMS_FLAG_NO, SS_DRB_PDU_REQ(msg_p).drb_id, 0, 0, SS_DRB_PDU_REQ(msg_p).sdu_size, sdu, NULL, NULL); */
break;
default: default:
LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p);
break; break;
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file DeactivateTestModeComplete.c
\brief test mode procedures for eNB/gNB
\author
\email:
\date 2022
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "nas_log.h"
#include "DeactivateTestModeComplete.h"
int encode_deactivate_test_mode_complete(deactivate_test_mode_complete_msg *deactivate_test_mode_complete, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
/* *(buffer + encoded) = deactivate_test_mode_complete->protocoldiscriminator; */
/* encoded++; */
/* *(buffer + encoded) = deactivate_test_mode_complete->messagetype; */
/* encoded++; */
return encoded;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file DeactivateTestModeComplete.h
\brief test mode procedures for eNB/gNB
\author
\email:
\date 2022
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "MessageType.h"
#ifndef DEACTIVATE_TEST_MODE_COMPLETE_H_
#define DEACTIVATE_TEST_MODE_COMPLETE_H_
typedef struct deactivate_test_mode_complete_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator; // LTE: skipIndicator + protocolDiscriminator
SecurityHeaderType securityheadertype:4; // LTE: missing
SpareHalfOctet sparehalfoctet:4; // LTE: missing
MessageType messagetype;
/* Optional fields */
} deactivate_test_mode_complete_msg;
int encode_deactivate_test_mode_complete(deactivate_test_mode_complete_msg *deactivate_test_mode_complete, uint8_t *buffer, uint32_t len);
#endif /* ! defined(DEACTIVATE_TEST_MODE_COMPLETE_H_) */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file OpenUeTestLoopComplete.c
\brief test mode procedures for eNB/gNB
\author
\email:
\date 2022
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "nas_log.h"
#include "OpenUeTestLoopComplete.h"
int encode_open_ue_test_loop_complete(open_ue_test_loop_complete_msg *open_ue_test_loop_complete, uint8_t *buffer, uint32_t len)
{
int encoded = 0;
/* *(buffer + encoded) = open_ue_test_loop_complete->protocoldiscriminator; */
/* encoded++; */
/* *(buffer + encoded) = open_ue_test_loop_complete->messagetype; */
/* encoded++; */
return encoded;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file OpenUeTestLoopComplete.h
\brief test mode procedures for eNB/gNB
\author
\email:
\date 2022
\version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ExtendedProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "SpareHalfOctet.h"
#include "MessageType.h"
#ifndef OPEN_UE_TEST_LOOP_COMPLETE_H_
#define OPEN_UE_TEST_LOOP_COMPLETE_H_
typedef struct open_ue_test_loop_complete_msg_tag {
/* Mandatory fields */
ExtendedProtocolDiscriminator protocoldiscriminator; // LTE: skipIndicator + protocolDiscriminator
SecurityHeaderType securityheadertype:4; // LTE: missing
SpareHalfOctet sparehalfoctet:4; // LTE: missing
MessageType messagetype;
/* Optional fields */
} open_ue_test_loop_complete_msg;
int encode_open_ue_test_loop_complete(open_ue_test_loop_complete_msg *open_ue_test_loop_complete, uint8_t *buffer, uint32_t len);
#endif /* ! defined(OPEN_UE_TEST_LOOP_COMPLETE_H_) */
...@@ -144,6 +144,12 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { ...@@ -144,6 +144,12 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) {
case CLOSE_UE_TEST_LOOP_COMPLETE: case CLOSE_UE_TEST_LOOP_COMPLETE:
encode_result = encode_close_ue_test_loop_complete(&mm_msg->close_ue_test_loop_complete, buffer, len); encode_result = encode_close_ue_test_loop_complete(&mm_msg->close_ue_test_loop_complete, buffer, len);
break; break;
case OPEN_UE_TEST_LOOP_COMPLETE:
encode_result = encode_open_ue_test_loop_complete(&mm_msg->open_ue_test_loop_complete, buffer, len);
break;
case DEACTIVATE_TEST_MODE_COMPLETE:
encode_result = encode_deactivate_test_mode_complete(&mm_msg->deactivate_test_mode_complete, buffer, len);
break;
case FGS_SERVICE_REQUEST: case FGS_SERVICE_REQUEST:
encode_result = encode_fgs_service_request(&mm_msg->fgs_service_request, buffer, len); encode_result = encode_fgs_service_request(&mm_msg->fgs_service_request, buffer, len);
break; break;
...@@ -918,6 +924,110 @@ static void generateCloseUeTestLoopComplete(int Mod_id, as_nas_info_t *initialNa ...@@ -918,6 +924,110 @@ static void generateCloseUeTestLoopComplete(int Mod_id, as_nas_info_t *initialNa
} }
} }
static void generateOpenUeTestLoopComplete(int Mod_id, as_nas_info_t *initialNasMsg) {
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg={0};
MM_msg *mm_msg;
nas_stream_cipher_t stream_cipher;
uint8_t mac[4];
nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED;
size += 7;
mm_msg = &nas_msg.security_protected.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = TEST_PD;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = OPEN_UE_TEST_LOOP_COMPLETE;
// set activate test mode complete
mm_msg->open_ue_test_loop_complete.protocoldiscriminator = TEST_PD;
size += 1;
mm_msg->open_ue_test_loop_complete.messagetype = OPEN_UE_TEST_LOOP_COMPLETE;
size += 1;
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size);
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = ue_security_key[Mod_id]->knas_int;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
stream_cipher.direction = 0;
stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6);
/* length in bits */
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
/* Workaround fix of bypassing security for the TTCN */
#if 0
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
#endif
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
initialNasMsg->data[2+i] = 0;//mac[i];/* Workaround fix of bypassing security for the TTCN */
}
}
static void generateDeactivateTestModeComplete(int Mod_id, as_nas_info_t *initialNasMsg) {
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg={0};
MM_msg *mm_msg;
nas_stream_cipher_t stream_cipher;
uint8_t mac[4];
nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE;
nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED;
size += 7;
mm_msg = &nas_msg.security_protected.plain.mm_msg;
// set header
mm_msg->header.ex_protocol_discriminator = TEST_PD;
mm_msg->header.security_header_type = PLAIN_5GS_MSG;
mm_msg->header.message_type = DEACTIVATE_TEST_MODE_COMPLETE;
// set activate test mode complete
mm_msg->deactivate_test_mode_complete.protocoldiscriminator = TEST_PD;
size += 1;
mm_msg->deactivate_test_mode_complete.messagetype = DEACTIVATE_TEST_MODE_COMPLETE;
size += 1;
// encode the message
initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t));
int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size);
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = ue_security_key[Mod_id]->knas_int;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
stream_cipher.direction = 0;
stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6);
/* length in bits */
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
/* Workaround fix of bypassing security for the TTCN */
#if 0
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
#endif
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
initialNasMsg->data[2+i] = 0;//mac[i];/* Workaround fix of bypassing security for the TTCN */
}
}
void generateServiceRequestInner(as_nas_info_t *initialNasMsg, int Mod_id) { void generateServiceRequestInner(as_nas_info_t *initialNasMsg, int Mod_id) {
int size = sizeof(mm_msg_header_t); int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg={0}; fgs_nas_message_t nas_msg={0};
...@@ -1239,9 +1349,15 @@ void *nas_nrue_task(void *args_p) ...@@ -1239,9 +1349,15 @@ void *nas_nrue_task(void *args_p)
case NR_CLOSE_UE_TEST_LOOP: case NR_CLOSE_UE_TEST_LOOP:
generateCloseUeTestLoopComplete(Mod_id, &initialNasMsg); generateCloseUeTestLoopComplete(Mod_id, &initialNasMsg);
break; break;
default: case OPEN_UE_TEST_LOOP:
LOG_W(NR_RRC,"unknow message type %d\n",msg_type); generateOpenUeTestLoopComplete(Mod_id, &initialNasMsg);
break; break;
case DEACTIVATE_TEST_MODE:
generateDeactivateTestModeComplete(Mod_id, &initialNasMsg);
break;
default:
LOG_W(NR_RRC,"unknow message type %d\n",msg_type);
break;
} }
if(initialNasMsg.length > 0){ if(initialNasMsg.length > 0){
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include "FGSServiceRequest.h" #include "FGSServiceRequest.h"
#include "ActivateTestModeComplete.h" #include "ActivateTestModeComplete.h"
#include "CloseUeTestLoopComplete.h" #include "CloseUeTestLoopComplete.h"
#include "OpenUeTestLoopComplete.h"
#include "DeactivateTestModeComplete.h"
#define PLAIN_5GS_MSG 0b0000 #define PLAIN_5GS_MSG 0b0000
#define INTEGRITY_PROTECTED 0b0001 #define INTEGRITY_PROTECTED 0b0001
...@@ -67,6 +69,10 @@ ...@@ -67,6 +69,10 @@
#define ACTIVATE_TEST_MODE_COMPLETE 0b10000101 /* 133 = 0x85 */ #define ACTIVATE_TEST_MODE_COMPLETE 0b10000101 /* 133 = 0x85 */
#define NR_CLOSE_UE_TEST_LOOP 0b10000000 /* 128 = 0x80 */ #define NR_CLOSE_UE_TEST_LOOP 0b10000000 /* 128 = 0x80 */
#define CLOSE_UE_TEST_LOOP_COMPLETE 0b10000001 /* 129 = 0x81 */ #define CLOSE_UE_TEST_LOOP_COMPLETE 0b10000001 /* 129 = 0x81 */
#define OPEN_UE_TEST_LOOP 0b10000010 /* 130 = 0x82 */
#define OPEN_UE_TEST_LOOP_COMPLETE 0b10000011 /* 131 = 0x83 */
#define DEACTIVATE_TEST_MODE 0b10000110 /* 134 = 0x86 */
#define DEACTIVATE_TEST_MODE_COMPLETE 0b10000111 /* 135 = 0x87 */
// message type for 5GS session management // message type for 5GS session management
#define FGS_PDU_SESSION_ESTABLISHMENT_REQ 0b11000001 /* 193= 0xc1 */ #define FGS_PDU_SESSION_ESTABLISHMENT_REQ 0b11000001 /* 193= 0xc1 */
...@@ -124,6 +130,8 @@ typedef union { ...@@ -124,6 +130,8 @@ typedef union {
fgs_uplink_nas_transport_msg uplink_nas_transport; fgs_uplink_nas_transport_msg uplink_nas_transport;
activate_test_mode_complete_msg activate_test_mode_complete; activate_test_mode_complete_msg activate_test_mode_complete;
close_ue_test_loop_complete_msg close_ue_test_loop_complete; close_ue_test_loop_complete_msg close_ue_test_loop_complete;
open_ue_test_loop_complete_msg open_ue_test_loop_complete;
deactivate_test_mode_complete_msg deactivate_test_mode_complete;
fgs_service_request_msg fgs_service_request; fgs_service_request_msg fgs_service_request;
} MM_msg; } MM_msg;
......
...@@ -52,9 +52,8 @@ ...@@ -52,9 +52,8 @@
#include "ss_gNB_context.h" #include "ss_gNB_context.h"
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
//extern uint16_t ss_rnti_g;
static acpCtx_t ctx_drb_g = NULL;
extern SSConfigContext_t SS_context; extern SSConfigContext_t SS_context;
static acpCtx_t ctx_drb_g = NULL;
static unsigned char *buffer = NULL; static unsigned char *buffer = NULL;
static const size_t size = 16 * 1024; static const size_t size = 16 * 1024;
...@@ -67,11 +66,29 @@ enum MsgUserId ...@@ -67,11 +66,29 @@ enum MsgUserId
MSG_NrDrbProcessToSS_userId, MSG_NrDrbProcessToSS_userId,
}; };
#if 0 static void bits_copy_from_array(char *dst, int off, const char* src, int len)
static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind, int cell_index)
{ {
struct DRB_COMMON_IND ind = {}; while (len-- > 0)
uint32_t status = 0; {
int bit = *src++ ? 1 : 0;
dst[off / 8] |= bit << (7 - off % 8);
off++;
}
}
static void bits_copy_to_array(char *dst, int off, const char* src, int len)
{
while (len-- > 0)
{
int bit = src[off / 8] & (1 << (7 - off % 8));
*dst++ = bit ? 0x01 : 0x00;
off++;
}
}
static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind)
{
struct NR_DRB_COMMON_IND ind = {};
LOG_A(GNB_APP, "[SS_DRB] Reported drb sdu_size:%d \t drb_id %d\n", pdu_ind->sdu_size, pdu_ind->drb_id); LOG_A(GNB_APP, "[SS_DRB] Reported drb sdu_size:%d \t drb_id %d\n", pdu_ind->sdu_size, pdu_ind->drb_id);
...@@ -79,17 +96,18 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind, int cell_index) ...@@ -79,17 +96,18 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind, int cell_index)
DevAssert(pdu_ind->sdu_size >= 0); DevAssert(pdu_ind->sdu_size >= 0);
DevAssert(pdu_ind->drb_id >= 0); DevAssert(pdu_ind->drb_id >= 0);
size_t msgSize = size;
memset(&ind, 0, sizeof(ind)); memset(&ind, 0, sizeof(ind));
ind.Common.CellId = SS_context.SSCell_list[cell_index].eutra_cellId; /* ind.Common.CellId = SS_context.nr_cellId; */
//TODO: Work Around till Sys port is implemented for 5G
ind.Common.CellId = nr_Cell1;
//Populated the Routing Info // Populated the Routing Info
ind.Common.RoutingInfo.d = RoutingInfo_Type_RadioBearerId; ind.Common.RoutingInfo.d = NR_RoutingInfo_Type_RadioBearerId;
ind.Common.RoutingInfo.v.RadioBearerId.d = RadioBearerId_Type_Drb; ind.Common.RoutingInfo.v.RadioBearerId.d = NR_RadioBearerId_Type_Drb;
ind.Common.RoutingInfo.v.RadioBearerId.v.Drb = pdu_ind->drb_id; ind.Common.RoutingInfo.v.RadioBearerId.v.Drb = pdu_ind->drb_id;
//Populated the Timing Info // Populated the Timing Info
ind.Common.TimingInfo.d = TimingInfo_Type_SubFrame; ind.Common.TimingInfo.d = TimingInfo_Type_SubFrame;
ind.Common.TimingInfo.v.SubFrame.SFN.d = SystemFrameNumberInfo_Type_Number; ind.Common.TimingInfo.v.SubFrame.SFN.d = SystemFrameNumberInfo_Type_Number;
ind.Common.TimingInfo.v.SubFrame.SFN.v.Number = pdu_ind->frame; ind.Common.TimingInfo.v.SubFrame.SFN.v.Number = pdu_ind->frame;
...@@ -106,49 +124,89 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind, int cell_index) ...@@ -106,49 +124,89 @@ static void ss_send_drb_data(ss_drb_pdu_ind_t *pdu_ind, int cell_index)
ind.Common.Status.d = IndicationStatus_Type_Ok; ind.Common.Status.d = IndicationStatus_Type_Ok;
ind.Common.Status.v.Ok = true; ind.Common.Status.v.Ok = true;
ind.Common.RlcBearerRouting.d = true; ind.Common.RlcBearerRouting.d = RlcBearerRouting_Type_NR;
ind.Common.RlcBearerRouting.v.d = RlcBearerRouting_Type_EUTRA; /* ind.Common.RlcBearerRouting.v.NR = SS_context.nr_cellId; */
ind.Common.RlcBearerRouting.v.v.EUTRA = SS_context.SSCell_list[cell_index].eutra_cellId; //TODO: Work Around till Sys port is implemented for 5G
ind.Common.RlcBearerRouting.v.NR = nr_Cell1;
//Populating the PDU
ind.U_Plane.SubframeData.NoOfTTIs = 1; // Populating the PDU
ind.U_Plane.SubframeData.PduSduList.d = L2DataList_Type_PdcpSdu; ind.U_Plane.SlotData.NoOfTTIs = 1;
ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.d = 1; ind.U_Plane.SlotData.PduSduList.d = NR_L2DataList_Type_RlcPdu;
LOG_A(GNB_APP, "[SS_DRB][DRB_COMMON_IND] PDCP SDU Count: %lu\n", ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.d); ind.U_Plane.SlotData.PduSduList.v.RlcPdu.d = 1;
for(int i = 0; i < ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.d; i++){ ind.U_Plane.SlotData.PduSduList.v.RlcPdu.v = CALLOC(1, (ind.U_Plane.SlotData.PduSduList.v.RlcPdu.d) * (sizeof(struct NR_RLC_PDU_Type)));
ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v = CALLOC(1,(ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.d)*(sizeof(PDCP_SDU_Type))); DevAssert(ind.U_Plane.SlotData.PduSduList.v.RlcPdu.v != NULL);
DevAssert(ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v != NULL); for (int i = 0; i < ind.U_Plane.SlotData.PduSduList.v.RlcPdu.d; i++) {
ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v[i].d = pdu_ind->sdu_size; struct NR_RLC_PDU_Type* rlcPdu = &ind.U_Plane.SlotData.PduSduList.v.RlcPdu.v[i];
ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v[i].v = CALLOC(1,ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v[i].d);
memcpy(ind.U_Plane.SubframeData.PduSduList.v.PdcpSdu.v[i].v, pdu_ind->sdu, pdu_ind->sdu_size); // TODO: suppose, we have UMD NoSN/SN6Bit RLC PDU
rlcPdu->d = NR_RLC_PDU_Type_UMD;
rlcPdu->v.UMD.d = ((pdu_ind->sdu[0] & 0xC0) == 0) ? NR_RLC_UMD_PDU_Type_NoSN : NR_RLC_UMD_PDU_Type_SN6Bit;
if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN)
{
struct NR_RLC_UMD_HeaderNoSN_Type *header = &rlcPdu->v.UMD.v.NoSN.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.NoSN.Data;
int pdu_header_size = 1;
bits_copy_to_array((char *)header->SegmentationInfo, 0, (const char *)pdu_ind->sdu, 2);
bits_copy_to_array((char *)header->Reserved, 2, (const char *)pdu_ind->sdu, 6);
data->d = pdu_ind->sdu_size - pdu_header_size;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_IND: %lu\n", pdu_ind->sdu_size);
data->v = CALLOC(1, data->d);
DevAssert(data->v != NULL);
memcpy(data->v, pdu_ind->sdu + pdu_header_size, data->d);
}
else if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_SN6Bit)
{
struct NR_RLC_UMD_HeaderSN6Bit_Type *header = &rlcPdu->v.UMD.v.SN6Bit.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.SN6Bit.Data;
int pdu_header_size = 1;
bits_copy_to_array((char *)header->SegmentationInfo, 0, (const char *)pdu_ind->sdu, 2);
bits_copy_to_array((char *)header->SequenceNumber, 2, (const char *)pdu_ind->sdu, 6);
if (pdu_ind->sdu[0] & 0x80)
{
pdu_header_size += 2;
header->SegmentOffset.d = true;
bits_copy_to_array((char *)header->SegmentOffset.v, 8, (const char *)pdu_ind->sdu, 16);
}
data->d = pdu_ind->sdu_size - pdu_header_size;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_IND: %lu\n", pdu_ind->sdu_size);
data->v = CALLOC(1, data->d);
DevAssert(data->v != NULL);
memcpy(data->v, pdu_ind->sdu + pdu_header_size, data->d);
}
else
{
LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit are handled in RLC PDU in NR_DRB_COMMON_IND\n");
}
} }
//Encode Message // Encode Message
if (acpDrbProcessToSSEncSrv(ctx_drb_g, buffer, &msgSize, &ind) != 0) size_t msgSize = size;
if (acpNrDrbProcessToSSEncSrv(ctx_drb_g, buffer, &msgSize, &ind) != 0)
{ {
LOG_A(GNB_APP, "[SS_DRB][DRB_COMMON_IND] acpDrbProcessToSSEncSrv Failure\n"); LOG_E(GNB_APP, "[SS_DRB] acpNrDrbProcessToSSEncSrv Failed\n");
return; return;
} }
LOG_A(GNB_APP, "[SS_DRB][DRB_COMMON_IND] Buffer msgSize=%d (!!2) to EUTRACell %d", (int)msgSize,SS_context.SSCell_list[cell_index].eutra_cellId); LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND buffer msgSize=%d to NRCell %d\n", (int)msgSize, SS_context.nr_cellId);
//Send Message // Send Message
status = acpSendMsg(ctx_drb_g, msgSize, buffer); int send_res = acpSendMsg(ctx_drb_g, msgSize, buffer);
if (status != 0) if (send_res != 0)
{ {
LOG_A(GNB_APP, "[SS_DRB][DRB_COMMON_IND] acpSendMsg failed. Error : %d on fd: %d\n", status, acpGetSocketFd(ctx_drb_g)); LOG_E(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND acpSendMsg failed. Error : %d on fd: %d\n", send_res, acpGetSocketFd(ctx_drb_g));
return;
} }
else else
{ {
LOG_A(GNB_APP, "[SS_DRB][DRB_COMMON_IND] acpSendMsg Success \n"); LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND acpSendMsg Success\n");
} }
/* acpNrDrbProcessToSSFree0SrvClt(&ind); */
} }
#endif
static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
{ {
assert(req); assert(req);
MessageDef *message_p = itti_alloc_new_message(TASK_PDCP_ENB, 0, SS_DRB_PDU_REQ); MessageDef *message_p = itti_alloc_new_message(TASK_RLC_ENB, 0, SS_DRB_PDU_REQ);
assert(message_p); assert(message_p);
if (message_p) if (message_p)
{ {
...@@ -163,23 +221,38 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -163,23 +221,38 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
LOG_A(GNB_APP, "[SS_DRB] RLC PDU Received in NR_DRB_COMMON_REQ\n"); LOG_A(GNB_APP, "[SS_DRB] RLC PDU Received in NR_DRB_COMMON_REQ\n");
for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.d; j++) for (int j = 0; j < req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.d; j++)
{ {
struct NR_RLC_PDU_Type* rlcPdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.v[j]; struct NR_RLC_PDU_Type *rlcPdu = &req->U_Plane.SlotDataList.v[i].PduSduList.v.RlcPdu.v[j];
if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN) if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_NoSN)
{ {
struct NR_RLC_UMD_HeaderNoSN_Type *header = &rlcPdu->v.UMD.v.NoSN.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.NoSN.Data;
int pdu_header_size = 1; int pdu_header_size = 1;
NR_RLC_UMD_Data_Type* data = &rlcPdu->v.UMD.v.NoSN.Data; bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 0, (const char *)header->SegmentationInfo, 2);
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 2, (const char *)header->Reserved, 6);
SS_DRB_PDU_REQ(message_p).sdu_size = pdu_header_size + data->d;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ: %lu\n", pdu_header_size + data->d);
memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d);
}
else if (rlcPdu->d == NR_RLC_PDU_Type_UMD && rlcPdu->v.UMD.d == NR_RLC_UMD_PDU_Type_SN6Bit)
{
struct NR_RLC_UMD_HeaderSN6Bit_Type *header = &rlcPdu->v.UMD.v.SN6Bit.Header;
NR_RLC_UMD_Data_Type *data = &rlcPdu->v.UMD.v.SN6Bit.Data;
int pdu_header_size = 1;
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 0, (const char *)header->SegmentationInfo, 2);
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 2, (const char *)header->SequenceNumber, 6);
if (header->SegmentOffset.d)
{
pdu_header_size += 2;
bits_copy_from_array((char *)SS_DRB_PDU_REQ(message_p).sdu, 8, (const char *)header->SegmentOffset.v, 16);
}
SS_DRB_PDU_REQ(message_p).sdu_size = pdu_header_size + data->d; SS_DRB_PDU_REQ(message_p).sdu_size = pdu_header_size + data->d;
LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ: %lu\n", pdu_header_size + data->d); LOG_A(GNB_APP, "[SS_DRB] Length of RLC PDU received in NR_DRB_COMMON_REQ: %lu\n", pdu_header_size + data->d);
/* TODO: expected header in RLC PDU: SegmentationInfo:00 + Reserved:000000000000,
* which should be converted from octets in ACP (each octet has a bit meaning) to bits */
SS_DRB_PDU_REQ(message_p).sdu[0] = 0;
memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d); memcpy(SS_DRB_PDU_REQ(message_p).sdu + pdu_header_size, data->v, data->d);
} }
else else
{ {
LOG_E(GNB_APP, "[SS_DRB] only UM NoSN are handled in RLC PDU in NR_DRB_COMMON_REQ\n"); LOG_E(GNB_APP, "[SS_DRB] only UMD NoSN/SN6Bit are handled in RLC PDU in NR_DRB_COMMON_REQ\n");
} }
} }
} }
...@@ -188,10 +261,10 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req) ...@@ -188,10 +261,10 @@ static void ss_task_handle_drb_pdu_req(struct NR_DRB_COMMON_REQ *req)
} }
SS_DRB_PDU_REQ(message_p).rnti = SS_context.ss_rnti_g; SS_DRB_PDU_REQ(message_p).rnti = SS_context.ss_rnti_g;
int send_res = itti_send_msg_to_task(TASK_RRC_GNB, instance_g, message_p); int send_res = itti_send_msg_to_task(TASK_RLC_ENB, instance_g, message_p);
if (send_res < 0) if (send_res < 0)
{ {
LOG_A(GNB_APP, "[SS_DRB] Error in itti_send_msg_to_task\n"); LOG_E(GNB_APP, "[SS_DRB] Error in itti_send_msg_to_task\n");
} }
LOG_A(GNB_APP, "[SS_DRB] Send res: %d\n", send_res); LOG_A(GNB_APP, "[SS_DRB] Send res: %d\n", send_res);
...@@ -230,7 +303,7 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx) ...@@ -230,7 +303,7 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx)
} }
else else
{ {
LOG_A(GNB_APP, "[SS_DRB] Invalid userId: %d \n", userId); LOG_E(GNB_APP, "[SS_DRB] Invalid userId: %d\n", userId);
break; break;
} }
} }
...@@ -238,34 +311,35 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx) ...@@ -238,34 +311,35 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx)
if (userId == 0) if (userId == 0)
{ {
// No message (timeout on socket) // No message (timeout on socket)
//break; break;
} }
else if (MSG_NrDrbProcessFromSS_userId == userId) else if (MSG_NrDrbProcessFromSS_userId == userId)
{ {
struct NR_DRB_COMMON_REQ *req = NULL; struct NR_DRB_COMMON_REQ *req = NULL;
LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ Received \n"); LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ Received\n");
if (acpNrDrbProcessFromSSDecSrv(ctx, buffer, msgSize, &req) != 0) if (acpNrDrbProcessFromSSDecSrv(ctx, buffer, msgSize, &req) != 0)
{ {
LOG_A(GNB_APP, "[SS_DRB][NR_DRB_COMMON_REQ] acpNrDrbProcessFromSSDecSrv Failed\n"); LOG_E(GNB_APP, "[SS_DRB] acpNrDrbProcessFromSSDecSrv Failed\n");
break; break;
} }
if (SS_context.State >= SS_STATE_CELL_ACTIVE) if (SS_context.State >= SS_STATE_CELL_ACTIVE)
{ {
LOG_A(GNB_APP, "[SS_DRB][NR_DRB_COMMON_REQ] NR_DRB_COMMON_REQ Received in CELL_ACTIVE\n"); LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ received in CELL_ACTIVE\n");
ss_task_handle_drb_pdu_req(req); ss_task_handle_drb_pdu_req(req);
} }
else else
{ {
LOG_W(GNB_APP, "[SS_DRB][NR_DRB_COMMON_REQ] received in SS state %d \n", SS_context.State); LOG_W(GNB_APP, "[SS_DRB] NR_DRB_COMMON_REQ received in SS state %d \n", SS_context.State);
} }
acpNrDrbProcessFromSSFreeSrv(req); acpNrDrbProcessFromSSFreeSrv(req);
return;
break;
} }
else if (MSG_NrDrbProcessToSS_userId == userId) else if (MSG_NrDrbProcessToSS_userId == userId)
{ {
LOG_A(GNB_APP, "[SS_DRB] DRB_COMMON_IND Received; ignoring \n"); LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND Received; ignoring\n");
break; break;
} }
} }
...@@ -273,11 +347,10 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx) ...@@ -273,11 +347,10 @@ static void ss_gNB_read_from_drb_socket(acpCtx_t ctx)
void *ss_gNB_drb_process_itti_msg(void *notUsed) void *ss_gNB_drb_process_itti_msg(void *notUsed)
{ {
#if 0
MessageDef *received_msg = NULL; MessageDef *received_msg = NULL;
int result = 0; int result = 0;
itti_receive_msg(TASK_SS_DRB, &received_msg); itti_poll_msg(TASK_SS_DRB, &received_msg);
/* Check if there is a packet to handle */ /* Check if there is a packet to handle */
if (received_msg != NULL) if (received_msg != NULL)
...@@ -286,48 +359,43 @@ void *ss_gNB_drb_process_itti_msg(void *notUsed) ...@@ -286,48 +359,43 @@ void *ss_gNB_drb_process_itti_msg(void *notUsed)
{ {
case SS_DRB_PDU_IND: case SS_DRB_PDU_IND:
{ {
int cell_index;
if(received_msg->ittiMsg.ss_drb_pdu_ind.physCellId){
cell_index = get_cell_index_pci(received_msg->ittiMsg.ss_drb_pdu_ind.physCellId, SS_context.SSCell_list);
LOG_A(ENB_SS,"[SS_DRB] cell_index in SS_DRB_PDU_IND: %d PhysicalCellId: %d \n",cell_index,SS_context.SSCell_list[cell_index].PhysicalCellId);
}
task_id_t origin_task = ITTI_MSG_ORIGIN_ID(received_msg); task_id_t origin_task = ITTI_MSG_ORIGIN_ID(received_msg);
if (origin_task == TASK_SS_PORTMAN) if (origin_task == TASK_SS_PORTMAN)
{ {
LOG_D(GNB_APP, "[SS_DRB] DUMMY WAKEUP recevied from PORTMAN state %d \n", SS_context.SSCell_list[cell_index].State); LOG_D(GNB_APP, "[SS_DRB] DUMMY WAKEUP recevied from PORTMAN state %d\n", SS_context.State);
} }
else else
{ {
LOG_A(GNB_APP, "[SS_DRB] Received SS_DRB_PDU_IND from RRC PDCP\n"); LOG_A(GNB_APP, "[SS_DRB] Received SS_DRB_PDU_IND from PDCP\n");
if (SS_context.SSCell_list[cell_index].State >= SS_STATE_CELL_ACTIVE) if (SS_context.State >= SS_STATE_CELL_ACTIVE)
{ {
LOG_A(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND received in CELL_ACTIVE\n");
instance_g = ITTI_MSG_DESTINATION_INSTANCE(received_msg); instance_g = ITTI_MSG_DESTINATION_INSTANCE(received_msg);
ss_send_drb_data(&received_msg->ittiMsg.ss_drb_pdu_ind,cell_index); ss_send_drb_data(&received_msg->ittiMsg.ss_drb_pdu_ind);
} }
else else
{ {
LOG_A(GNB_APP, "ERROR [SS_DRB][SS_DRB_PDU_IND] received in SS state %d \n", SS_context.SSCell_list[cell_index].State); LOG_W(GNB_APP, "[SS_DRB] NR_DRB_COMMON_IND received in SS state %d\n", SS_context.State);
} }
} }
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}; };
break; break;
case TERMINATE_MESSAGE: case TERMINATE_MESSAGE:
LOG_A(GNB_APP, "[SS_DRB] Received TERMINATE_MESSAGE \n"); LOG_A(GNB_APP, "[SS_DRB] Received TERMINATE_MESSAGE\n");
itti_exit_task(); itti_exit_task();
break; break;
default: default:
LOG_A(GNB_APP, "[SS_DRB] Received unhandled message %d:%s\n", LOG_W(GNB_APP, "[SS_DRB] Received unhandled message %d:%s\n",
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break; break;
} }
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} }
#endif
ss_gNB_read_from_drb_socket(ctx_drb_g); ss_gNB_read_from_drb_socket(ctx_drb_g);
......
...@@ -490,7 +490,7 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed) ...@@ -490,7 +490,7 @@ void *ss_gNB_sys_process_itti_msg(void *notUsed)
itti_receive_msg(TASK_SYS_GNB, &received_msg); itti_receive_msg(TASK_SYS_GNB, &received_msg);
LOG_A(GNB_APP, "Entry in fxn:%s \n", __FUNCTION__); LOG_D(GNB_APP, "Entry in fxn:%s \n", __FUNCTION__);
/* Check if there is a packet to handle */ /* Check if there is a packet to handle */
if (received_msg != NULL) if (received_msg != NULL)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment