diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 050d50f9f5..de54c9a550 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1744,9 +1744,15 @@ set(NR_RLC_SRC ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_sdu.c ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_ue_manager.c ) + +set(NR_PDCP_SRC + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ) set(L2_SRC - ${OPENAIR2_DIR}/LAYER2/openair2_proc.c ${PDCP_DIR}/pdcp.c ${PDCP_DIR}/pdcp_fifo.c ${PDCP_DIR}/pdcp_sequence_manager.c @@ -1754,6 +1760,7 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c @@ -1765,6 +1772,20 @@ set(L2_SRC ${RRC_DIR}/L2_interface_common.c ${RRC_DIR}/L2_interface_ue.c ) + +set(L2_RRC_SRC + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c + # ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_eNB.c + ${RRC_DIR}/rrc_eNB_endc.c + ${RRC_DIR}/rrc_eNB_S1AP.c + ${RRC_DIR}/rrc_eNB_M2AP.c + ${RRC_DIR}/rrc_eNB_UE_context.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c + ) set(L2_LTE_SRC ${RLC_V2} @@ -1772,6 +1793,7 @@ set(L2_LTE_SRC set(L2_NR_SRC ${NR_RLC_SRC} + ${NR_PDCP_SRC} ${NR_RRC_DIR}/rrc_gNB.c ${NR_RRC_DIR}/nr_rrc_common.c ${NR_RRC_DIR}/L2_nr_interface.c @@ -1796,19 +1818,16 @@ set(L2_SRC_UE ${RRC_DIR}/L2_interface_ue.c ) -set(LTE_NR_L2_SRC_UE - ${PDCP_DIR}/pdcp.c - ${PDCP_DIR}/pdcp_fifo.c - ${PDCP_DIR}/pdcp_sequence_manager.c - ${PDCP_DIR}/pdcp_primitives.c - ${PDCP_DIR}/pdcp_util.c - ${PDCP_DIR}/pdcp_security.c - ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V2} - ) - +set(L2_RRC_SRC_UE + ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c + ) + set(NR_L2_SRC_UE ${NR_RLC_SRC} + ${NR_PDCP_SRC} ${NR_UE_RRC_DIR}/L2_interface_ue.c ${NR_UE_RRC_DIR}/main_ue.c ${NR_UE_RRC_DIR}/rrc_UE.c @@ -1918,6 +1937,14 @@ add_library(L2_NR ${MAC_NR_SRC} ${GNB_APP_SRC} ) + +add_library(L2_LTE_NR + ${L2_RRC_SRC} + ${MAC_SRC} + ${ENB_APP_SRC} + ${MCE_APP_SRC} +) + add_dependencies(L2_NR rrc_flag nr_rrc_flag s1ap_flag x2_flag) add_library(L2_UE @@ -1925,6 +1952,11 @@ add_library(L2_UE ${MAC_SRC_UE} ) +add_library(L2_UE_LTE_NR + ${L2_RRC_SRC_UE} + ${MAC_SRC_UE} +) + if (NOT ${NOS1}) target_compile_definitions(L2_UE PUBLIC -DPDCP_USE_NETLINK) endif() @@ -2745,7 +2777,7 @@ target_link_libraries (nr-softmodem -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS NR_GTPV1U SECU_CN SECU_OSA ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB - S1AP_LIB S1AP_ENB L2 L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} -Wl,--end-group z dl) @@ -2787,7 +2819,7 @@ add_executable(nr-uesoftmodem target_link_libraries (nr-uesoftmodem -Wl,--start-group RRC_LIB NR_RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB - PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB + PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} -Wl,--end-group z dl) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index cdcd014caa..c06a2570c5 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -364,8 +364,6 @@ static void UE_synch(void *arg) { } void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { - - fapi_nr_config_request_t *cfg = &UE->nrUE_config; int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_tti_tx); uint8_t gNB_id = 0; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fa816b506c..62761098fc 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -585,7 +585,7 @@ void init_pdcp(void) { LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration();*/ + nr_DRB_preconfiguration();*/ pdcp_module_init(pdcp_initmask); pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index a31b4acb1e..89711050e2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -711,8 +711,8 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, } #ifdef DEBUG_ULSCH_DECODING - LOG_I(PHY, "Decoder output (payload): \n"); - for (i = 0; i < harq_process->TBS ; i++) { + LOG_I(PHY, "Decoder output (payload, TBS: %d): \n", harq_process->TBS); + for (i = 0; i < harq_process->TBS; i++) { //harq_process_ul_ue->a[i] = (unsigned char) rand(); //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); printf("%02x",harq_process->b[i]); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index dedab0ad2b..f63eb83ac1 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -123,7 +123,7 @@ int generate_dlsch_header(unsigned char *mac_header, unsigned char *ue_cont_res_id, unsigned char short_padding, unsigned short post_padding){return 0;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 2db5bc905c..ec79274b8f 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -76,7 +76,7 @@ boolean_t pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, const sdu_size_t sdu_buffer_sizeP, mem_block_t *const sdu_buffer_pP) {return(false);} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} void pdcp_layer_init(void) {} int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 0ecb8f2c36..ad65d0a4d7 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -97,7 +97,7 @@ boolean_t pdcp_data_ind( ) { return(false);} void pdcp_run (const protocol_ctxt_t *const ctxt_pP) { return;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} int rrc_init_nr_global_param(void){return(0);} diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index af9822a5df..bae8e0d3c0 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -39,6 +39,7 @@ #include "PHY/defs_UE.h" #include "openair2/LAYER2/RLC/rlc.h" #include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "executables/softmodem-common.h" static NR_UE_MAC_INST_t *nr_ue_mac_inst; @@ -59,7 +60,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration(); + nr_DRB_preconfiguration(); } } else LOG_I(MAC,"Running without RRC instance\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 9cc7b26803..dd0f30cf4b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -261,6 +261,7 @@ int configure_fapi_dl_pdu(int Mod_idP, uint16_t *rbStart) { + LOG_I(MAC, "Inside configure_fapi_dl_pdu() \n"); gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = nr_mac->common_channels; @@ -596,7 +597,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest frame %d slot %d\n",frameP,slotP); int post_padding = 0, ta_len = 0, header_length_total = 0, sdu_length_total = 0, num_sdus = 0; - int lcid, offset, i, header_length_last, TBS_bytes; + int lcid, offset, i, header_length_last, TBS_bytes = 0; int UE_id = 0, CC_id = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; @@ -630,70 +631,62 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, if (TBS_bytes == 0) return; - - //The --NOS1 use case currently schedules DLSCH transmissions only when there is IP traffic arriving - //through the LTE stack - if (IS_SOFTMODEM_NOS1){ - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { + lcid = DL_SCH_LCID_DTCH; - // TODO: check if the lcid is active + //for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n", - module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3); + // TODO: check if the lcid is active - if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - slotP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - 0, - 0); + LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n", + module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3); - if (rlc_status.bytes_in_buffer > 0) { + //if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + slotP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0); - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n", - module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - lcid, header_length_total, TBS_bytes); + if (rlc_status.bytes_in_buffer > 0) { - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - (char *)&mac_sdus[sdu_length_total], - 0, - 0); + LOG_I(MAC, "configure fapi due to data availability \n"); - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid); + LOG_I(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n", + module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, + lcid, header_length_total, TBS_bytes); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, + (char *)&mac_sdus[sdu_length_total], + 0, + 0); - num_sdus++; + LOG_W(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid); - //ue_sched_ctl->uplane_inactivity_timer = 0; - } - } else { // no TBS_bytes left - break; - } - } + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + + num_sdus++; + + //ue_sched_ctl->uplane_inactivity_timer = 0; + } - } //if (IS_SOFTMODEM_NOS1) else { - //When the --NOS1 option is not enabled, DLSCH transmissions with random data - //occur every time that the current function is called (dlsch phytest mode) - LOG_D(MAC,"Configuring DL_TX in %d.%d\n", frameP, slotP); // fill dlsch_buffer with random data @@ -718,7 +711,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, } #endif - } // else IS_SOFTMODEM_NOS1 + } // there is at least one SDU or TA command // if (num_sdus > 0 ){ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 7fe0d63efa..0ab005f9ab 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -36,6 +36,7 @@ void nr_process_mac_pdu( module_id_t module_idP, + rnti_t rnti, uint8_t CC_id, frame_t frameP, uint8_t *pduP, @@ -219,25 +220,33 @@ void nr_process_mac_pdu( LOG_T(MAC, "\n"); #endif - - if (IS_SOFTMODEM_NOS1){ - if (rx_lcid < NB_RB_MAX && rx_lcid >= UL_SCH_LCID_DTCH) { - - mac_rlc_data_ind(module_idP, - 0x1234, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, module_idP); - } + if(IS_SOFTMODEM_NOS1){ + mac_rlc_data_ind(module_idP, + 0x1234, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); } + else{ + mac_rlc_data_ind(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } + break; @@ -306,7 +315,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, UE_scheduling_control->ta_update = timing_advance; LOG_I(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); LOG_D(MAC, "Received PDU at MAC gNB \n"); - nr_process_mac_pdu(gnb_mod_idP, CC_idP, frameP, sduP, sdu_lenP); + nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP); } } else { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 7dd956927b..d7e7971efe 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -301,6 +301,7 @@ void schedule_fapi_ul_pdu(int Mod_idP, void nr_process_mac_pdu( module_id_t module_idP, + rnti_t rnti, uint8_t CC_id, frame_t frameP, uint8_t *pduP, diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 873deddbe7..bd0be8c409 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -35,6 +35,7 @@ #include "assertions.h" #include "LAYER2/PDCP_v10.1.0/pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "RRC/NR/nr_rrc_defs.h" #include "common/utils/LOG/log.h" //#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" @@ -89,7 +90,7 @@ void mac_top_init_gNB(void) pdcp_layer_init(); if(IS_SOFTMODEM_NOS1) - nr_ip_over_LTE_DRB_preconfiguration(); + nr_DRB_preconfiguration(); rrc_init_nr_global_param(); diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 3667af2698..33f268f07f 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -2353,101 +2353,6 @@ void pdcp_module_cleanup (void) { } -void nr_ip_over_LTE_DRB_preconfiguration(void){ - - // Addition for the use-case of 4G stack on top of 5G-NR. - // We need to configure pdcp and rlc instances without having an actual - // UE RRC Connection. In order to be able to test the NR PHY with some injected traffic - // on top of the LTE stack. - protocol_ctxt_t ctxt; - LTE_DRB_ToAddModList_t* DRB_configList=NULL; - DRB_configList = CALLOC(1, sizeof(LTE_DRB_ToAddModList_t)); - struct LTE_LogicalChannelConfig *DRB_lchan_config = NULL; - struct LTE_RLC_Config *DRB_rlc_config = NULL; - struct LTE_PDCP_Config *DRB_pdcp_config = NULL; - struct LTE_PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; - - struct LTE_DRB_ToAddMod *DRB_config = NULL; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL; - long *logicalchannelgroup_drb; - - - //Static preconfiguration of DRB - DRB_config = CALLOC(1, sizeof(*DRB_config)); - - DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); - // allowed value 5..15, value : x+4 - *(DRB_config->eps_BearerIdentity) = 1; //ue_context_pP->ue_context.e_rab[i].param.e_rab_id;//+ 4; // especial case generation - // DRB_config->drb_Identity = 1 + drb_identity_index + e_rab_done;// + i ;// (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id; - // 1 + drb_identiy_index; - DRB_config->drb_Identity = 1; - DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); - *(DRB_config->logicalChannelIdentity) = DRB_config->drb_Identity + 3; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2 - - DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); - DRB_config->rlc_Config = DRB_rlc_config; - - DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); - DRB_config->pdcp_Config = DRB_pdcp_config; - DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long)); - *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity; - DRB_pdcp_config->rlc_AM = NULL; - DRB_pdcp_config->rlc_UM = NULL; - - DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; - DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; - // PDCP - PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); - DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; - PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; - - DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; - - DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); - DRB_config->logicalChannelConfig = DRB_lchan_config; - DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); - DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - - DRB_ul_SpecificParameters->priority= 4; - - DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; - //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - - logicalchannelgroup_drb = CALLOC(1, sizeof(long)); - *logicalchannelgroup_drb = 1;//(i+1) % 3; - DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; - - ASN_SEQUENCE_ADD(&DRB_configList->list,DRB_config); - - if (ENB_NAS_USE_TUN){ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); - } - else{ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); - } - - rrc_pdcp_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t *) NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t *) NULL, - 0xff, NULL, NULL, NULL - , (LTE_PMCH_InfoList_r9_t *) NULL, - &DRB_config->drb_Identity); - - rrc_rlc_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t*)NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t*)NULL - //#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - ,(LTE_PMCH_InfoList_r9_t *)NULL - , 0, 0 - //#endif - ); -} //----------------------------------------------------------------------------- void pdcp_layer_init(void) //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c new file mode 100644 index 0000000000..e25201c22c --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -0,0 +1,74 @@ +/* + * 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 + */ + +#include "nr_pdcp_entity.h" + +#include "nr_pdcp_entity_drb_am.h" + +#include "LOG/log.h" + +nr_pdcp_entity_t *new_nr_pdcp_entity_srb( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data) +{ + abort(); +} + +nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data) +{ + nr_pdcp_entity_drb_am_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu; + ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu; + ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key; + + ret->common.delete = nr_pdcp_entity_drb_am_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->common.deliver_pdu = deliver_pdu; + ret->common.deliver_pdu_data = deliver_pdu_data; + + ret->rb_id = rb_id; + + ret->common.maximum_nr_pdcp_sn = 4095; + + return (nr_pdcp_entity_t *)ret; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h new file mode 100644 index 0000000000..45555ad6af --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -0,0 +1,65 @@ +/* + * 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 + */ + +#ifndef _NR_PDCP_ENTITY_H_ +#define _NR_PDCP_ENTITY_H_ + +typedef struct nr_pdcp_entity_t { + /* functions provided by the PDCP module */ + void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); + void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id); + void (*delete)(struct nr_pdcp_entity_t *entity); + void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key); + + /* callbacks provided to the PDCP module */ + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size); + void *deliver_sdu_data; + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id); + void *deliver_pdu_data; + int tx_hfn; + int next_nr_pdcp_tx_sn; + int maximum_nr_pdcp_sn; +} nr_pdcp_entity_t; + +nr_pdcp_entity_t *new_nr_pdcp_entity_srb( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data); + +nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data); + +void nr_DRB_preconfiguration(void); + +#endif /* _NR_PDCP_ENTITY_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c new file mode 100644 index 0000000000..85f638d66d --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c @@ -0,0 +1,71 @@ +/* + * 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 + */ + +#include "nr_pdcp_entity_drb_am.h" + +#include +#include +#include + +void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + + if (size < 3) abort(); + if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (nr_pdcp_entity_t *)entity, buffer+3, size-3); +} + +void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + int sn; + char buf[size+2]; + + sn = entity->common.next_nr_pdcp_tx_sn; + + entity->common.next_nr_pdcp_tx_sn++; + if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) { + entity->common.next_nr_pdcp_tx_sn = 0; + entity->common.tx_hfn++; + } + + buf[0] = 0x80 | ((sn >> 16) & 0x3); + buf[1] = (sn >> 8) & 0xff; + buf[2] = sn & 0xff; + memcpy(buf+3, buffer, size); + + entity->common.deliver_pdu(entity->common.deliver_pdu_data, + (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id); +} + +void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key) +{ + /* nothing to do */ +} + +void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + free(entity); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h new file mode 100644 index 0000000000..faa8226e93 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h @@ -0,0 +1,38 @@ +/* + * 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 + */ + +#ifndef _NR_PDCP_ENTITY_DRB_AM_H_ +#define _NR_PDCP_ENTITY_DRB_AM_H_ + +#include "nr_pdcp_entity.h" + +typedef struct { + nr_pdcp_entity_t common; + int rb_id; +} nr_pdcp_entity_drb_am_t; + +void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); +void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id); +void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key); +void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity); + +#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c new file mode 100644 index 0000000000..ba59c85fb6 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -0,0 +1,946 @@ +/* + * 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 + */ + +#include "nr_pdcp_ue_manager.h" +#include "NR_RadioBearerConfig.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_CellGroupConfig.h" +#include "openair2/RRC/NR/nr_rrc_proto.h" + +/* from OAI */ +#include "pdcp.h" + +#define TODO do { \ + printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \ + exit(1); \ + } while (0) + +static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; + +/* necessary globals for OAI, not used internally */ +hash_table_t *pdcp_coll_p; +static uint64_t pdcp_optmask; + +/****************************************************************************/ +/* rlc_data_req queue - begin */ +/****************************************************************************/ + +#include + +/* NR PDCP and RLC both use "big locks". In some cases a thread may do + * lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu'). + * Another thread may first do lock(pdcp) and then lock(rlc) (typically + * the GTP module calls 'pdcp_data_req' that, in a previous implementation + * was indirectly calling 'rlc_data_req' which does lock(rlc)). + * To avoid the resulting deadlock it is enough to ensure that a call + * to lock(pdcp) will never be followed by a call to lock(rlc). So, + * here we chose to have a separate thread that deals with rlc_data_req, + * out of the PDCP lock. Other solutions may be possible. + * So instead of calling 'rlc_data_req' directly we have a queue and a + * separate thread emptying it. + */ + +typedef struct { + protocol_ctxt_t ctxt_pP; + srb_flag_t srb_flagP; + MBMS_flag_t MBMS_flagP; + rb_id_t rb_idP; + mui_t muiP; + confirm_t confirmP; + sdu_size_t sdu_sizeP; + mem_block_t *sdu_pP; +} rlc_data_req_queue_item; + +#define RLC_DATA_REQ_QUEUE_SIZE 10000 + +typedef struct { + rlc_data_req_queue_item q[RLC_DATA_REQ_QUEUE_SIZE]; + volatile int start; + volatile int length; + pthread_mutex_t m; + pthread_cond_t c; +} rlc_data_req_queue; + +static rlc_data_req_queue q; + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +static void *rlc_data_req_thread(void *_) +{ + int i; + + while (1) { + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == 0) + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + i = q.start; + if (pthread_mutex_unlock(&q.m) != 0) abort(); + + rlc_data_req(&q.q[i].ctxt_pP, + q.q[i].srb_flagP, + q.q[i].MBMS_flagP, + q.q[i].rb_idP, + q.q[i].muiP, + q.q[i].confirmP, + q.q[i].sdu_sizeP, + q.q[i].sdu_pP, + NULL, + NULL); + + if (pthread_mutex_lock(&q.m) != 0) abort(); + + q.length--; + q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); + } +} + +static void init_nr_rlc_data_req_queue(void) +{ + pthread_t t; + + pthread_mutex_init(&q.m, NULL); + pthread_cond_init(&q.c, NULL); + + if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP, + void *_unused1, void *_unused2) +{ + int i; + int logged = 0; + + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == RLC_DATA_REQ_QUEUE_SIZE) { + if (!logged) { + logged = 1; + LOG_W(PDCP, "%s: rlc_data_req queue is full\n", __FUNCTION__); + } + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + } + + i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE; + q.length++; + + q.q[i].ctxt_pP = *ctxt_pP; + q.q[i].srb_flagP = srb_flagP; + q.q[i].MBMS_flagP = MBMS_flagP; + q.q[i].rb_idP = rb_idP; + q.q[i].muiP = muiP; + q.q[i].confirmP = confirmP; + q.q[i].sdu_sizeP = sdu_sizeP; + q.q[i].sdu_pP = sdu_pP; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); +} + +/****************************************************************************/ +/* rlc_data_req queue - end */ +/****************************************************************************/ + +/****************************************************************************/ +/* hacks to be cleaned up at some point - begin */ +/****************************************************************************/ + +#include "LAYER2/MAC/mac_extern.h" + +static void reblock_tun_socket(void) +{ + extern int nas_sock_fd[]; + int f; + + f = fcntl(nas_sock_fd[0], F_GETFL, 0); + f &= ~(O_NONBLOCK); + if (fcntl(nas_sock_fd[0], F_SETFL, f) == -1) { + LOG_E(PDCP, "reblock_tun_socket failed\n"); + exit(1); + } +} + +static void *enb_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + +printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void *ue_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + +printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 0; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void start_pdcp_tun_enb(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, enb_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void start_pdcp_tun_ue(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/****************************************************************************/ +/* hacks to be cleaned up at some point - end */ +/****************************************************************************/ + +int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) +{ + return 0; +} + +void pdcp_layer_init(void) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + if (pthread_mutex_unlock(&m) != 0) abort(); + return; + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + + nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); + init_nr_rlc_data_req_queue(); +} + +#include "nfapi/oai_integration/vendor_ext.h" +#include "targets/RT/USER/lte-softmodem.h" +#include "openair2/RRC/NAS/nas_config.h" + +uint64_t pdcp_module_init(uint64_t _pdcp_optmask) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + abort(); + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + +#if 0 + pdcp_optmask = _pdcp_optmask; + return pdcp_optmask; +#endif + /* temporary enforce netlink when UE_NAS_USE_TUN is set, + this is while switching from noS1 as build option + to noS1 as config option */ + if ( _pdcp_optmask & UE_NAS_USE_TUN_BIT) { + pdcp_optmask = pdcp_optmask | PDCP_USE_NETLINK_BIT ; + } + + pdcp_optmask = pdcp_optmask | _pdcp_optmask ; + LOG_I(PDCP, "pdcp init,%s %s\n", + ((LINK_ENB_PDCP_TO_GTPV1U)?"usegtp":""), + ((PDCP_USE_NETLINK)?"usenetlink":"")); + + if (PDCP_USE_NETLINK) { + nas_getparams(); + + if(UE_NAS_USE_TUN) { + int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1; + netlink_init_tun("ue",num_if); + //Add --nr-ip-over-lte option check for next line + if (IS_SOFTMODEM_NOS1) + nas_config(1, 1, 2, "ue"); + LOG_I(PDCP, "UE pdcp will use tun interface\n"); + start_pdcp_tun_ue(); + } else if(ENB_NAS_USE_TUN) { + netlink_init_tun("enb",1); + nas_config(1, 1, 1, "enb"); + LOG_I(PDCP, "ENB pdcp will use tun interface\n"); + start_pdcp_tun_enb(); + } else { + LOG_I(PDCP, "pdcp will use kernel modules\n"); + abort(); + netlink_init(); + } + } + return pdcp_optmask ; +} + +static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size) +{ + extern int nas_sock_fd[]; + int len; + nr_pdcp_ue_t *ue = _ue; + MessageDef *message_p; + uint8_t *gtpu_buffer_p; + int rb_id; + int i; + + if(IS_SOFTMODEM_NOS1){ + len = write(nas_sock_fd[0], buf, size); + if (len != size) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + } + else{ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + + rb_found: + gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U, + size + GTPU_HEADER_OVERHEAD_MAX); + AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY"); + memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf, size); + message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ); + AssertFatal(message_p != NULL, "OUT OF MEMORY"); + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length = size; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ue->rnti; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4; + printf("!!!!!!! deliver_sdu_drb (drb %d) sending message to gtp size %d: ", rb_id, size); + //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]); + printf("\n"); + itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + + } +} + +static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id) +{ + nr_pdcp_ue_t *ue = _ue; + int rb_id; + protocol_ctxt_t ctxt; + int i; + mem_block_t *memblock; + + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = ue->rnti; + + memblock = get_free_mem_block(size, __FUNCTION__); + memcpy(memblock->data, buf, size); + +printf("!!!!!!! deliver_pdu_drb (srb %d) calling rlc_data_req size %d: ", rb_id, size); +//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); +printf("\n"); + enqueue_rlc_data_req(&ctxt, 0, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL); +} + +boolean_t pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer) +{ + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (ctxt_pP->enb_flag) + T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti), + T_INT(rb_id), T_INT(sdu_buffer_size)); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (srb_flagP == 1) { + if (rb_id < 1 || rb_id > 2) + rb = NULL; + else + rb = ue->srb[rb_id - 1]; + } else { + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + } + + if (rb != NULL) { + rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size); + } else { + LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %ld, srb_flag %d)\n", + __FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP); + exit(1); + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + free_mem_block(sdu_buffer, __FUNCTION__); + + return 1; +} + +void pdcp_run(const protocol_ctxt_t *const ctxt_pP) +{ + MessageDef *msg_p; + int result; + protocol_ctxt_t ctxt; + + while (1) { + itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p); + if (msg_p == NULL) + break; + switch (ITTI_MSG_ID(msg_p)) { + case RRC_DCCH_DATA_REQ: + PROTOCOL_CTXT_SET_BY_MODULE_ID( + &ctxt, + RRC_DCCH_DATA_REQ(msg_p).module_id, + RRC_DCCH_DATA_REQ(msg_p).enb_flag, + RRC_DCCH_DATA_REQ(msg_p).rnti, + RRC_DCCH_DATA_REQ(msg_p).frame, + 0, + RRC_DCCH_DATA_REQ(msg_p).eNB_index); + result = pdcp_data_req(&ctxt, + SRB_FLAG_YES, + RRC_DCCH_DATA_REQ(msg_p).rb_id, + RRC_DCCH_DATA_REQ(msg_p).muip, + RRC_DCCH_DATA_REQ(msg_p).confirmp, + RRC_DCCH_DATA_REQ(msg_p).sdu_size, + RRC_DCCH_DATA_REQ(msg_p).sdu_p, + RRC_DCCH_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), RRC_DCCH_DATA_REQ(msg_p).sdu_p); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + break; + default: + LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p)); + break; + } + } +} + +static void add_srb(int rnti, struct NR_SRB_ToAddMod *s) +{ + TODO; +} + +static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) +{ + nr_pdcp_entity_t *pdcp_drb; + nr_pdcp_ue_t *ue; + + int drb_id = s->drb_Identity; + +printf("\n\n################# rnti %d add drb %d\n\n\n", rnti, drb_id); + + if (drb_id != 1) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + if (ue->drb[drb_id-1] != NULL) { + LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } else { + pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue); + nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); + + LOG_D(PDCP, "%s:%d:%s: added drb %d to ue %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Config) +{ + switch (rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(rnti, s); + break; + case NR_RLC_Config_PR_um_Bi_Directional: + //add_drb_um(rnti, s); + /* hack */ + add_drb_am(rnti, s); + break; + default: + LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 +#endif + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) + //struct NR_RLC_Config *rlc_Config) +{ + int rnti = ctxt_pP->rnti; + int i; + + if (//ctxt_pP->enb_flag != 1 || + ctxt_pP->module_id != 0 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + //ctxt_pP->configured != 2 || + //srb2add_list == NULL || + //drb2add_list != NULL || + drb2release_list != NULL || + security_modeP != 255 || + //kRRCenc != NULL || + //kRRCint != NULL || + //kUPenc != NULL || + pmch_InfoList_r9 != NULL /*|| + defaultDRB != NULL */) { + TODO; + } + + if (srb2add_list != NULL) { + for (i = 0; i < srb2add_list->list.count; i++) { + add_srb(rnti, srb2add_list->list.array[i]); + } + } + + if (drb2add_list != NULL) { + for (i = 0; i < drb2add_list->list.count; i++) { + LOG_I(PDCP, "Before calling add_drb \n"); + add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config); + } + } + + /* update security */ + if (kRRCint != NULL) { + /* todo */ + } + + free(kRRCenc); + free(kRRCint); + free(kUPenc); + + return 0; +} + +/* Dummy function due to dependency from LTE libraries */ +boolean_t rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list, + LTE_DRB_ToAddModList_t *const drb2add_list, + LTE_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 +#endif + ,rb_id_t *const defaultDRB) +{ + return 0; +} + +void nr_DRB_preconfiguration(void) +{ + + NR_RadioBearerConfig_t *rbconfig = NULL; + struct NR_CellGroupConfig__rlc_BearerToAddModList *Rlc_Bearer_ToAdd_list = NULL; + protocol_ctxt_t ctxt; + //fill_default_rbconfig(rb_config, 5, 1); + rbconfig = calloc(1, sizeof(*rbconfig)); + + rbconfig->srb_ToAddModList = NULL; + rbconfig->srb3_ToRelease = NULL; + rbconfig->drb_ToAddModList = calloc(1,sizeof(*rbconfig->drb_ToAddModList)); + NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); + drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); + drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; + drb_ToAddMod->drb_Identity = 1; + drb_ToAddMod->reestablishPDCP = NULL; + drb_ToAddMod->recoverPDCP = NULL; + drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); + drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); + drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; + drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + drb_ToAddMod->pdcp_Config->drb->integrityProtection=NULL; + drb_ToAddMod->pdcp_Config->drb->statusReportRequired=NULL; + drb_ToAddMod->pdcp_Config->drb->outOfOrderDelivery=NULL; + drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; + + drb_ToAddMod->pdcp_Config->t_Reordering = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->t_Reordering)); + *drb_ToAddMod->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + drb_ToAddMod->pdcp_Config->ext1 = NULL; + + ASN_SEQUENCE_ADD(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); + + rbconfig->drb_ToReleaseList = NULL; + + rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); + rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); + rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; + rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); + *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + + xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); + + + NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); + + RLC_BearerConfig->logicalChannelIdentity = 3; + RLC_BearerConfig->servedRadioBearer = calloc(1,sizeof(*RLC_BearerConfig->servedRadioBearer)); + RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; + + RLC_BearerConfig->servedRadioBearer->choice.drb_Identity=1; + RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); + *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; + RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); + + // RLC UM Bi-directional Bearer configuration + RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + + // RLC AM Bearer configuration + /*RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; + RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; + + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15;*/ + + RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); + *RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + + Rlc_Bearer_ToAdd_list = calloc(1,sizeof(*Rlc_Bearer_ToAdd_list)); + ASN_SEQUENCE_ADD(&Rlc_Bearer_ToAdd_list->list, RLC_BearerConfig); + + if (ENB_NAS_USE_TUN){ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); + } + else{ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); + } + + nr_rrc_pdcp_config_asn1_req( + &ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList , + rbconfig->drb_ToReleaseList, + 0xff, + NULL, + NULL, + NULL, + NULL, + NULL, + Rlc_Bearer_ToAdd_list); + + nr_rrc_rlc_config_asn1_req (&ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList, + rbconfig->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + Rlc_Bearer_ToAdd_list); +} + +uint64_t get_pdcp_optmask(void) +{ + return pdcp_optmask; +} + +boolean_t pdcp_remove_UE( + const protocol_ctxt_t *const ctxt_pP) +{ + TODO; + return 1; +} + +void pdcp_config_set_security(const protocol_ctxt_t* const ctxt_pP, pdcp_t *pdcp_pP, rb_id_t rb_id, + uint16_t lc_idP, uint8_t security_modeP, uint8_t *kRRCenc_pP, uint8_t *kRRCint_pP, uint8_t *kUPenc_pP) +{ + TODO; +} + +static boolean_t pdcp_data_req_drb( + protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) +{ +printf("pdcp_data_req called size %d\n", sdu_buffer_size); + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 /*|| + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0*/) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + + if (rb == NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal: no DRB found (rnti %d, rb_id %ld)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, rb_id); + exit(1); + } + + rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return 1; +} + +boolean_t pdcp_data_req( + protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + 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 mode +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + ,const uint32_t *const sourceL2Id + ,const uint32_t *const destinationL2Id +#endif + ) +{ + if (srb_flagP) { TODO; } + return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, + sdu_buffer); +} + +void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) +{ + /* nothing to do */ +} + +void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) +{ + /* nothing to do */ +} + +//Dummy function needed due to LTE dependencies +void +pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ + /* nothing to do */ +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c new file mode 100644 index 0000000000..ca51da3d5f --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -0,0 +1,198 @@ +/* + * 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 + */ + +#include "nr_pdcp_ue_manager.h" + +#include +#include +#include + +#include "LOG/log.h" + +typedef struct { + pthread_mutex_t lock; + nr_pdcp_ue_t **ue_list; + int ue_count; + int enb_flag; +} nr_pdcp_ue_manager_internal_t; + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag) +{ + nr_pdcp_ue_manager_internal_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_ue_manager_internal_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->enb_flag = enb_flag; + + return ret; +} + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->enb_flag; +} + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_lock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_unlock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + /* TODO: optimze */ + nr_pdcp_ue_manager_internal_t *m = _m; + int i; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + return m->ue_list[i]; + + LOG_D(PDCP, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti); + + m->ue_count++; + m->ue_list = realloc(m->ue_list, sizeof(nr_pdcp_ue_t *) * m->ue_count); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + m->ue_list[m->ue_count-1] = calloc(1, sizeof(nr_pdcp_ue_t)); + if (m->ue_list[m->ue_count-1] == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + m->ue_list[m->ue_count-1]->rnti = rnti; + + return m->ue_list[m->ue_count-1]; +} + +/* must be called with lock acquired */ +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + nr_pdcp_ue_t *ue; + int i; + int j; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + break; + + if (i == m->ue_count) { + LOG_D(PDCP, "%s:%d:%s: warning: ue %d not found\n", + __FILE__, __LINE__, __FUNCTION__, + rnti); + return; + } + + ue = m->ue_list[i]; + + for (j = 0; j < 2; j++) + if (ue->srb[j] != NULL) + ue->srb[j]->delete(ue->srb[j]); + + for (j = 0; j < 5; j++) + if (ue->drb[j] != NULL) + ue->drb[j]->delete(ue->drb[j]); + + free(ue); + + m->ue_count--; + if (m->ue_count == 0) { + free(m->ue_list); + m->ue_list = NULL; + return; + } + + memmove(&m->ue_list[i], &m->ue_list[i+1], + (m->ue_count - i) * sizeof(nr_pdcp_ue_t *)); + m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(nr_pdcp_ue_t *)); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, nr_pdcp_entity_t *entity) +{ + if (srb_id < 1 || srb_id > 2) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + srb_id--; + + if (ue->srb[srb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, srb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->srb[srb_id] = entity; +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity_t *entity) +{ + if (drb_id < 1 || drb_id > 5) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + drb_id--; + + if (ue->drb[drb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, drb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->drb[drb_id] = entity; +} + +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (m->ue_count == 0) + return -1; + return m->ue_list[0]->rnti; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h new file mode 100644 index 0000000000..0de2f024b3 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h @@ -0,0 +1,65 @@ +/* + * 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 + */ + +#ifndef _NR_PDCP_UE_MANAGER_H_ +#define _NR_PDCP_UE_MANAGER_H_ + +#include "nr_pdcp_entity.h" + +typedef void nr_pdcp_ue_manager_t; + +typedef struct nr_pdcp_ue_t { + int rnti; + nr_pdcp_entity_t *srb[2]; + nr_pdcp_entity_t *drb[5]; +} nr_pdcp_ue_t; + +/***********************************************************************/ +/* manager functions */ +/***********************************************************************/ + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag); + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *m); + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *m); +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); + +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); + +/***********************************************************************/ +/* ue functions */ +/***********************************************************************/ + +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, + nr_pdcp_entity_t *entity); +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, + nr_pdcp_entity_t *entity); + +/***********************************************************************/ +/* hacks */ +/***********************************************************************/ + +/* returns -1 if no UE */ +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *m); + +#endif /* _NR_PDCP_UE_MANAGER_H_ */ diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.c b/openair2/LAYER2/nr_rlc/asn1_utils.c index 46f7d90da5..43d55af1ac 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.c +++ b/openair2/LAYER2/nr_rlc/asn1_utils.c @@ -21,14 +21,14 @@ #include "rlc.h" -int decode_t_reordering(int v) +int decode_t_reassembly(int v) { - static int tab[32] = { - 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, - 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600 + static int tab[31] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200 }; - if (v < 0 || v > 31) { + if (v < 0 || v > 30) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -72,11 +72,13 @@ int decode_t_poll_retransmit(int v) int decode_poll_pdu(int v) { - static int tab[8] = { - 4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */ + static int tab[24] = { + 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 6144, 8192, 12288, + 16384, 20480, 24576, 28672, 32768, 40960, 49152, 57344, 65536 + -1 /* -1 means infinity */ }; - if (v < 0 || v > 7) { + if (v < 0 || v > 23) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -86,12 +88,23 @@ int decode_poll_pdu(int v) int decode_poll_byte(int v) { - static int tab[15] = { - 25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000, + static int tab[44] = { + /* KB */ + 1024 * 1, 1024 * 2, 1024 * 5, 1024 * 8, 1024 * 10, + 1024 * 15, 1024 * 25, 1024 * 50, 1024 * 75, 1024 * 100, + 1024 * 125, 1024 * 250, 1024 * 375, 1024 * 500, 1024 * 750, + 1024 * 1000, 1024 * 1250, 1024 * 1500, 1024 * 2000, 1024 * 3000, + 1024 * 4000, 1024 * 4500, 1024 * 5000, 1024 * 5500, 1024 * 6000, + 1024 * 6500, 1024 * 7000, 1024 * 7500, + /* MB */ + 1024 * 1024 * 8, 1024 * 1024 * 9, 1024 * 1024 * 10, 1024 * 1024 * 11, + 1024 * 1024 * 12, 1024 * 1024 * 13, 1024 * 1024 * 14, 1024 * 1024 * 15, + 1024 * 1024 * 16, 1024 * 1024 * 17, 1024 * 1024 * 18, 1024 * 1024 * 20, + 1024 * 1024 * 25, 1024 * 1024 * 30, 1024 * 1024 * 40, -1 /* -1 means infinity */ }; - if (v < 0 || v > 14) { + if (v < 0 || v > 43) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -114,10 +127,24 @@ int decode_max_retx_threshold(int v) return tab[v]; } -int decode_sn_field_length(int v) +int decode_sn_field_length_um(int v) { static int tab[2] = { - 5, 10 + 6, 12 + }; + + if (v < 0 || v > 1) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_field_length_am(int v) +{ + static int tab[2] = { + 12, 18 }; if (v < 0 || v > 1) { diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.h b/openair2/LAYER2/nr_rlc/asn1_utils.h index 61394c9c69..cf6309e330 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.h +++ b/openair2/LAYER2/nr_rlc/asn1_utils.h @@ -22,12 +22,13 @@ #ifndef _ASN1_UTILS_H_ #define _ASN1_UTILS_H_ -int decode_t_reordering(int v); +int decode_t_reassembly(int v); int decode_t_status_prohibit(int v); int decode_t_poll_retransmit(int v); int decode_poll_pdu(int v); int decode_poll_byte(int v); int decode_max_retx_threshold(int v); -int decode_sn_field_length(int v); +int decode_sn_field_length_um(int v); +int decode_sn_field_length_am(int v); #endif /* _ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 8f3d49d8c2..0c8526c2f0 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -109,7 +109,8 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity, * upper layers should deal with this condition, internally it's better * for the RLC code to keep going with this segment (we only remove * a segment that was ACKed) - */ + */ + LOG_D(RLC, "RLC segment to be added at the ReTx list \n"); nr_rlc_sdu_segment_list_append(&entity->retransmit_list, &entity->retransmit_end, cur); @@ -1588,6 +1589,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, sdu = nr_rlc_new_sdu(buffer, size, sdu_id); + LOG_I(RLC, "Created new RLC SDU and append it to the RLC list \n"); + nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index bbc4acbd56..04e0f5b3d6 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -27,19 +27,23 @@ #include "asn1_utils.h" #include "nr_rlc_ue_manager.h" #include "nr_rlc_entity.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_DRB-ToAddMod.h" +#include "NR_DRB-ToAddModList.h" +#include "NR_SRB-ToAddModList.h" +#include "NR_DRB-ToReleaseList.h" +#include "NR_CellGroupConfig.h" +#include "NR_RLC-Config.h" #include static nr_rlc_ue_manager_t *nr_rlc_ue_manager; /* TODO: handle time a bit more properly */ -//#if 0 static uint64_t nr_rlc_current_time; static int nr_rlc_current_time_last_frame; static int nr_rlc_current_time_last_subframe; -//#endif -//#if 0 void mac_rlc_data_ind ( const module_id_t module_idP, const rnti_t rntiP, @@ -195,7 +199,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( ret.head_sdu_is_segmented = 0; return ret; } -//#endif rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( const module_id_t module_idP, @@ -254,7 +257,6 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( int oai_emulation; -//#if 0 rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP, @@ -306,9 +308,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, return RLC_OP_STATUS_OK; } -//#endif -//#if 0 int rlc_module_init(int enb_flag) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; @@ -329,13 +329,10 @@ int rlc_module_init(int enb_flag) return 0; } -//#endif -//#if 0 void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) { } -//#endif static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) { @@ -522,7 +519,7 @@ rb_found: #endif } -__attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) +static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; @@ -532,7 +529,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * int srb_id = s->srb_Identity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -575,7 +571,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * exit(1); } am = &r->choice.explicitValue.choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); @@ -585,7 +580,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * } case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue: /* default values from 36.331 9.2.1 */ - //t_reordering = 35; t_status_prohibit = 0; t_poll_retransmit = 45; poll_pdu = -1; @@ -628,18 +622,17 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -669,10 +662,9 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) } switch (r->present) { - case LTE_RLC_Config_PR_am: { - struct LTE_RLC_Config__am *am; - am = &r->choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + case NR_RLC_Config_PR_am: { + struct NR_RLC_Config__am *am; + am = r->choice.am; t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); @@ -716,18 +708,17 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_um; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int sn_field_length; int t_reassembly; @@ -752,15 +743,15 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) } switch (r->present) { - case LTE_RLC_Config_PR_um_Bi_Directional: { - struct LTE_RLC_Config__um_Bi_Directional *um; - um = &r->choice.um_Bi_Directional; - //t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering); - if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) { + case NR_RLC_Config_PR_um_Bi_Directional: { + struct NR_RLC_Config__um_Bi_Directional *um; + um = r->choice.um_Bi_Directional; + t_reassembly = decode_t_reassembly(um->dl_UM_RLC.t_Reassembly); + if (*um->dl_UM_RLC.sn_FieldLength != *um->ul_UM_RLC.sn_FieldLength) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength); + sn_field_length = decode_sn_field_length_um(*um->dl_UM_RLC.sn_FieldLength); break; } default: @@ -774,9 +765,6 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - /* hack: hardcode values for NR */ - t_reassembly = 35; - sn_field_length = 6; nr_rlc_um = new_nr_rlc_entity_um(1000000, 1000000, deliver_sdu, ue, @@ -790,14 +778,14 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -__attribute__ ((unused)) static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, struct NR_RLC_BearerConfig *rlc_BearerConfig) { - switch (s->rlc_Config->present) { - case LTE_RLC_Config_PR_am: - add_drb_am(rnti, s); + switch (rlc_BearerConfig->rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(rnti, s, rlc_BearerConfig); break; - case LTE_RLC_Config_PR_um_Bi_Directional: - add_drb_um(rnti, s); + case NR_RLC_Config_PR_um_Bi_Directional: + add_drb_um(rnti, s, rlc_BearerConfig); break; default: LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n", @@ -806,7 +794,7 @@ __attribute__ ((unused)) static void add_drb(int rnti, struct LTE_DRB_ToAddMod * } } -//#if 0 +/* Dummy function due to dependency from LTE libraries */ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, const LTE_SRB_ToAddModList_t * const srb2add_listP, const LTE_DRB_ToAddModList_t * const drb2add_listP, @@ -814,6 +802,16 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, const uint32_t sourceL2Id, const uint32_t destinationL2Id) +{ + return 0; +} + +rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const LTE_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) { int rnti = ctxt_pP->rnti; int i; @@ -845,15 +843,13 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP if (drb2add_listP != NULL) { for (i = 0; i < drb2add_listP->list.count; i++) { - add_drb(rnti, drb2add_listP->list.array[i]); + add_drb(rnti, drb2add_listP->list.array[i], rlc_bearer2add_list->list.array[i]); } } return RLC_OP_STATUS_OK; } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_config_req ( const protocol_ctxt_t* const ctxt_pP, const srb_flag_t srb_flagP, @@ -912,16 +908,12 @@ rlc_op_status_t rrc_rlc_config_req ( nr_rlc_manager_unlock(nr_rlc_ue_manager); return RLC_OP_STATUS_OK; } -//#endif -//#if 0 void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) { /* nothing to do */ } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) { LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti); @@ -931,4 +923,3 @@ rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) return RLC_OP_STATUS_OK; } -//#endif diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 865bf32b34..78f39c16d7 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -36,11 +36,34 @@ //#include "NR_UE-CapabilityRAT-ContainerList.h" #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" +//#include "NR_SRB-ToAddModList.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h" #include "executables/softmodem-common.h" #include +extern boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc + #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + #endif + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -244,6 +267,27 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ 1, // add_ue flag ue_context_p->ue_id_rnti, ue_context_p->ue_context.secondaryCellGroup); + + nr_rrc_pdcp_config_asn1_req( + &ctxt, + (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList , + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + 0xff, + NULL, + NULL, + NULL, + NULL, + NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + + nr_rrc_rlc_config_asn1_req (&ctxt, + (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList, + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 6ea6f3b3b3..d3eae00ca7 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -66,7 +66,19 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); - RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; + + // RLC UM Bi-directional Bearer configuration + RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + + // RLC AM Bearer configuration + /*RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; @@ -77,7 +89,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15;*/ RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; @@ -150,9 +162,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions= calloc(1,sizeof(struct NR_CFRA__occasions)); memcpy(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->rach_ConfigGeneric, &servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric, sizeof(NR_RACH_ConfigGeneric_t)); - //secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); - //*secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= NULL; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); + *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb; secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb = calloc(1,sizeof(struct NR_CFRA__resources__ssb)); secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; @@ -2047,7 +2058,7 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity=5; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; drb_ToAddMod->drb_Identity = 1; drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL;