diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 32f06de02524a7a657c5a9e9d78b8defad6476a3..3a561cc60a1e1effa02d9d3feaec2cf429c8cc72 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2005,6 +2005,7 @@ add_executable(oaisim_nos1 ${OPENAIR_BIN_DIR}/messages_xml.h ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-ru.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 36dae6431c6e69edd57661c824653cb6b22f1363..bf63d5abbefb8857d02c0cafe74ee523ce38895b 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -6560,7 +6560,7 @@ uint8_t pdcch_alloc2ul_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n) else ul_subframe = ((n+4)%10); - if (subframe_select(frame_parms,ul_subframe) != SF_UL) return(255); + if ((subframe_select(frame_parms,ul_subframe) != SF_UL) && (frame_parms->frame_type == TDD)) return(255); LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe); return ul_subframe; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 1b3e634e6c23f94b3e7279bd95f38a1fe2171970..e067137a14b8ff180f67702b906317999efbb7c3 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -178,9 +178,26 @@ void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch) //ulsch->harq_processes[i]->phich_active = 0; //this will be done later after transmission of PHICH ulsch->harq_processes[i]->phich_ACK = 0; ulsch->harq_processes[i]->round = 0; + ulsch->harq_processes[i]->rar_alloc = 0; + ulsch->harq_processes[i]->first_rb = 0; + ulsch->harq_processes[i]->nb_rb = 0; + ulsch->harq_processes[i]->TBS = 0; + ulsch->harq_processes[i]->Or1 = 0; + ulsch->harq_processes[i]->Or2 = 0; + for ( int j = 0; j < 2; j++ ) { + ulsch->harq_processes[i]->o_RI[j] = 0; + } + ulsch->harq_processes[i]->O_ACK = 0; + ulsch->harq_processes[i]->srs_active = 0; + ulsch->harq_processes[i]->rvidx = 0; + ulsch->harq_processes[i]->Msc_initial = 0; + ulsch->harq_processes[i]->Nsymb_initial = 0; } } - + ulsch->beta_offset_cqi_times8 = 0; + ulsch->beta_offset_ri_times8 = 0; + ulsch->beta_offset_harqack_times8 = 0; + ulsch->Msg3_active = 0; } } @@ -2044,3 +2061,4 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, } #endif + diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 0e44a7f8bd6f184923f7798791b933422768fc7f..6f52867d2d0c590c819c602d8f2bd35d3772e495 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -989,6 +989,7 @@ typedef struct PHY_VARS_eNB_s { LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA LTE_eNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p; LTE_eNB_DLSCH_t *dlsch_MCH; + LTE_eNB_DLSCH_t *dlsch_PCH; LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX]; LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX]; diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index e29bbf7aad220952cc5ab1b240658ce0ba006fd3..7fb9e6991d58e187bf06d9d9383b8ce724c637f4 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -213,6 +213,13 @@ void prach_procedures(PHY_VARS_eNB *eNB, int br_flag #endif ); + +/*! \brief Function to compute subframe Number(DL and S) as a function of Frame type and TDD Configuration + @param frame_parms Pointer to DL frame parameter descriptor + @returns Subframe Number (DL,S) +*/ +int subframe_num(LTE_DL_FRAME_PARMS *frame_parms); + /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. @param frame_parms Pointer to DL frame parameter descriptor @param subframe Subframe index diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index 01c44d6078f6df559cfaf0b99643d14d388eb736..bbb6986ce9c7c3ac375e79eb170e5c4c77b2ab72 100644 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -709,6 +709,26 @@ uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1) return(Np[0+plus1]); } +int subframe_num(LTE_DL_FRAME_PARMS *frame_parms){ + if (frame_parms->frame_type == FDD) + return 10; + + switch (frame_parms->tdd_config) { + case 1: + return 6; + case 3: + return 7; + case 4: + return 8; + case 5: + return 9; + default: + LOG_E(PHY,"Unsupported TDD configuration %d\n",frame_parms->tdd_config); + AssertFatal(frame_parms->tdd_config==1 || frame_parms->tdd_config==3 || frame_parms->tdd_config==4 || frame_parms->tdd_config==5,"subframe x Unsupported TDD configuration"); + return(255); + } +} + lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe) { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index db729187cba2328ebb329f12a0643f7b2530444a..4aa9600c06585ba25da7eda923e50320096c7d03 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -887,10 +887,10 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) if (uci->type == SR) { if (SR_payload == 1) { fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); - return; + continue; } else { - return; + continue; } } case HARQ: diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index c1135a34ae05cbae7143d4be13f5eba70f31861e..fcb45431491b940a8646600b2bccec82626b4951 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -40,3 +40,5 @@ MESSAGE_DEF(RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDat MESSAGE_DEF(RRC_MAC_MCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDataReq, rrc_mac_mcch_data_req) MESSAGE_DEF(RRC_MAC_MCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDataInd, rrc_mac_mcch_data_ind) + +MESSAGE_DEF(RRC_MAC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacPcchDataReq, rrc_mac_pcch_data_req) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index 5f27a0fe69ea20b1673c6e8110f28f1c3d68983d..d7fd44f072a35d0de25c04777ba62e7b7d6ca96e 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -43,11 +43,13 @@ #define RRC_MAC_MCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_req #define RRC_MAC_MCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_ind +#define RRC_MAC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_pcch_data_req // Some constants from "LAYER2/MAC/defs.h" #define BCCH_SDU_SIZE (512) #define CCCH_SDU_SIZE (512) #define MCCH_SDU_SIZE (512) +#define PCCH_SDU_SIZE (512) //-------------------------------------------------------------------------------------------// // Messages between RRC and MAC layers @@ -114,4 +116,10 @@ typedef struct RrcMacMcchDataInd_s { uint8_t mbsfn_sync_area; } RrcMacMcchDataInd; +typedef struct RrcMacPcchDataReq_s { + uint32_t frame; + uint32_t sdu_size; + uint8_t sdu[PCCH_SDU_SIZE]; + uint8_t enb_index; +} RrcMacPcchDataReq; #endif /* MAC_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/pdcp_messages_def.h b/openair2/COMMON/pdcp_messages_def.h index da0d770def60982456d1312874e6828215aed70f..c4be4b2957416ed4fcc96ee17f16514b683129a6 100644 --- a/openair2/COMMON/pdcp_messages_def.h +++ b/openair2/COMMON/pdcp_messages_def.h @@ -30,3 +30,4 @@ // Messages between RRC and PDCP layers MESSAGE_DEF(RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataReq, rrc_dcch_data_req) MESSAGE_DEF(RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd, rrc_dcch_data_ind) +MESSAGE_DEF(RRC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcPcchDataReq, rrc_pcch_data_req) diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h index 033e73e86bbd8370f442d566238d7f01ed78e965..c90490b0fd36077c99f1c023ec33655244b01ca0 100644 --- a/openair2/COMMON/pdcp_messages_types.h +++ b/openair2/COMMON/pdcp_messages_types.h @@ -33,6 +33,7 @@ // Defines to access message fields. #define RRC_DCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_req #define RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_ind +#define RRC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_pcch_data_req //-------------------------------------------------------------------------------------------// // Messages between RRC and PDCP layers @@ -60,4 +61,13 @@ typedef struct RrcDcchDataInd_s { uint8_t eNB_index; // LG: needed in UE } RrcDcchDataInd; +typedef struct RrcPcchDataReq_s { + uint32_t sdu_size; + uint8_t *sdu_p; + uint8_t mode; + uint16_t rnti; + uint8_t ue_index; + uint8_t CC_id; +} RrcPcchDataReq; + #endif /* PDCP_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/s1ap_messages_def.h b/openair2/COMMON/s1ap_messages_def.h index d3d853c7e714532e36d12119e19e0f8520ccf624..a39953d8f77e777ca79b1e4644be41690ae3f799 100644 --- a/openair2/COMMON/s1ap_messages_def.h +++ b/openair2/COMMON/s1ap_messages_def.h @@ -33,6 +33,11 @@ MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgT MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_ue_context_release_log) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_request_log) MESSAGE_DEF(S1AP_E_RAB_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_response_log) +MESSAGE_DEF(S1AP_E_RAB_MODIFY_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_modify_request_log) +MESSAGE_DEF(S1AP_E_RAB_MODIFY_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_modify_response_log) +MESSAGE_DEF(S1AP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_paging_log) +MESSAGE_DEF(S1AP_E_RAB_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_request_log) +MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_response_log) /* eNB application layer -> S1AP messages */ MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req) @@ -54,6 +59,8 @@ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_fail_t , s1ap_ue_ctxt_modification_fail) MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_resp_t , s1ap_e_rab_setup_resp) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail) +MESSAGE_DEF(S1AP_E_RAB_MODIFY_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_resp_t , s1ap_e_rab_modify_resp) +MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_resp_t , s1ap_e_rab_release_resp) /* S1AP -> RRC messages */ MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas ) @@ -61,6 +68,8 @@ MESSAGE_DEF(S1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, s1ap_initial_ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_req_t , s1ap_ue_ctxt_modification_req) MESSAGE_DEF(S1AP_PAGING_IND , MESSAGE_PRIORITY_MED, s1ap_paging_ind_t , s1ap_paging_ind ) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQ , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_t , s1ap_e_rab_setup_req ) +MESSAGE_DEF(S1AP_E_RAB_MODIFY_REQ , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_req_t , s1ap_e_rab_modify_req ) +MESSAGE_DEF(S1AP_E_RAB_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_command_t , s1ap_e_rab_release_command) MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, s1ap_ue_release_command_t , s1ap_ue_release_command) /* S1AP <-> RRC messages (can be initiated either by MME or eNB) */ diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index c17097d4ecb9b3b3ea02d13e8d618e863dc69df1..4a5f492b0baa3f4685c8de48f342ff6075e02d8f 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -41,6 +41,7 @@ #define S1AP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_fail #define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp #define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail +#define S1AP_E_RAB_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_modify_resp #define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas #define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req @@ -48,9 +49,12 @@ #define S1AP_UE_CONTEXT_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_command #define S1AP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_complete #define S1AP_E_RAB_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req -#define S1AP_PAGIND_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_paging_ind +#define S1AP_E_RAB_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_modify_req +#define S1AP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_paging_ind #define S1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_req +#define S1AP_E_RAB_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_release_command +#define S1AP_E_RAB_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_release_resp //-------------------------------------------------------------------------------------------// /* Maximum number of e-rabs to be setup/deleted in a single message. @@ -175,6 +179,11 @@ typedef struct s1ap_gummei_s { uint16_t mme_group_id; } s1ap_gummei_t; +typedef struct s1ap_imsi_s { + uint8_t buffer[S1AP_IMSI_LENGTH]; + uint8_t length; +} s1ap_imsi_t; + typedef struct s_tmsi_s { uint8_t mme_code; uint32_t m_tmsi; @@ -189,7 +198,7 @@ typedef enum ue_paging_identity_presenceMask_e { typedef struct ue_paging_identity_s { ue_paging_identity_presenceMask_t presenceMask; union { - char imsi[S1AP_IMSI_LENGTH]; + s1ap_imsi_t imsi; s_tmsi_t s_tmsi; } choice; } ue_paging_identity_t; @@ -260,11 +269,29 @@ typedef struct e_rab_setup_s { uint32_t gtp_teid; } e_rab_setup_t; +typedef struct e_rab_modify_s { + /* Unique e_rab_id for the UE. */ + uint8_t e_rab_id; +} e_rab_modify_t; + +typedef enum S1ap_Cause_e { + S1AP_CAUSE_NOTHING, /* No components present */ + S1AP_CAUSE_RADIO_NETWORK, + S1AP_CAUSE_TRANSPORT, + S1AP_CAUSE_NAS, + S1AP_CAUSE_PROTOCOL, + S1AP_CAUSE_MISC, + /* Extensions may appear below */ + +} s1ap_Cause_t; + typedef struct e_rab_failed_s { /* Unique e_rab_id for the UE. */ uint8_t e_rab_id; /* Cause of the failure */ // cause_t cause; + s1ap_Cause_t cause; + uint8_t cause_value; } e_rab_failed_t; typedef enum s1ap_ue_ctxt_modification_present_s { @@ -460,6 +487,12 @@ typedef struct s1ap_initial_context_setup_req_s { e_rab_t e_rab_param[S1AP_MAX_E_RAB]; } s1ap_initial_context_setup_req_t; +typedef struct tai_plmn_identity_s { + uint16_t mcc; + uint16_t mnc; + uint8_t mnc_digit_length; +} plmn_identity_t; + typedef struct s1ap_paging_ind_s { /* UE identity index value. * Specified in 3GPP TS 36.304 @@ -472,6 +505,15 @@ typedef struct s1ap_paging_ind_s { /* Indicates origin of paging */ cn_domain_t cn_domain; + /* PLMN_identity in TAI of Paging*/ + plmn_identity_t plmn_identity[256]; + + /* TAC in TAIList of Paging*/ + int16_t tac[256]; + + /* size of TAIList*/ + int16_t tai_size; + /* Optional fields */ paging_drx_t paging_drx; @@ -520,16 +562,6 @@ typedef struct s1ap_ue_release_command_s { //-------------------------------------------------------------------------------------------// -typedef enum S1ap_Cause_e { - S1AP_CAUSE_NOTHING, /* No components present */ - S1AP_CAUSE_RADIO_NETWORK, - S1AP_CAUSE_TRANSPORT, - S1AP_CAUSE_NAS, - S1AP_CAUSE_PROTOCOL, - S1AP_CAUSE_MISC, - /* Extensions may appear below */ - -} s1ap_Cause_t; // S1AP <-- RRC messages typedef struct s1ap_ue_release_req_s { unsigned eNB_ue_s1ap_id:24; @@ -537,4 +569,78 @@ typedef struct s1ap_ue_release_req_s { long cause_value; } s1ap_ue_release_req_t, s1ap_ue_release_resp_t; +typedef struct s1ap_e_rab_modify_req_s { + /* UE id for initial connection to S1AP */ + uint16_t ue_initial_id; + + /* MME UE id */ + uint16_t mme_ue_s1ap_id; + + /* eNB ue s1ap id as initialized by S1AP layer */ + unsigned eNB_ue_s1ap_id:24; + + /* Number of e_rab to be modify in the list */ + uint8_t nb_e_rabs_tomodify; + + /* E RAB modify request */ + e_rab_t e_rab_modify_params[S1AP_MAX_E_RAB]; +} s1ap_e_rab_modify_req_t; + +typedef struct s1ap_e_rab_modify_resp_s { + unsigned eNB_ue_s1ap_id:24; + + /* Number of e_rab modify-ed in the list */ + uint8_t nb_of_e_rabs; + /* list of e_rab modify-ed by RRC layers */ + e_rab_modify_t e_rabs[S1AP_MAX_E_RAB]; + + /* Number of e_rab failed to be modify in list */ + uint8_t nb_of_e_rabs_failed; + /* list of e_rabs that failed to be modify */ + e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB]; +} s1ap_e_rab_modify_resp_t; + +typedef struct e_rab_release_s { + /* Unique e_rab_id for the UE. */ + uint8_t e_rab_id; +} e_rab_release_t; + +typedef struct s1ap_e_rab_release_command_s { + /* MME UE id */ + uint16_t mme_ue_s1ap_id; + + /* eNB ue s1ap id as initialized by S1AP layer */ + unsigned eNB_ue_s1ap_id:24; + + /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ + nas_pdu_t nas_pdu; + + /* Number of e_rab to be released in the list */ + uint8_t nb_e_rabs_torelease; + + /* E RAB release command */ + e_rab_release_t e_rab_release_params[S1AP_MAX_E_RAB]; + +} s1ap_e_rab_release_command_t; + +typedef struct s1ap_e_rab_release_resp_s { + /* MME UE id */ + uint16_t mme_ue_s1ap_id; + + /* eNB ue s1ap id as initialized by S1AP layer */ + unsigned eNB_ue_s1ap_id:24; + + /* Number of e_rab released in the list */ + uint8_t nb_of_e_rabs_released; + + /* list of e_rabs released */ + e_rab_release_t e_rab_release[S1AP_MAX_E_RAB]; + + /* Number of e_rab failed to be released in list */ + uint8_t nb_of_e_rabs_failed; + /* list of e_rabs that failed to be released */ + e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB]; + +} s1ap_e_rab_release_resp_t; + #endif /* S1AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index 43d8167fe604315290e416dbd8190fbfcffae392..78a74f00d3f1a48b705cc15a03dc880e5d5f226e 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -163,6 +163,8 @@ /*!\brief maximum number of slices / groups */ #define MAX_NUM_SLICES 4 +#define U_PLANE_INACTIVITY_VALUE 6000 + /* * eNB part */ @@ -472,6 +474,15 @@ typedef struct { /// BCCH MCS uint32_t ccch_mcs; + /// num PCCH PDU per CC + uint32_t total_num_pcch_pdu; + /// PCCH buffer size + uint32_t pcch_buffer; + /// total PCCH buffer size + uint32_t total_pcch_buffer; + /// BCCH MCS + uint32_t pcch_mcs; + /// num active users uint16_t num_dlactive_UEs; /// available number of PRBs for a give SF @@ -824,6 +835,8 @@ typedef struct { int32_t cqi_req_timer; int32_t ul_inactivity_timer; int32_t ul_failure_timer; + uint32_t ue_reestablishment_reject_timer; + uint32_t ue_reestablishment_reject_timer_thres; int32_t ul_scheduled; int32_t ra_pdcch_order_sent; int32_t ul_out_of_sync; @@ -855,6 +868,7 @@ typedef struct { uint8_t aperiodic_wideband_cqi1[NFAPI_CC_MAX]; uint8_t aperiodic_wideband_pmi1[NFAPI_CC_MAX]; uint8_t dl_cqi[NFAPI_CC_MAX]; + int32_t uplane_inactivity_timer; } UE_sched_ctrl; /*! \brief eNB template for the Random access information */ typedef struct { @@ -982,6 +996,10 @@ typedef struct { uint32_t BCCH_alloc_pdu; /// Outgoing CCCH pdu for PHY CCCH_PDU CCCH_pdu; + /// Outgoing PCCH DCI allocation + uint32_t PCCH_alloc_pdu; + /// Outgoing PCCH pdu for PHY + PCCH_PDU PCCH_pdu; /// Outgoing RAR pdu for PHY RAR_PDU RAR_pdu; /// Template for RA computations @@ -1102,6 +1120,8 @@ typedef struct eNB_MAC_INST_s { time_stats_t schedule_mch; /// processing time of eNB ULSCH reception time_stats_t rx_ulsch_sdu; // include rlc_data_ind + /// processing time of eNB PCH scheduler + time_stats_t schedule_pch; } eNB_MAC_INST; /* diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index f03a3961f67c5d10c6272dd61595cffefe2a7bec..42835a5a8824089a97088e88b66ee042665b195b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -164,7 +164,7 @@ schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG; ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t) - sizeof(nfapi_ul_config_srs_pdu);; + sizeof(nfapi_ul_config_srs_pdu); ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id]. rnti; @@ -546,7 +546,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; // check threshold - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) { + if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 20000) { // inform RRC of failure and clear timer LOG_I(MAC, "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n", @@ -558,6 +558,12 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, } } // ul_failure_timer>0 + UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer++; + if(UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE*subframe_num(&RC.eNB[module_idP][CC_id]->frame_parms))){ + LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti); + mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti); + UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + }// time > 60s } void @@ -702,6 +708,50 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, ul_inactivity_timer, RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer); check_ul_failure(module_idP, CC_id, i, frameP, subframeP); + + if (RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer > 0) { + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer++; + if(RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer >= + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer_thres) { + RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer = 0; + for (int ue_id_l = 0; ue_id_l < NUMBER_OF_UE_MAX; ue_id_l++) { + if (reestablish_rnti_map[ue_id_l][0] == rnti) { + // clear currentC-RNTI from map + reestablish_rnti_map[ue_id_l][0] = 0; + reestablish_rnti_map[ue_id_l][1] = 0; + break; + } + } + + for (int ii=0; ii<NUMBER_OF_UE_MAX; ii++) { + LTE_eNB_ULSCH_t *ulsch = NULL; + ulsch = RC.eNB[module_idP][CC_id]->ulsch[ii]; + if((ulsch != NULL) && (ulsch->rnti == rnti)){ + LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti); + clean_eNb_ulsch(ulsch); + break; + } + } + + for(int j = 0; j < 10; j++){ + nfapi_ul_config_request_body_t *ul_req_tmp = NULL; + ul_req_tmp = &RC.mac[module_idP]->UL_req_tmp[CC_id][j].ul_config_request_body; + if(ul_req_tmp){ + int pdu_number = ul_req_tmp->number_of_pdus; + for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){ + if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){ + LOG_I(MAC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number); + if(pdu_index < pdu_number -1){ + memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t)); + } + ul_req_tmp->number_of_pdus--; + } + } + } + } + rrc_mac_remove_ue(module_idP,rnti); + } + } } @@ -731,6 +781,8 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, schedule_mib(module_idP, frameP, subframeP); // This schedules SI for legacy LTE and eMTC starting in subframeP schedule_SI(module_idP, frameP, subframeP); + // This schedules Paging in subframeP + schedule_PCH(module_idP,frameP,subframeP); // This schedules Random-Access for legacy LTE and eMTC starting in subframeP schedule_RA(module_idP, frameP, subframeP); // copy previously scheduled UL resources (ULSCH + HARQ) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index fe6c045fe71de4389240952c5dec3f9e3c8950d7..31ef50feaeb77280b3d2830a339599ebe39c4ee7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1073,6 +1073,7 @@ schedule_ue_spec(module_id_t module_idP, header_len_dtch_last--; } num_sdus++; + UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } // no data for this LCID else { header_len_dtch -= 3; @@ -1655,7 +1656,13 @@ unsigned char *get_dlsch_sdu(module_id_t module_idP, BCCH_pdu.payload[0]); } - UE_id = find_UE_id(module_idP, rntiP); + if (rntiP==P_RNTI) { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Get PCH sdu for PCCH \n", module_idP, CC_id, frameP); + + return((unsigned char *)&eNB->common_channels[CC_id].PCCH_pdu.payload[0]); + } + + UE_id = find_UE_id(module_idP,rntiP); if (UE_id != -1) { LOG_D(MAC, @@ -1770,3 +1777,351 @@ set_ue_dai(sub_frame_t subframeP, break; } } + +void schedule_PCH(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP) +{ + /* DCI:format 1A/1C P-RNTI:0xFFFE */ + /* PDU:eNB_rrc_inst[Mod_idP].common_channels[CC_id].PCCH_pdu.payload */ + uint16_t pcch_sdu_length; + int mcs = -1; + int CC_id; + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + uint8_t *vrb_map; + int n_rb_dl; + int first_rb = -1; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + nfapi_dl_config_request_body_t *dl_req; +#ifdef FORMAT1C + int gap_index = 0; /* indicate which gap(1st or 2nd) is used (0:1st) */ + const int GAP_MAP [9][2] = { + {-1, 0}, /* N_RB_DL [6-10] -1: |N_RB/2| 0: N/A*/ + {4, 0}, /* N_RB_DL [11] */ + {8, 0}, /* N_RB_DL [12-19] */ + {12, 0}, /* N_RB_DL [20-26] */ + {18, 0}, /* N_RB_DL [27-44] */ + {27, 0}, /* N_RB_DL [45-49] */ + {27, 9}, /* N_RB_DL [50-63] */ + {32, 16}, /* N_RB_DL [64-79] */ + {48, 16} /* N_RB_DL [80-110] */ + }; + uint8_t n_rb_step = 0; + uint8_t n_gap = 0; + uint8_t n_vrb_dl = 0; + uint8_t Lcrbs = 0; + uint16_t rb_bit = 168; /* RB bit number value is unsure */ + #endif + + start_meas(&eNB->schedule_pch); + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + cc = &eNB->common_channels[CC_id]; + vrb_map = (void*)&cc->vrb_map; + n_rb_dl = to_prb(cc->mib->message.dl_Bandwidth); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + for (uint16_t i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_PF_PO[CC_id][i].enable_flag != TRUE) { + continue; + } + if (frameP % UE_PF_PO[CC_id][i].T == UE_PF_PO[CC_id][i].PF_min && subframeP == UE_PF_PO[CC_id][i].PO) { + pcch_sdu_length = mac_rrc_data_req(module_idP, + CC_id, + frameP, + PCCH,1, + &cc->PCCH_pdu.payload[0], + 1, + module_idP, + i); // used for ue index + if (pcch_sdu_length == 0) { + LOG_D(MAC,"[eNB %d] Frame %d subframe %d: PCCH not active(size = 0 byte)\n", module_idP,frameP, subframeP); + continue; + } + LOG_D(MAC,"[eNB %d] Frame %d subframe %d: PCCH->PCH CC_id %d UE_id %d, Received %d bytes \n", module_idP, frameP, subframeP, CC_id,i, pcch_sdu_length); +#ifdef FORMAT1C + //NO SIB + if ((subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) || + (subframeP == 5 && ((frameP % 2) != 0 && (frameP % 8) != 1))) { + switch (n_rb_dl) { +#if 0 + case 6: + n_gap = n_rb_dl/2; /* expect: 3 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));; /* expect: 6 */ + first_rb = 0; + break; + case 15: + n_gap = GAP_MAP[2][0]; /* expect: 8 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 14 */ + first_rb = 6; + break; +#endif + case 25: + n_gap = GAP_MAP[3][0]; /* expect: 12 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 24 */ + first_rb = 10; + break; + case 50: + n_gap = GAP_MAP[6][gap_index]; /* expect: 27 or 9 */ + if (gap_index > 0) { + n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap); /* 36 */ + } else { + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 46 */ + } + first_rb = 24; + break; + case 100: + n_gap = GAP_MAP[8][gap_index]; /* expect: 48 or 16 */ + if (gap_index > 0) { + n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap); /* expect: 96 */ + } else { + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 96 */ + } + first_rb = 48; + break; + } + } else if (subframeP == 5 && ((frameP % 2) == 0 || (frameP % 8) == 1)) { // SIB + paging + switch (n_rb_dl) { +#if 0 + case 6: + n_gap = n_rb_dl/2; /* expect: 3 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));; /* expect: 6 */ + first_rb = 0; + break; + case 15: + n_gap = GAP_MAP[2][0]; /* expect: 8 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 14 */ + first_rb = 10; + break; +#endif + case 25: + n_gap = GAP_MAP[3][0]; /* expect: 12 */ + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 24 */ + first_rb = 14; + break; + case 50: + n_gap = GAP_MAP[6][gap_index]; /* expect: 27 or 9 */ + if (gap_index > 0) { + n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap); /* 36 */ + } else { + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 46 */ + } + first_rb = 28; + break; + case 100: + n_gap = GAP_MAP[8][gap_index]; /* expect: 48 or 16 */ + if (gap_index > 0) { + n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap); /* expect: 96 */ + } else { + n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap)); /* expect: 96 */ + } + first_rb = 52; + break; + } + } + /* Get MCS for length of PCH */ + if (pcch_sdu_length <= TBStable1C[0]) { + mcs=0; + } else if (pcch_sdu_length <= TBStable1C[1]) { + mcs=1; + } else if (pcch_sdu_length <= TBStable1C[2]) { + mcs=2; + } else if (pcch_sdu_length <= TBStable1C[3]) { + mcs=3; + } else if (pcch_sdu_length <= TBStable1C[4]) { + mcs=4; + } else if (pcch_sdu_length <= TBStable1C[5]) { + mcs=5; + } else if (pcch_sdu_length <= TBStable1C[6]) { + mcs=6; + } else if (pcch_sdu_length <= TBStable1C[7]) { + mcs=7; + } else if (pcch_sdu_length <= TBStable1C[8]) { + mcs=8; + } else if (pcch_sdu_length <= TBStable1C[9]) { + mcs=9; + } else { + /* unexpected: pcch sdb size is over max value*/ + LOG_E(MAC,"[eNB %d] Frame %d : PCCH->PCH CC_id %d, Received %d bytes is over max length(256) \n", + module_idP, frameP,CC_id, pcch_sdu_length); + return; + } + rb_num = TBStable1C[mcs] / rb_bit + ( (TBStable1C[mcs] % rb_bit == 0)? 0: 1) + 1; + /* calculate N_RB_STEP and Lcrbs */ + if (n_rb_dl < 50) { + n_rb_step = 2; + Lcrbs = rb_num / 2 + ((rb_num % 2 == 0) ? 0:2); + } else { + n_rb_step = 4; + Lcrbs = rb_num / 4 + ((rb_num % 4 == 0) ? 0:4); + } + for(i = 0;i < Lcrbs ;i++){ + vrb_map[first_rb+i] = 1; + } +#else + //NO SIB + if ((subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) || + (subframeP == 5 && ((frameP % 2) != 0 && (frameP % 8) != 1))) { + switch (n_rb_dl) { + case 25: + first_rb = 10; + break; + case 50: + first_rb = 24; + break; + case 100: + first_rb = 48; + break; + } + } else if (subframeP == 5 && ((frameP % 2) == 0 || (frameP % 8) == 1)) { // SIB + paging + switch (n_rb_dl) { + case 25: + first_rb = 14; + break; + case 50: + first_rb = 28; + break; + case 100: + first_rb = 52; + break; + } + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + /* Get MCS for length of PCH */ + if (pcch_sdu_length <= get_TBS_DL(0,3)) { + mcs=0; + } else if (pcch_sdu_length <= get_TBS_DL(1,3)) { + mcs=1; + } else if (pcch_sdu_length <= get_TBS_DL(2,3)) { + mcs=2; + } else if (pcch_sdu_length <= get_TBS_DL(3,3)) { + mcs=3; + } else if (pcch_sdu_length <= get_TBS_DL(4,3)) { + mcs=4; + } else if (pcch_sdu_length <= get_TBS_DL(5,3)) { + mcs=5; + } else if (pcch_sdu_length <= get_TBS_DL(6,3)) { + mcs=6; + } else if (pcch_sdu_length <= get_TBS_DL(7,3)) { + mcs=7; + } else if (pcch_sdu_length <= get_TBS_DL(8,3)) { + mcs=8; + } else if (pcch_sdu_length <= get_TBS_DL(9,3)) { + mcs=9; + } +#endif + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); +#ifdef FORMAT1C + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1C; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_vrb_dl/n_rb_step, first_rb/n_rb_step, Lcrbs/n_rb_step); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.ngap = n_gap; +#else + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl,first_rb,4); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; +#endif + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFE; // P-RNTI + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // P-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + + // Rel10 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3; + // Rel13 fields + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 0; // regular UE + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; + + if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, P_RNTI)) { + LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for P_RNTI\n", frameP,subframeP); + dl_req->number_dci++; + dl_req->number_pdu++; + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFE; +#ifdef FORMAT1C + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 3; // format 1C + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(n_vrb_dl/n_rb_step, first_rb/n_rb_step, Lcrbs/n_rb_step); +#else + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(n_rb_dl,first_rb,4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized +#endif + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + eNB->TX_req[CC_id].sfn_sf = (frameP<<4)+subframeP; + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = pcch_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = pcch_sdu_length; + TX_req->segments[0].segment_data = cc[CC_id].PCCH_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + } else { + LOG_E(MAC,"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A/1C for Paging\n",module_idP, CC_id, frameP, subframeP); + continue; + } + + if (opt_enabled == 1) { + trace_pdu(1, + &eNB->common_channels[CC_id].PCCH_pdu.payload[0], + pcch_sdu_length, + 0xffff, + PCCH, + P_RNTI, + eNB->frame, + eNB->subframe, + 0, + 0); + LOG_D(OPT,"[eNB %d][PCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, 0xffff, pcch_sdu_length); + } + eNB->eNB_stats[CC_id].total_num_pcch_pdu+=1; + eNB->eNB_stats[CC_id].pcch_buffer=pcch_sdu_length; + eNB->eNB_stats[CC_id].total_pcch_buffer+=pcch_sdu_length; + eNB->eNB_stats[CC_id].pcch_mcs=mcs; + //paging first_rb log + LOG_D(MAC,"[eNB %d] Frame %d subframe %d PCH: paging_ue_index %d pcch_sdu_length %d mcs %d first_rb %d\n", + module_idP, frameP, subframeP, UE_PF_PO[CC_id][i].ue_index_value, pcch_sdu_length, mcs, first_rb); + + pthread_mutex_lock(&ue_pf_po_mutex); + memset(&UE_PF_PO[CC_id][i], 0, sizeof(UE_PF_PO_t)); + pthread_mutex_unlock(&ue_pf_po_mutex); + } + } + } + /* this might be misleading when pcch is inactive */ + stop_meas(&eNB->schedule_pch); + return; +} diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 1bffb83d49efc74c5b6647049990bc1c85fdcaf3..3e574a56c36432dd69790fa3dc6958fa1b5a757d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2094,6 +2094,7 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP, int harq_pidP sizeof(UE_sched_ctrl)); memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], 0, sizeof(eNB_UE_STATS)); + UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; UE_list->UE_sched_ctrl[UE_id].ta_update = 31; @@ -2124,47 +2125,68 @@ int rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { int i; + int j; UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - int UE_id = find_UE_id(mod_idP, rntiP); + int UE_id = find_UE_id(mod_idP,rntiP); int pCC_id; if (UE_id == -1) { - LOG_W(MAC, "rrc_mac_remove_ue: UE %x not found\n", rntiP); - return 0; + LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP); + return 0; } - pCC_id = UE_PCCID(mod_idP, UE_id); + pCC_id = UE_PCCID(mod_idP,UE_id); - LOG_I(MAC, "Removing UE %d from Primary CC_id %d (rnti %x)\n", UE_id, - pCC_id, rntiP); - dump_ue_list(UE_list, 0); + LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP); + dump_ue_list(UE_list,0); UE_list->active[UE_id] = FALSE; UE_list->num_UEs--; - if (UE_list->head == UE_id) - UE_list->head = UE_list->next[UE_id]; - else - UE_list->next[prev(UE_list, UE_id, 0)] = UE_list->next[UE_id]; - if (UE_list->head_ul == UE_id) - UE_list->head_ul = UE_list->next_ul[UE_id]; - else - UE_list->next_ul[prev(UE_list, UE_id, 0)] = - UE_list->next_ul[UE_id]; + if (UE_list->head == UE_id) UE_list->head=UE_list->next[UE_id]; + else UE_list->next[prev(UE_list,UE_id,0)]=UE_list->next[UE_id]; + if (UE_list->head_ul == UE_id) UE_list->head_ul=UE_list->next_ul[UE_id]; + else UE_list->next_ul[prev(UE_list,UE_id,0)]=UE_list->next_ul[UE_id]; // clear all remaining pending transmissions - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2] = 0; - UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3] = 0; - - UE_list->UE_template[pCC_id][UE_id].ul_SR = 0; - UE_list->UE_template[pCC_id][UE_id].rnti = NOT_A_RNTI; - UE_list->UE_template[pCC_id][UE_id].ul_active = FALSE; - eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; - eNB_ulsch_info[mod_idP][pCC_id][UE_id].status = S_UL_NONE; - eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; - eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE; + /* UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2] = 0; + UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3] = 0; + + UE_list->UE_template[pCC_id][UE_id].ul_SR = 0; + UE_list->UE_template[pCC_id][UE_id].rnti = NOT_A_RNTI; + UE_list->UE_template[pCC_id][UE_id].ul_active = FALSE; + */ + memset (&UE_list->UE_template[pCC_id][UE_id],0,sizeof(UE_TEMPLATE)); + + UE_list->eNB_UE_stats[pCC_id][UE_id].total_rbs_used = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_rbs_used_retx = 0; + for ( j = 0; j < NB_RB_MAX; j++ ) { + UE_list->eNB_UE_stats[pCC_id][UE_id].num_pdu_tx[j] = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].num_bytes_tx[j] = 0; + } + UE_list->eNB_UE_stats[pCC_id][UE_id].num_retransmission = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_sdu_bytes = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_pdu_bytes = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_num_pdus = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_rbs_used_rx = 0; + for ( j = 0; j < NB_RB_MAX; j++ ) { + UE_list->eNB_UE_stats[pCC_id][UE_id].num_pdu_rx[j] = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].num_bytes_rx[j] = 0; + } + UE_list->eNB_UE_stats[pCC_id][UE_id].num_errors_rx = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_pdu_bytes_rx = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_num_pdus_rx = 0; + UE_list->eNB_UE_stats[pCC_id][UE_id].total_num_errors_rx = 0; + + eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; + eNB_ulsch_info[mod_idP][pCC_id][UE_id].status = S_UL_NONE; + eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; + eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE; + + eNB_ulsch_info[mod_idP][pCC_id][UE_id].serving_num = 0; + eNB_dlsch_info[mod_idP][pCC_id][UE_id].serving_num = 0; // check if this has an RA process active RA_t *ra; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index def57639f626de3327e668e74494cb84e7604dca..dbae220301dea309b4f085a89b521d5e287f6890 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -732,6 +732,8 @@ rx_sdu(const module_id_t enb_mod_idP, num_pdu_rx[rx_lcids[i]] += 1; UE_list->eNB_UE_stats[CC_idP][UE_id]. num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + //clear uplane_inactivity_timer + UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } else { /* rx_length[i] */ UE_list->eNB_UE_stats[CC_idP][UE_id]. num_errors_rx += 1; diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h index 50ea5634b93dd13ca57c40875e4fda4d9930e2a7..d0c8706ad6728ab8cbfae407c77a1a429671c493 100644 --- a/openair2/LAYER2/MAC/extern.h +++ b/openair2/LAYER2/MAC/extern.h @@ -101,4 +101,4 @@ extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1; extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2; extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E; -#endif //DEF_H +#endif //DEF_H diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index bbd6d6a36d84d365e6a63bc8b2222303a3a9bf02..46a8b005e4476d8fb81a3bcbe46e0a0e204b325d 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -426,6 +426,14 @@ void set_ue_dai(sub_frame_t subframeP, int UE_id, uint8_t CC_id, uint8_t tdd_config, UE_list_t * UE_list); +/** \brief First stage of PCH Scheduling. Gets a PCH SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs). +@param Mod_id Instance ID of eNB +@param frame Frame index +@param subframe Subframe number on which to act +@param paging_ue_index +*/ +void schedule_PCH(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP); + uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, unsigned char group_id); uint8_t UE_is_to_be_scheduled(module_id_t module_idP, int CC_id, diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index b362e8887a08066b969d160d7d86222cbff06e2e..894abeb100a5e5ca2fdccae21181661723ad89de 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -68,6 +68,8 @@ extern int otg_enabled; #endif +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; //----------------------------------------------------------------------------- /* @@ -948,6 +950,21 @@ pdcp_run ( AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); break; + case RRC_PCCH_DATA_REQ: + { + sdu_size_t sdu_buffer_sizeP; + sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size; + uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id; + uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index; + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP; + if (sdu_buffer_sizeP > 0) { + memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP); + } + //paging pdcp log + LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP); + } + break; + default: LOG_E(PDCP, "Received unexpected message %s\n", msg_name); break; @@ -1037,6 +1054,13 @@ pdcp_remove_UE( // check and remove SRBs first + for(int i = 0;i<NUMBER_OF_UE_MAX;i++){ + if(pdcp_eNB_UE_instance_to_rnti[i] == ctxt_pP->rnti){ + pdcp_eNB_UE_instance_to_rnti[i] = NOT_A_RNTI; + break; + } + } + for (srb_id=0; srb_id<2; srb_id++) { key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES); h_rc = hashtable_remove(pdcp_coll_p, key); @@ -1344,7 +1368,7 @@ rrc_pdcp_config_asn1_req ( for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) { pdrb_id_p = drb2release_list_pP->list.array[cnt]; drb_id = *pdrb_id_p; - key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_NO); + key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO); h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p); if (h_rc != HASH_TABLE_OK) { @@ -1472,7 +1496,17 @@ pdcp_config_req_asn1 ( if (ctxt_pP->enb_flag == ENB_FLAG_YES) { pdcp_pP->is_ue = FALSE; //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti; - pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti; +// pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti; + if( srb_flagP == SRB_FLAG_NO ) { + for(int i = 0;i<NUMBER_OF_UE_MAX;i++){ + if(pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] == NOT_A_RNTI){ + break; + } + pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % NUMBER_OF_UE_MAX; + } + pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti; + pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % NUMBER_OF_UE_MAX; + } //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % NUMBER_OF_UE_MAX; } else { pdcp_pP->is_ue = TRUE; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index e65bbf1db06880384dd925c95b4807f141177937..37ff231198b7c6d35336fba8a2f46e1a98823e63 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -589,7 +589,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) if (ctxt_cpy.enb_flag) { ctxt.module_id = 0; rab_id = pdcp_read_header_g.rb_id % maxDRB; - ctxt.rnti = pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index]; + ctxt.rnti = pdcp_eNB_UE_instance_to_rnti[pdcp_read_header_g.rb_id / maxDRB]; } else { ctxt.module_id = 0; rab_id = pdcp_read_header_g.rb_id % maxDRB; diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c index faf7763e4fae992fa6e175ca2c4e69ea1d70c796..15dc90f175a183dab9d247afeb081aad21db975a 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c @@ -125,6 +125,7 @@ rlc_tm_cleanup ( // RX SIDE if ((rlcP->output_sdu_in_construction)) { free_mem_block (rlcP->output_sdu_in_construction, __func__); + rlcP->output_sdu_in_construction = NULL; } memset(rlcP, 0, sizeof(rlc_tm_entity_t)); diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c index 423aca55e9242f6db9ed647b6327cfbbed7c9b7f..4e2723a8f476489bb16fe1eb677f6e0ed4550ab2 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c @@ -343,6 +343,7 @@ rlc_um_cleanup ( if ((rlc_pP->output_sdu_in_construction)) { free_mem_block (rlc_pP->output_sdu_in_construction, __func__); + rlc_pP->output_sdu_in_construction = NULL; } if (rlc_pP->dar_buffer) { diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index 7801279be2058fc2fc6f653084f70ef4b4c52d0d..a5a8135feda8037c2b3131c8ceedd63a1585d876 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -131,6 +131,12 @@ int dump_eNB_l2_stats(char *buffer, int length) eNB->eNB_stats[CC_id].bcch_buffer, eNB->eNB_stats[CC_id].total_bcch_buffer, eNB->eNB_stats[CC_id].bcch_mcs); + + len += sprintf(&buffer[len],"PCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n", + eNB->eNB_stats[CC_id].total_num_pcch_pdu, + eNB->eNB_stats[CC_id].pcch_buffer, + eNB->eNB_stats[CC_id].total_pcch_buffer, + eNB->eNB_stats[CC_id].pcch_mcs); eNB->eNB_stats[CC_id].dlsch_bitrate=((eNB->eNB_stats[CC_id].dlsch_bytes_tx*8)/((eNB->frame + 1)*10)); eNB->eNB_stats[CC_id].total_dlsch_pdus_tx+=eNB->eNB_stats[CC_id].dlsch_pdus_tx; diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c index 3077b9ba80220d757f0f3cf091047b8b5c82be05..47adc80f959389eaa6a8acbc64e994add6867563 100644 --- a/openair2/RRC/LITE/L2_interface.c +++ b/openair2/RRC/LITE/L2_interface.c @@ -249,6 +249,44 @@ mac_rrc_data_req( return (Sdu_size); } + if( (Srb_id & RAB_OFFSET ) == PCCH) { + LOG_T(RRC,"[eNB %d] Frame %d PCCH request (Srb_id %d)\n",Mod_idP,frameP, Srb_id); + + // check if data is there for MAC + if(RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area] > 0) { //Fill buffer + LOG_D(RRC,"[eNB %d] PCCH (%p) has %d bytes\n",Mod_idP,&RC.rrc[Mod_idP]->carrier[CC_id].paging[mbsfn_sync_area], + RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area]); + +#if 0 //defined(ENABLE_ITTI) + { + MessageDef *message_p; + int pcch_size = RC.rrc[Mod_idP]->arrier[CC_id].sizeof_paging[mbsfn_sync_area]; + int sdu_size = sizeof(RRC_MAC_PCCH_DATA_REQ (message_p).sdu); + + if (pcch_size > sdu_size) { + LOG_E(RRC, "SDU larger than PCCH SDU buffer size (%d, %d)", pcch_size, sdu_size); + pcch_size = sdu_size; + } + + message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_MAC_PCCH_DATA_REQ); + RRC_MAC_PCCH_DATA_REQ (message_p).frame = frameP; + RRC_MAC_PCCH_DATA_REQ (message_p).sdu_size = pcch_size; + memset (RRC_MAC_PCCH_DATA_REQ (message_p).sdu, 0, PCCH_SDU_SIZE); + memcpy (RRC_MAC_PCCH_DATA_REQ (message_p).sdu, RC.rrc[Mod_idP]->carrier[CC_id].paging[mbsfn_sync_area], pcch_size); + RRC_MAC_PCCH_DATA_REQ (message_p).enb_index = eNB_index; + + itti_send_msg_to_task (TASK_MAC_ENB, ENB_MODULE_ID_TO_INSTANCE(Mod_idP), message_p); + } +#endif + + memcpy(buffer_pP, RC.rrc[Mod_idP]->carrier[CC_id].paging[mbsfn_sync_area], RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area]); + Sdu_size = RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area]; + RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area] = 0; + } + + return (Sdu_size); + } + #if defined(Rel10) || defined(Rel14) if((Srb_id & RAB_OFFSET) == MCCH) { @@ -770,12 +808,34 @@ void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP, if (ue_context_p != NULL) { LOG_I(RRC,"Frame %d, Subframe %d: UE %x UL failure, activating timer\n",frameP,subframeP,rntiP); - ue_context_p->ue_context.ul_failure_timer=1; + if(ue_context_p->ue_context.ul_failure_timer == 0) + ue_context_p->ue_context.ul_failure_timer=1; } else { LOG_W(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP); } - rrc_mac_remove_ue(Mod_instP,rntiP); +// rrc_mac_remove_ue(Mod_instP,rntiP); +} + +void mac_eNB_rrc_uplane_failure(const module_id_t Mod_instP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP) +{ + struct rrc_eNB_ue_context_s* ue_context_p = NULL; + ue_context_p = rrc_eNB_get_ue_context( + RC.rrc[Mod_instP], + rntiP); + if (ue_context_p != NULL) { + LOG_I(RRC,"Frame %d, Subframe %d: UE %x U-Plane failure, activating timer\n",frameP,subframeP,rntiP); + + if(ue_context_p->ue_context.ul_failure_timer == 0) + ue_context_p->ue_context.ul_failure_timer=19999; + } + else { + LOG_W(RRC,"Frame %d, Subframe %d: U-Plane failure: UE %x unknown \n",frameP,subframeP,rntiP); + } } void mac_eNB_rrc_ul_in_sync(const module_id_t Mod_instP, diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c index a05b27ddc361f93e62c6bb6bac70803b662ac152..db5ce5db9537e088340448ada83a135a8048894b 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c @@ -54,6 +54,8 @@ #include "UL-DCCH-Message.h" #include "DL-CCCH-Message.h" #include "DL-DCCH-Message.h" +#include "PCCH-Message.h" +#include "openair3/UTILS/conversions.h" #include "EstablishmentCause.h" #include "RRCConnectionSetup.h" #include "SRB-ToAddModList.h" @@ -89,6 +91,7 @@ #endif #include "common/ran_context.h" +#include "secu_defs.h" //#include "PHY/defs.h" #ifndef USER_MODE @@ -230,7 +233,7 @@ uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich AssertFatal(phich_Resource <= PHICH_Config__phich_Resource_two,"Illegal phich_Resource\n"); mib->message.phich_Config.phich_Resource = phich_Resource; - AssertFatal(phich_Resource <= PHICH_Config__phich_Duration_extended,"Illegal phich_Duration\n"); + AssertFatal(phich_duration <= PHICH_Config__phich_Duration_extended,"Illegal phich_Duration\n"); mib->message.phich_Config.phich_Duration = phich_duration; LOG_I(RRC,"[MIB] systemBandwidth %x, phich_duration %x, phich_resource %x,sfn %x\n", (uint32_t)mib->message.dl_Bandwidth, @@ -1964,6 +1967,214 @@ do_RRCConnectionReconfiguration( return((enc_rval.encoded+7)/8); } +//------------------------------------------------------------------------------ +uint8_t +do_RRCConnectionReestablishment( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + int CC_id, + uint8_t* const buffer, + const uint8_t transmission_mode, + const uint8_t Transaction_id, + SRB_ToAddModList_t **SRB_configList, + struct PhysicalConfigDedicated **physicalConfigDedicated) +{ + asn_enc_rval_t enc_rval; + + long* logicalchannelgroup = NULL; + struct SRB_ToAddMod* SRB1_config = NULL; + struct SRB_ToAddMod* SRB2_config = NULL; + struct SRB_ToAddMod__rlc_Config* SRB1_rlc_config = NULL; + struct SRB_ToAddMod__logicalChannelConfig* SRB1_lchan_config = NULL; + struct LogicalChannelConfig__ul_SpecificParameters* SRB1_ul_SpecificParameters = NULL; + eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id]; + +#ifdef CBA + struct PUSCH_CBAConfigDedicated_vlola* pusch_CBAConfigDedicated_vlola = NULL; + long* betaOffset_CBA_Index = NULL; + long* cShift_CBA = NULL; +#endif + PhysicalConfigDedicated_t* physicalConfigDedicated2 = NULL; + + DL_CCCH_Message_t dl_ccch_msg; + + RRCConnectionReestablishment_t* rrcConnectionReestablishment = NULL; + + int i = 0; + SRB_ToAddModList_t **SRB_configList2 = NULL; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id]; + if (*SRB_configList2) { + free(*SRB_configList2); + } + *SRB_configList2 = CALLOC(1, sizeof(SRB_ToAddModList_t)); + + memset((void *)&dl_ccch_msg, 0, sizeof(DL_CCCH_Message_t)); + dl_ccch_msg.message.present = DL_CCCH_MessageType_PR_c1; + dl_ccch_msg.message.choice.c1.present = DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment; + rrcConnectionReestablishment = &dl_ccch_msg.message.choice.c1.choice.rrcConnectionReestablishment; + + // RRCConnectionReestablishment + // Configure SRB1 + + + // get old configuration of SRB2 + if (*SRB_configList != NULL) { + for (i = 0; (i < (*SRB_configList)->list.count) && (i < 3); i++) { + LOG_D(RRC, "(*SRB_configList)->list.array[%d]->srb_Identity=%ld\n", + i, (*SRB_configList)->list.array[i]->srb_Identity); + if ((*SRB_configList)->list.array[i]->srb_Identity == 2 ){ + SRB2_config = (*SRB_configList)->list.array[i]; + } else if ((*SRB_configList)->list.array[i]->srb_Identity == 1 ){ + SRB1_config = (*SRB_configList)->list.array[i]; + } + } + } + + if (SRB1_config == NULL) { + // default SRB1 configuration + LOG_W(RRC,"SRB1 configuration does not exist in SRB configuration list, use default\n"); + /// SRB1 + SRB1_config = CALLOC(1, sizeof(*SRB1_config)); + + SRB1_config->srb_Identity = 1; + SRB1_rlc_config = CALLOC(1, sizeof(*SRB1_rlc_config)); + SRB1_config->rlc_Config = SRB1_rlc_config; + + SRB1_rlc_config->present = SRB_ToAddMod__rlc_Config_PR_explicitValue; + SRB1_rlc_config->choice.explicitValue.present=RLC_Config_PR_am; + #if defined(ENABLE_ITTI) + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = rrc->srb1_timer_poll_retransmit; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = rrc->srb1_poll_pdu; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = rrc->srb1_poll_byte; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = rrc->srb1_max_retx_threshold; + SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = rrc->srb1_timer_reordering; + SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = rrc->srb1_timer_status_prohibit; + #else + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms20;; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = PollPDU_p4;; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = PollByte_kBinfinity; + SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t8; + SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = T_Reordering_ms35; + SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = T_StatusProhibit_ms0; + #endif + + SRB1_lchan_config = CALLOC(1, sizeof(*SRB1_lchan_config)); + SRB1_config->logicalChannelConfig = SRB1_lchan_config; + + SRB1_lchan_config->present = SRB_ToAddMod__logicalChannelConfig_PR_explicitValue; + SRB1_ul_SpecificParameters = CALLOC(1, sizeof(*SRB1_ul_SpecificParameters)); + + SRB1_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB1_ul_SpecificParameters; + SRB1_ul_SpecificParameters->priority = 1; + + //assign_enum(&SRB1_ul_SpecificParameters->prioritisedBitRate,LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity); + SRB1_ul_SpecificParameters->prioritisedBitRate=LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + + //assign_enum(&SRB1_ul_SpecificParameters->bucketSizeDuration,LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50); + SRB1_ul_SpecificParameters->bucketSizeDuration=LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + + logicalchannelgroup = CALLOC(1, sizeof(long)); + *logicalchannelgroup = 0; + SRB1_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; + } + + if (SRB2_config == NULL) { + LOG_W(RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } else { + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + } + + if (*SRB_configList) { + free(*SRB_configList); + } + + *SRB_configList = CALLOC(1, sizeof(SRB_ToAddModList_t)); + + ASN_SEQUENCE_ADD(&(*SRB_configList)->list,SRB1_config); + + physicalConfigDedicated2 = *physicalConfigDedicated; + + rrcConnectionReestablishment->rrc_TransactionIdentifier = Transaction_id; + rrcConnectionReestablishment->criticalExtensions.present = RRCConnectionReestablishment__criticalExtensions_PR_c1; + rrcConnectionReestablishment->criticalExtensions.choice.c1.present = RRCConnectionReestablishment__criticalExtensions__c1_PR_rrcConnectionReestablishment_r8; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.srb_ToAddModList = *SRB_configList; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.drb_ToAddModList = NULL; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.drb_ToReleaseList = NULL; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.sps_Config = NULL; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.physicalConfigDedicated = physicalConfigDedicated2; + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.radioResourceConfigDedicated.mac_MainConfig = NULL; + + uint8_t KeNB_star[32] = { 0 }; + uint16_t pci = rrc->carrier[CC_id].physCellId; + uint32_t earfcn_dl = (uint32_t)freq_to_arfcn10(RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + rrc->carrier[CC_id].dl_CarrierFreq); + bool is_rel8_only = true; + if (earfcn_dl > 65535) { + is_rel8_only = false; + } + + LOG_D(RRC, "pci=%d, eutra_band=%d, downlink_frequency=%d, earfcn_dl=%u, is_rel8_only=%s\n", + pci, + RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + rrc->carrier[CC_id].dl_CarrierFreq, + earfcn_dl, + is_rel8_only == true ? "true": "false"); +#if defined(ENABLE_SECURITY) + if (ue_context_pP->ue_context.nh_ncc >= 0) { + derive_keNB_star(ue_context_pP->ue_context.nh, pci, earfcn_dl, is_rel8_only, KeNB_star); + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.nextHopChainingCount = ue_context_pP->ue_context.nh_ncc; + } else { // first HO + derive_keNB_star (ue_context_pP->ue_context.kenb, pci, earfcn_dl, is_rel8_only, KeNB_star); + // LG: really 1 + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.nextHopChainingCount = 0; + } + + // copy KeNB_star to ue_context_pP->ue_context.kenb + memcpy (ue_context_pP->ue_context.kenb, KeNB_star, 32); + ue_context_pP->ue_context.kenb_ncc = 0; +#else + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.nextHopChainingCount = 0; +#endif + + rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.nonCriticalExtension = NULL; + +#ifdef XER_PRINT + xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg); +#endif + enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message, + (void*)&dl_ccch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + +#if defined(ENABLE_ITTI) +# if !defined(DISABLE_XER_SPRINT) + { + char message_string[20000]; + size_t message_string_size; + + if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message, (void *) &dl_ccch_msg)) > 0) { + MessageDef *msg_p; + + msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText)); + msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size; + memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size); + + itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p); + } + } +# endif +#endif + +#ifdef USER_MODE + LOG_D(RRC,"RRCConnectionReestablishment Encoded %zd bits (%zd bytes)\n", + enc_rval.encoded,(enc_rval.encoded+7)/8); +#endif + + return((enc_rval.encoded+7)/8); +} + //------------------------------------------------------------------------------ uint8_t do_RRCConnectionReestablishmentReject( @@ -2451,6 +2662,73 @@ uint8_t do_DLInformationTransfer(uint8_t Mod_id, uint8_t **buffer, uint8_t trans return encoded; } +uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_paging_identity, cn_domain_t cn_domain) +{ + LOG_D(RRC, "[eNB %d] do_Paging start\n", Mod_id); + asn_enc_rval_t enc_rval; + + PCCH_Message_t pcch_msg; + PagingRecord_t *paging_record_p; + int j; + + pcch_msg.message.present = PCCH_MessageType_PR_c1; + pcch_msg.message.choice.c1.present = PCCH_MessageType__c1_PR_paging; + + pcch_msg.message.choice.c1.choice.paging.pagingRecordList = CALLOC(1,sizeof(*pcch_msg.message.choice.c1.choice.paging.pagingRecordList)); + + pcch_msg.message.choice.c1.choice.paging.systemInfoModification = NULL; + pcch_msg.message.choice.c1.choice.paging.etws_Indication = NULL; + pcch_msg.message.choice.c1.choice.paging.nonCriticalExtension = NULL; + + asn_set_empty(&pcch_msg.message.choice.c1.choice.paging.pagingRecordList->list); + pcch_msg.message.choice.c1.choice.paging.pagingRecordList->list.count = 0; + + if ((paging_record_p = calloc(1, sizeof(PagingRecord_t))) == NULL) { + /* Possible error on calloc */ + return (-1); + } + + memset(paging_record_p, 0, sizeof(PagingRecord_t)); + + /* convert ue_paging_identity_t to PagingUE_Identity_t */ + if (ue_paging_identity.presenceMask == UE_PAGING_IDENTITY_s_tmsi) { + paging_record_p->ue_Identity.present = PagingUE_Identity_PR_s_TMSI; + MME_CODE_TO_OCTET_STRING(ue_paging_identity.choice.s_tmsi.mme_code, + &paging_record_p->ue_Identity.choice.s_TMSI.mmec); + paging_record_p->ue_Identity.choice.s_TMSI.mmec.bits_unused = 0; + M_TMSI_TO_OCTET_STRING(ue_paging_identity.choice.s_tmsi.m_tmsi, + &paging_record_p->ue_Identity.choice.s_TMSI.m_TMSI); + paging_record_p->ue_Identity.choice.s_TMSI.m_TMSI.bits_unused = 0; + } else if (ue_paging_identity.presenceMask == UE_PAGING_IDENTITY_imsi) { + IMSI_Digit_t imsi_digit[21]; + for (j = 0; j< ue_paging_identity.choice.imsi.length; j++) { /* IMSI size */ + imsi_digit[j] = (IMSI_Digit_t)ue_paging_identity.choice.imsi.buffer[j]; + ASN_SEQUENCE_ADD(&paging_record_p->ue_Identity.choice.imsi.list, &imsi_digit[j]); + } + } + + /* set cn_domain */ + if (cn_domain == CN_DOMAIN_PS) { + paging_record_p->cn_Domain = PagingRecord__cn_Domain_ps; + } else { + paging_record_p->cn_Domain = PagingRecord__cn_Domain_cs; + } + /* add to list */ + ASN_SEQUENCE_ADD(&pcch_msg.message.choice.c1.choice.paging.pagingRecordList->list, paging_record_p); + LOG_D(RRC, "[eNB %d] do_Paging paging_record: cn_Domain %ld, ue_paging_identity.presenceMask %d, PagingRecordList.count %d\n", + Mod_id, paging_record_p->cn_Domain, ue_paging_identity.presenceMask, pcch_msg.message.choice.c1.choice.paging.pagingRecordList->list.count); + + enc_rval = uper_encode_to_buffer(&asn_DEF_PCCH_Message, (void*)&pcch_msg, buffer, RRC_BUF_SIZE); + + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); +#ifdef XER_PRINT + xer_fprint(stdout, &asn_DEF_PCCH_Message, (void*)&pcch_msg); +#endif + + return((enc_rval.encoded+7)/8); +} + uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer) { ssize_t encoded; diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h index 6241e2963fbacb6538a115a1707aa3af530856d1..270d9bc58fea6c3b3764bca0770893c9b72197ee 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h @@ -195,6 +195,28 @@ do_RRCConnectionReconfiguration( , SCellToAddMod_r10_t *SCell_config #endif ); +/** +\brief Generate an RRCConnectionReestablishment DL-CCCH-Message (eNB). This routine configures SRB_ToAddMod (SRB1/SRB2) and +PhysicalConfigDedicated IEs. The latter does not enable periodic CQI reporting (PUCCH format 2/2a/2b) or SRS. +@param ctxt_pP Running context +@param ue_context_pP UE context +@param CC_id Component Carrier ID +@param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU +@param transmission_mode Transmission mode for UE (1-9) +@param Transaction_id Transaction_ID for this message +@param SRB_configList Pointer (returned) to SRB1_config/SRB2_config(later) IEs for this UE +@param physicalConfigDedicated Pointer (returned) to PhysicalConfigDedicated IE for this UE +@returns Size of encoded bit stream in bytes*/ +uint8_t +do_RRCConnectionReestablishment( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + int CC_id, + uint8_t* const buffer, + const uint8_t transmission_mode, + const uint8_t Transaction_id, + SRB_ToAddModList_t **SRB_configList, + struct PhysicalConfigDedicated **physicalConfigDedicated); /** \brief Generate an RRCConnectionReestablishmentReject DL-CCCH-Message (eNB). @@ -249,6 +271,8 @@ uint8_t do_MeasurementReport(uint8_t Mod_id, uint8_t *buffer,int measid,int phy_ uint8_t do_DLInformationTransfer(uint8_t Mod_id, uint8_t **buffer, uint8_t transaction_id, uint32_t pdu_length, uint8_t *pdu_buffer); +uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_paging_identity, cn_domain_t cn_domain); + uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer); OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer); diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h index 9d7f7fdf2d169d4104de8c5ff5662d51aa2bfc85..0a661849988efbea794cc129772db7074a56fb01 100644 --- a/openair2/RRC/LITE/defs.h +++ b/openair2/RRC/LITE/defs.h @@ -296,12 +296,15 @@ typedef enum e_rab_satus_e { E_RAB_STATUS_DONE, // from the eNB perspective E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE E_RAB_STATUS_FAILED, + E_RAB_STATUS_TORELEASE // to release DRB between eNB and UE } e_rab_status_t; typedef struct e_rab_param_s { e_rab_t param; uint8_t status; uint8_t xid; // transaction_id + s1ap_Cause_t cause; + uint8_t cause_value; } __attribute__ ((__packed__)) e_rab_param_t; #endif @@ -379,6 +382,7 @@ typedef struct eNB_RRC_UE_s { SRB_ToAddModList_t* SRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; DRB_ToAddModList_t* DRB_configList; DRB_ToAddModList_t* DRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; + DRB_ToReleaseList_t* DRB_Release_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; uint8_t DRB_active[8]; struct PhysicalConfigDedicated* physicalConfigDedicated; struct SPS_Config* sps_Config; @@ -398,6 +402,9 @@ typedef struct eNB_RRC_UE_s { #if defined(ENABLE_SECURITY) /* KeNB as derived from KASME received from EPC */ uint8_t kenb[32]; + int8_t kenb_ncc; + uint8_t nh[32]; + int8_t nh_ncc; #endif /* Used integrity/ciphering algorithms */ CipheringAlgorithm_r12_t ciphering_algorithm; @@ -427,9 +434,15 @@ typedef struct eNB_RRC_UE_s { uint8_t setup_e_rabs; /* Number of e_rab to be setup in the list */ uint8_t nb_of_e_rabs; + /* Number of e_rab to be modified in the list */ + uint8_t nb_of_modify_e_rabs; + uint8_t nb_of_failed_e_rabs; + e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; /* list of e_rab to be setup by RRC layers */ e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; - + //release e_rabs + uint8_t nb_release_of_e_rabs; + e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB]; // LG: For GTPV1 TUNNELS uint32_t enb_gtp_teid[S1AP_MAX_E_RAB]; transport_layer_addr_t enb_gtp_addrs[S1AP_MAX_E_RAB]; @@ -438,6 +451,13 @@ typedef struct eNB_RRC_UE_s { uint32_t ul_failure_timer; uint32_t ue_release_timer; uint32_t ue_release_timer_thres; + uint32_t ue_release_timer_s1; + uint32_t ue_release_timer_thres_s1; + uint32_t ue_release_timer_rrc; + uint32_t ue_release_timer_thres_rrc; + uint32_t ue_reestablishment_timer; + uint32_t ue_reestablishment_timer_thres; + uint8_t e_rab_release_command_flag; } eNB_RRC_UE_t; typedef uid_t ue_uid_t; @@ -501,6 +521,8 @@ typedef struct { #endif SRB_INFO SI; SRB_INFO Srb0; + uint8_t *paging[NUMBER_OF_UE_MAX]; + uint32_t sizeof_paging[NUMBER_OF_UE_MAX]; } rrc_eNB_carrier_data_t; typedef struct eNB_RRC_INST_s { @@ -628,6 +650,8 @@ typedef struct UE_RRC_INST_s { #if defined(ENABLE_SECURITY) /* KeNB as computed from parameters within USIM card */ uint8_t kenb[32]; + uint8_t nh[32]; + int8_t nh_ncc; #endif /* Used integrity/ciphering algorithms */ @@ -635,6 +659,14 @@ typedef struct UE_RRC_INST_s { e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; } UE_RRC_INST; +typedef struct UE_PF_PO_s { + boolean_t enable_flag; /* flag indicate whether current object is used */ + uint16_t ue_index_value; /* UE index value */ + uint8_t PF_min; /* minimal value of Paging Frame (PF) */ + uint8_t PO; /* Paging Occasion (PO) */ + uint32_t T; /* DRX cycle */ +} UE_PF_PO_t; + #include "proto.h" #endif diff --git a/openair2/RRC/LITE/extern.h b/openair2/RRC/LITE/extern.h index 77dcaac5e69492b9895d87434850adb42c923aec..71d8c9d0dcf8780dd91542ee1b5019ae12aa38d6 100644 --- a/openair2/RRC/LITE/extern.h +++ b/openair2/RRC/LITE/extern.h @@ -77,6 +77,11 @@ extern uint32_t timeToTrigger_ms[16]; extern float RSRP_meas_mapping[100]; extern float RSRQ_meas_mapping[33]; +extern UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +extern pthread_mutex_t ue_pf_po_mutex; + +extern uint16_t reestablish_rnti_map[NUMBER_OF_UE_MAX][2]; + #endif diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h index b3d5beb2922f26316695a32c742a13eda1647908..3e00bc9769ea2b4edd8903aebde5eaa5aaba70fb 100644 --- a/openair2/RRC/LITE/proto.h +++ b/openair2/RRC/LITE/proto.h @@ -254,6 +254,8 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration( const uint8_t ho_state ); +int freq_to_arfcn10(int band, unsigned long freq); + void rrc_eNB_generate_dedeicatedRRCConnectionReconfiguration( const protocol_ctxt_t* const ctxt_pP, @@ -261,6 +263,18 @@ rrc_eNB_generate_dedeicatedRRCConnectionReconfiguration( const uint8_t ho_state ); +/**\brief release Data Radio Bearer between ENB and UE + \param ctxt_pP Running context + \param ue_context_pP UE context of UE receiving the message*/ +void +rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t* nas_buffer +); + void rrc_eNB_reconfigure_DRBs (const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* ue_context_pP); @@ -324,6 +338,12 @@ void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP, const sub_frame_t subframeP, const rnti_t rnti); +void mac_eNB_rrc_uplane_failure(const module_id_t Mod_instP, + const int CC_id, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rnti); + void mac_eNB_rrc_ul_in_sync(const module_id_t Mod_instP, const int CC_id, const frame_t frameP, diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index 65e1a25b1708e404cd07508c2754ffe3a2669085..4bccf7d6beebef71be5c5b9430112639a88b99fd 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -333,26 +333,58 @@ rrc_rx_tx( RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) { if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { - LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n", + LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/8\n", ue_context_p->ue_context.rnti, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.ul_failure_timer); } else { - LOG_I(RRC,"UE rnti %x failure timer %d/20000\n", + LOG_I(RRC,"UE rnti %x failure timer %d/8\n", ue_context_p->ue_context.rnti, ue_context_p->ue_context.ul_failure_timer); } } if (ue_context_p->ue_context.ul_failure_timer>0) { ue_context_p->ue_context.ul_failure_timer++; - if (ue_context_p->ue_context.ul_failure_timer >= 20000) { + if (ue_context_p->ue_context.ul_failure_timer >= 8) { // remove UE after 20 seconds after MAC has indicated UL failure LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti); ue_to_be_removed = ue_context_p; break; } } + if (ue_context_p->ue_context.ue_release_timer_s1>0) { + ue_context_p->ue_context.ue_release_timer_s1++; + if (ue_context_p->ue_context.ue_release_timer_s1 >= + ue_context_p->ue_context.ue_release_timer_thres_s1) { + LOG_I(RRC,"Removing UE %x instance Because of UE_CONTEXT_RELEASE_COMMAND not received after %d ms from sending request\n", + ue_context_p->ue_context.rnti, ue_context_p->ue_context.ue_release_timer_thres_s1); + ue_to_be_removed = ue_context_p; + break; + } + } + + if (ue_context_p->ue_context.ue_release_timer_rrc>0) { + ue_context_p->ue_context.ue_release_timer_rrc++; + if (ue_context_p->ue_context.ue_release_timer_rrc >= + ue_context_p->ue_context.ue_release_timer_thres_rrc) { + LOG_I(RRC,"Removing UE %x instance After UE_CONTEXT_RELEASE_Complete\n", ue_context_p->ue_context.rnti); + ue_to_be_removed = ue_context_p; + break; + } + } + + if (ue_context_p->ue_context.ue_reestablishment_timer>0) { + ue_context_p->ue_context.ue_reestablishment_timer++; + if (ue_context_p->ue_context.ue_reestablishment_timer >= + ue_context_p->ue_context.ue_reestablishment_timer_thres) { + LOG_I(RRC,"UE %d reestablishment_timer max\n",ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ul_failure_timer = 20000; + ue_to_be_removed = ue_context_p; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + break; + } + } if (ue_context_p->ue_context.ue_release_timer>0) { ue_context_p->ue_context.ue_release_timer++; if (ue_context_p->ue_context.ue_release_timer >= @@ -363,9 +395,18 @@ rrc_rx_tx( } } } - if (ue_to_be_removed) + if (ue_to_be_removed) { + if(ue_to_be_removed->ue_context.ul_failure_timer >= 8) { + ue_to_be_removed->ue_context.ue_release_timer_s1 = 1; + ue_to_be_removed->ue_context.ue_release_timer_thres_s1 = 100; + ue_to_be_removed->ue_context.ue_release_timer = 0; + ue_to_be_removed->ue_context.ue_reestablishment_timer = 0; + } rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed); - + if(ue_to_be_removed->ue_context.ul_failure_timer >= 8){ + ue_to_be_removed->ue_context.ul_failure_timer = 0; + } + } #ifdef RRC_LOCALIZATION /* for the localization, only primary CC_id might be relevant*/ diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index ad9b63c798d563126f241fa117673771c118ae26..c9ef58129b92b4580a6479622510b0b55085172e 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -84,6 +84,7 @@ #endif #include "pdcp.h" +#include "gtpv1u_eNB_task.h" #if defined(ENABLE_ITTI) # include "intertask_interface.h" @@ -575,6 +576,7 @@ rrc_eNB_get_next_free_ue_context( ctxt_pP->rnti); if (ue_context_p == NULL) { +#if 0 RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { if (ue_context_p->ue_context.random_ue_identity == ue_identityP) { LOG_D(RRC, @@ -585,6 +587,7 @@ rrc_eNB_get_next_free_ue_context( return NULL; } } +#endif ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[ctxt_pP->module_id]); if (ue_context_p == NULL) { @@ -683,11 +686,29 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.SRB_configList = NULL; } + for(i = 0;i < RRC_TRANSACTION_IDENTIFIER_NUMBER;i++){ + if (ue_context_pP->ue_context.SRB_configList2[i]) { + free(ue_context_pP->ue_context.SRB_configList2[i]); + ue_context_pP->ue_context.SRB_configList2[i] = NULL; + } + } + if (ue_context_pP->ue_context.DRB_configList) { ASN_STRUCT_FREE(asn_DEF_DRB_ToAddModList, ue_context_pP->ue_context.DRB_configList); ue_context_pP->ue_context.DRB_configList = NULL; } + for(i = 0;i < RRC_TRANSACTION_IDENTIFIER_NUMBER;i++){ + if (ue_context_pP->ue_context.DRB_configList2[i]) { + free(ue_context_pP->ue_context.DRB_configList2[i]); + ue_context_pP->ue_context.DRB_configList2[i] = NULL; + } + if (ue_context_pP->ue_context.DRB_Release_configList2[i]) { + free(ue_context_pP->ue_context.DRB_Release_configList2[i]); + ue_context_pP->ue_context.DRB_Release_configList2[i] = NULL; + } + } + memset(ue_context_pP->ue_context.DRB_active, 0, sizeof(ue_context_pP->ue_context.DRB_active)); if (ue_context_pP->ue_context.physicalConfigDedicated) { @@ -724,10 +745,14 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.mac_MainConfig = NULL; } - if (ue_context_pP->ue_context.measGapConfig) { +/* if (ue_context_pP->ue_context.measGapConfig) { ASN_STRUCT_FREE(asn_DEF_MeasGapConfig, ue_context_pP->ue_context.measGapConfig); ue_context_pP->ue_context.measGapConfig = NULL; - } + }*/ + if (ue_context_pP->ue_context.handover_info) { + ASN_STRUCT_FREE(asn_DEF_Handover, ue_context_pP->ue_context.handover_info); + ue_context_pP->ue_context.handover_info = NULL; + } //SRB_INFO SI; //SRB_INFO Srb0; @@ -782,7 +807,11 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* (void)ue_module_id; #endif rnti_t rnti = ue_context_pP->ue_context.rnti; - + int i, j , CC_id, pdu_number; + LTE_eNB_ULSCH_t *ulsch = NULL; + nfapi_ul_config_request_body_t *ul_req_tmp = NULL; + PHY_VARS_eNB *eNB_PHY = NULL; + eNB_MAC_INST *eNB_MAC = RC.mac[enb_mod_idP]; AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB inst invalid (%d/%d) for UE %x!", enb_mod_idP, NB_eNB_INST, rnti); /* ue_context_p = rrc_eNB_get_ue_context( @@ -795,6 +824,8 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* LOG_W(RRC, "[eNB %d] Removing UE RNTI %x\n", enb_mod_idP, rnti); #if defined(ENABLE_USE_MME) + if( ue_context_pP->ue_context.ul_failure_timer >= 8 ) { + LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ RNTI %x\n", enb_mod_idP, rnti); rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered) * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before @@ -802,6 +833,8 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* * in order to allow the UE to perform the NAS recovery * procedure, see TS 23.401 [17]. */ + return; + } #else #if defined(OAI_EMU) AssertFatal(ue_context_pP->local_uid < NUMBER_OF_UE_MAX, "local_uid invalid (%d<%d) for UE %x!", ue_context_pP->local_uid, NUMBER_OF_UE_MAX, rnti); @@ -811,7 +844,33 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI; #endif #endif + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + eNB_PHY = RC.eNB[enb_mod_idP][CC_id]; + for (i=0; i<NUMBER_OF_UE_MAX; i++) { + ulsch = eNB_PHY->ulsch[i]; + if((ulsch != NULL) && (ulsch->rnti == rnti)){ + LOG_I(RRC, "clean_eNb_ulsch UE %x \n", rnti); + clean_eNb_ulsch(ulsch); + break; + } + } + for(j = 0; j < 10; j++){ + ul_req_tmp = &eNB_MAC->UL_req_tmp[CC_id][j].ul_config_request_body; + if(ul_req_tmp){ + pdu_number = ul_req_tmp->number_of_pdus; + for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){ + if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){ + LOG_I(RRC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number); + if(pdu_index < pdu_number -1){ + memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t)); + } + ul_req_tmp->number_of_pdus--; + } + } + } + } + } rrc_mac_remove_ue(enb_mod_idP,rnti); rrc_rlc_remove_ue(&ctxt); pdcp_remove_UE(&ctxt); @@ -1027,216 +1086,968 @@ rrc_eNB_generate_RRCConnectionReject( //----------------------------------------------------------------------------- void -rrc_eNB_generate_RRCConnectionReestablishmentReject( - const protocol_ctxt_t* const ctxt_pP, +rrc_eNB_generate_RRCConnectionReestablishment( + const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, - const int CC_id + const int CC_id ) //----------------------------------------------------------------------------- { -#ifdef RRC_MSG_PRINT + LogicalChannelConfig_t *SRB1_logicalChannelConfig; + SRB_ToAddModList_t **SRB_configList; + SRB_ToAddMod_t *SRB1_config; int cnt; -#endif - T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T(T_ENB_RRC_CONNECTION_REESTABLISHMENT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + SRB_configList = &ue_context_pP->ue_context.SRB_configList; RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size = - do_RRCConnectionReestablishmentReject(ctxt_pP->module_id, - (uint8_t*) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload); + do_RRCConnectionReestablishment(ctxt_pP, + ue_context_pP, + CC_id, + (uint8_t*) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload, + (uint8_t) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].p_eNB, //at this point we do not have the UE capability information, so it can only be TM1 or TM2 + rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), + SRB_configList, + &ue_context_pP->ue_context.physicalConfigDedicated); #ifdef RRC_MSG_PRINT - LOG_F(RRC,"[MSG] RRCConnectionReestablishmentReject\n"); + LOG_F(RRC,"[MSG] RRCConnectionReestablishment\n"); for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { - LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->Srb0.Tx_buffer.Payload)[cnt]); + LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload)[cnt]); } LOG_F(RRC,"\n"); #endif - MSC_LOG_TX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Header, - RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size, - MSC_AS_TIME_FMT" RRCConnectionReestablishmentReject UE %x size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, - RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); + // configure SRB1 for UE - LOG_I(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReestablishmentReject (bytes %d)\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), - RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); -} + if (*SRB_configList != NULL) { + for (cnt = 0; cnt < (*SRB_configList)->list.count; cnt++) { + if ((*SRB_configList)->list.array[cnt]->srb_Identity == 1) { + SRB1_config = (*SRB_configList)->list.array[cnt]; -//----------------------------------------------------------------------------- -void -rrc_eNB_generate_RRCConnectionRelease( - const protocol_ctxt_t* const ctxt_pP, - rrc_eNB_ue_context_t* const ue_context_pP -) -//----------------------------------------------------------------------------- -{ + if (SRB1_config->logicalChannelConfig) { + if (SRB1_config->logicalChannelConfig->present == + SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) { + SRB1_logicalChannelConfig = &SRB1_config->logicalChannelConfig->choice.explicitValue; + } else { + SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue; + } + } else { + SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue; + } - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; + LOG_D(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_eNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_mac_config_req_eNB(ctxt_pP->module_id, + ue_context_pP->ue_context.primaryCC_id, + 0,0,0,0,0, +#ifdef Rel14 + 0, +#endif + ctxt_pP->rnti, + (BCCH_BCH_Message_t *) NULL, + (RadioResourceConfigCommonSIB_t *) NULL, + (RadioResourceConfigCommonSIB_t *) NULL, + (struct PhysicalConfigDedicated* ) ue_context_pP->ue_context.physicalConfigDedicated, +#if defined(Rel10) || defined(Rel14) + (SCellToAddMod_r10_t *)NULL, + //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, +#endif + (MeasObjectToAddMod_t **) NULL, + ue_context_pP->ue_context.mac_MainConfig, + 1, + SRB1_logicalChannelConfig, + ue_context_pP->ue_context.measGapConfig, + (TDD_Config_t *) NULL, + NULL, + (SchedulingInfoList_t *) NULL, + 0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL +#if defined(Rel10) || defined(Rel14) + , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL +#endif +#ifdef Rel14 + ,(SystemInformationBlockType1_v1310_IEs_t *)NULL +#endif + ); + break; + } + } + } - T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), - T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, + MSC_RRC_UE, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Header, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCConnectionReestablishment UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); - memset(buffer, 0, RRC_BUF_SIZE); - size = do_RRCConnectionRelease(ctxt_pP->module_id, buffer,rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); - // set release timer - ue_context_pP->ue_context.ue_release_timer=1; - // remove UE after 10 frames after RRCConnectionRelease is triggered - ue_context_pP->ue_context.ue_release_timer_thres=100; LOG_I(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCConnectionRelease (bytes %d)\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), - size); - - LOG_D(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcConnectionRelease MUI %d) --->[PDCP][RB %u]\n", + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReestablishment (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), - size, - rrc_eNB_mui, - DCCH); - - MSC_LOG_TX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - buffer, - size, - MSC_AS_TIME_FMT" rrcConnectionRelease UE %x MUI %d size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_pP->ue_context.rnti, - rrc_eNB_mui, - size); + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); - rrc_data_req( - ctxt_pP, - DCCH, - rrc_eNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + // activate release timer, if RRCComplete not received after 10 frames, remove UE + //ue_context_pP->ue_context.ue_release_timer = 1; + // remove UE after 10 frames after RRCConnectionReestablishmentRelease is triggered + //ue_context_pP->ue_context.ue_release_timer_thres = 100; + // activate release timer, if RRCComplete not received after 100 frames, remove UE + int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); + RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + // remove UE after 100 frames after RRCConnectionReestablishmentRelease is triggered + RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 1000; } -uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9}; - -// TBD: this directive can be remived if we create a similar e_rab_param_t structure in RRC context -#if defined(ENABLE_ITTI) //----------------------------------------------------------------------------- void -rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP, - rrc_eNB_ue_context_t* const ue_context_pP, - const uint8_t ho_state - ) +rrc_eNB_process_RRCConnectionReestablishmentComplete( + const protocol_ctxt_t* const ctxt_pP, + const rnti_t const reestablish_rnti, + rrc_eNB_ue_context_t* ue_context_pP, + const uint8_t xid, + RRCConnectionReestablishmentComplete_r8_IEs_t * rrcConnectionReestablishmentComplete +) //----------------------------------------------------------------------------- { - + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, processing RRCConnectionReestablishmentComplete from UE (SRB1 Active)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + + T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + + DRB_ToAddModList_t* DRB_configList = ue_context_pP->ue_context.DRB_configList; + SRB_ToAddModList_t* SRB_configList = ue_context_pP->ue_context.SRB_configList; + SRB_ToAddModList_t** SRB_configList2 = NULL; + DRB_ToAddModList_t** DRB_configList2 = NULL; + struct SRB_ToAddMod *SRB2_config = NULL; + struct DRB_ToAddMod *DRB_config = NULL; + int i = 0; +# if defined(ENABLE_USE_MME) + int j = 0; + hashtable_rc_t h_rc; +#endif uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; - int i; - - struct DRB_ToAddMod *DRB_config = NULL; - struct RLC_Config *DRB_rlc_config = NULL; - struct PDCP_Config *DRB_pdcp_config = NULL; - struct PDCP_Config__rlc_AM *PDCP_rlc_AM = NULL; - struct PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; - struct LogicalChannelConfig *DRB_lchan_config = NULL; - struct LogicalChannelConfig__ul_SpecificParameters - *DRB_ul_SpecificParameters = NULL; - // DRB_ToAddModList_t** DRB_configList=&ue_context_pP->ue_context.DRB_configList; - DRB_ToAddModList_t* DRB_configList=ue_context_pP->ue_context.DRB_configList; - DRB_ToAddModList_t** DRB_configList2=NULL; - //DRB_ToAddModList_t** RRC_DRB_configList=&ue_context_pP->ue_context.DRB_configList; - + MeasObjectToAddModList_t *MeasObj_list = NULL; + MeasObjectToAddMod_t *MeasObj = NULL; + ReportConfigToAddModList_t *ReportConfig_list = NULL; + ReportConfigToAddMod_t *ReportConfig_per, *ReportConfig_A1, + *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; + MeasIdToAddModList_t *MeasId_list = NULL; + MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; + RSRP_Range_t *rsrp = NULL; + struct MeasConfig__speedStatePars *Sparams = NULL; + QuantityConfig_t *quantityConfig = NULL; + CellsToAddMod_t *CellToAdd = NULL; + CellsToAddModList_t *CellsToAddModList = NULL; struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* for no gcc warnings */ (void)dedicatedInfoNas; + C_RNTI_t *cba_RNTI = NULL; + uint8_t next_xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); + + ue_context_pP->ue_context.Status = RRC_CONNECTED; + + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + // get old configuration of SRB2 + if (*SRB_configList2 != NULL) { + LOG_D(RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", + SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ){ + LOG_D(RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", xid); + SRB2_config = (*SRB_configList2)->list.array[i]; + break; + } + } + } + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[next_xid]; + DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[next_xid]; + + if (*SRB_configList2) { + free(*SRB_configList2); + LOG_D(RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", next_xid); + } + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + if (SRB2_config != NULL) { + // Add SRB2 to SRB configuration list + + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + + LOG_D(RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList\n", + SRB2_config->srb_Identity); + LOG_D(RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", + SRB2_config->srb_Identity, next_xid); + } else { + // SRB configuration list only contains SRB1. + LOG_W(RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } + - long *logicalchannelgroup_drb; - int drb_identity_index=0; - uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, - DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; if (*DRB_configList2) { free(*DRB_configList2); + LOG_D(RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", next_xid); } - //*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - /* Initialize NAS list */ - dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - int e_rab_done=0; - - for ( i = 0 ; - i < ue_context_pP->ue_context.setup_e_rabs ; - i++){ - - // bypass the new and already configured erabs - if (ue_context_pP->ue_context.e_rab[i].status >= E_RAB_STATUS_DONE) { - drb_identity_index++; - continue; + if (DRB_configList != NULL) { + LOG_D(RRC, "get DRB_config from (ue_context_pP->ue_context.DRB_configList)\n"); + for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { + DRB_config = DRB_configList->list.array[i]; + + // Add DRB to DRB configuration list, for RRCConnectionReconfigurationComplete + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); } - - DRB_config = CALLOC(1, sizeof(*DRB_config)); + } + ue_context_pP->ue_context.Srb1.Active = 1; + //ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2; + +# if defined(ENABLE_USE_MME) + rrc_ue_s1ap_ids_t* rrc_ue_s1ap_ids_p = NULL; + uint16_t ue_initial_id = ue_context_pP->ue_context.ue_initial_id; + uint32_t eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; + eNB_RRC_INST *rrc_instance_p = RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]; + if (eNB_ue_s1ap_id > 0) { + h_rc = hashtable_get(rrc_instance_p->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&rrc_ue_s1ap_ids_p); + if (h_rc == HASH_TABLE_OK) { + rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } + if (ue_initial_id != 0) { + h_rc = hashtable_get(rrc_instance_p->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&rrc_ue_s1ap_ids_p); + if (h_rc == HASH_TABLE_OK) { + rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } - DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); - // allowed value 5..15, value : x+4 - *(DRB_config->eps_BearerIdentity) = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;//+ 4; // especial case generation + gtpv1u_enb_create_tunnel_req_t create_tunnel_req; - 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; + /* Save e RAB information for later */ + memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req)); - DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); - *(DRB_config->logicalChannelIdentity) = DRB_config->drb_Identity + 2; //(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; + for (j = 0, i = 0; i < NB_RB_MAX; i++) { + if (ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_ESTABLISHED) { + create_tunnel_req.eps_bearer_id[j] = ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + create_tunnel_req.sgw_S1u_teid[j] = ue_context_pP->ue_context.e_rab[i].param.gtp_teid; - 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 = PDCP_Config__discardTimer_infinity; - DRB_pdcp_config->rlc_AM = NULL; - DRB_pdcp_config->rlc_UM = NULL; + memcpy(&create_tunnel_req.sgw_addr[j], + &ue_context_pP->ue_context.e_rab[i].param.sgw_addr, + sizeof(transport_layer_addr_t)); + j++; + } + } + create_tunnel_req.rnti = ctxt_pP->rnti; // warning put zero above + create_tunnel_req.num_tunnels = j; - switch (ue_context_pP->ue_context.e_rab[i].param.qos.qci){ - /* - * type: realtime data with medium packer error rate - * action: swtich to RLC UM - */ - case 1: // 100ms, 10^-2, p2, GBR - case 2: // 150ms, 10^-3, p4, GBR - case 3: // 50ms, 10^-3, p3, GBR - case 4: // 300ms, 10^-6, p5 - case 7: // 100ms, 10^-3, p7, GBR - case 9: // 300ms, 10^-6, p9 - case 65: // 75ms, 10^-2, p0.7, mission critical voice, GBR - case 66: // 100ms, 10^-2, p2, non-mission critical voice , GBR - // RLC - DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional; - DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = 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 = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; - break; - - /* - * type: non-realtime data with low packer error rate - * action: swtich to RLC AM - */ + gtpv1u_update_s1u_tunnel( + ctxt_pP->instance, + &create_tunnel_req, + reestablish_rnti); +#endif + /* Update RNTI in ue_context */ + ue_context_pP->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else + ue_context_pP->ue_context.rnti = ctxt_pP->rnti; +# if defined(ENABLE_USE_MME) + uint8_t send_security_mode_command = FALSE; + rrc_pdcp_config_security( + ctxt_pP, + ue_context_pP, + send_security_mode_command); + LOG_D(RRC, "set security successfully \n"); +#endif + // Measurement ID list + MeasId_list = CALLOC(1, sizeof(*MeasId_list)); + memset((void *)MeasId_list, 0, sizeof(*MeasId_list)); + + MeasId0 = CALLOC(1, sizeof(*MeasId0)); + MeasId0->measId = 1; + MeasId0->measObjectId = 1; + MeasId0->reportConfigId = 1; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId0); + + MeasId1 = CALLOC(1, sizeof(*MeasId1)); + MeasId1->measId = 2; + MeasId1->measObjectId = 1; + MeasId1->reportConfigId = 2; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId1); + + MeasId2 = CALLOC(1, sizeof(*MeasId2)); + MeasId2->measId = 3; + MeasId2->measObjectId = 1; + MeasId2->reportConfigId = 3; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId2); + + MeasId3 = CALLOC(1, sizeof(*MeasId3)); + MeasId3->measId = 4; + MeasId3->measObjectId = 1; + MeasId3->reportConfigId = 4; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId3); + + MeasId4 = CALLOC(1, sizeof(*MeasId4)); + MeasId4->measId = 5; + MeasId4->measObjectId = 1; + MeasId4->reportConfigId = 5; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId4); + + MeasId5 = CALLOC(1, sizeof(*MeasId5)); + MeasId5->measId = 6; + MeasId5->measObjectId = 1; + MeasId5->reportConfigId = 6; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); + + // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; + + // Add one EUTRA Measurement Object + MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); + memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); + + // Configure MeasObject + + MeasObj = CALLOC(1, sizeof(*MeasObj)); + memset((void *)MeasObj, 0, sizeof(*MeasObj)); + + MeasObj->measObjectId = 1; + MeasObj->measObject.present = MeasObjectToAddMod__measObject_PR_measObjectEUTRA; + MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 3350; //band 7, 2.68GHz + //MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 36090; //band 33, 1.909GHz + MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = AllowedMeasBandwidth_mbw25; + MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1; + MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t)); + MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; + MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; + MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; + MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB + + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + + // Add adjacent cell lists (6 per eNB) + for (i = 0; i < 6; i++) { + CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0; + + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } + + ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); + // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + + // Report Configurations for periodical, A1-A5 events + ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); + + ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); + + ReportConfig_A1 = CALLOC(1, sizeof(*ReportConfig_A1)); + + ReportConfig_A2 = CALLOC(1, sizeof(*ReportConfig_A2)); + + ReportConfig_A3 = CALLOC(1, sizeof(*ReportConfig_A3)); + + ReportConfig_A4 = CALLOC(1, sizeof(*ReportConfig_A4)); + + ReportConfig_A5 = CALLOC(1, sizeof(*ReportConfig_A5)); + + ReportConfig_per->reportConfigId = 1; + ReportConfig_per->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_periodical; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose = + ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per); + + ReportConfig_A1->reportConfigId = 2; + ReportConfig_A1->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.choice.threshold_RSRP = 10; + + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerQuantity = ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1); + + if (RC.rrc[ctxt_pP->module_id]->HO_flag == 1 /*HO_MEASURMENT */ ) { + LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, A5, and A6 event reporting\n", + ctxt_pP->module_id, ctxt_pP->frame); + ReportConfig_A2->reportConfigId = 3; + ReportConfig_A2->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.choice.threshold_RSRP = 10; + + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A2); + + ReportConfig_A3->reportConfigId = 4; + ReportConfig_A3->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3; + + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = 1; //10; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA3.reportOnLeave = 1; + + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = 0.5; // FIXME ...hysteresis is of type long! + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger = + TimeToTrigger_ms40; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3); + + ReportConfig_A4->reportConfigId = 5; + ReportConfig_A4->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.choice.threshold_RSRP = 10; + + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A4); + + ReportConfig_A5->reportConfigId = 6; + ReportConfig_A5->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.present = + ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.present = ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.present = ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.choice.threshold_RSRP = 10; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.choice.threshold_RSRP = 10; + + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity; + + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); + // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + rsrp = CALLOC(1, sizeof(RSRP_Range_t)); + *rsrp = 20; + + Sparams = CALLOC(1, sizeof(*Sparams)); + Sparams->present = MeasConfig__speedStatePars_PR_setup; + Sparams->choice.setup.timeToTrigger_SF.sf_High = SpeedStateScaleFactors__sf_Medium_oDot75; + Sparams->choice.setup.timeToTrigger_SF.sf_Medium = SpeedStateScaleFactors__sf_High_oDot5; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeHigh = 10; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeMedium = 5; + Sparams->choice.setup.mobilityStateParameters.t_Evaluation = MobilityStateParameters__t_Evaluation_s60; + Sparams->choice.setup.mobilityStateParameters.t_HystNormal = MobilityStateParameters__t_HystNormal_s120; + + quantityConfig = CALLOC(1, sizeof(*quantityConfig)); + memset((void *)quantityConfig, 0, sizeof(*quantityConfig)); + quantityConfig->quantityConfigEUTRA = CALLOC(1, sizeof(struct QuantityConfigEUTRA)); + memset((void *)quantityConfig->quantityConfigEUTRA, 0, sizeof(*quantityConfig->quantityConfigEUTRA)); + quantityConfig->quantityConfigCDMA2000 = NULL; + quantityConfig->quantityConfigGERAN = NULL; + quantityConfig->quantityConfigUTRA = NULL; + quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = + CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP))); + quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = + CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ))); + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = FilterCoefficient_fc4; + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = FilterCoefficient_fc4; + + LOG_I(RRC, + "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n", + ctxt_pP->module_id, ctxt_pP->frame); + // store the information in an intermediate structure for Hanodver management + //rrc_inst->handover_info.as_config.sourceRadioResourceConfig.srb_ToAddModList = CALLOC(1,sizeof()); + ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); + //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.srb_ToAddModList,(void *)SRB_list,sizeof(SRB_ToAddModList_t)); + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList = *SRB_configList2; + //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.drb_ToAddModList,(void *)DRB_list,sizeof(DRB_ToAddModList_t)); + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToAddModList = DRB_configList; + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL; + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig = + CALLOC(1, sizeof(*ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig)); + memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig, + (void *)ue_context_pP->ue_context.mac_MainConfig, sizeof(MAC_MainConfig_t)); + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated = + CALLOC(1, sizeof(PhysicalConfigDedicated_t)); + memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated, + (void*)ue_context_pP->ue_context.physicalConfigDedicated, sizeof(PhysicalConfigDedicated_t)); + ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.sps_Config = NULL; + //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.sps_Config,(void *)rrc_inst->sps_Config[ue_mod_idP],sizeof(SPS_Config_t)); + + } + +#ifdef CBA + //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; + uint8_t *cba_RNTI_buf; + cba_RNTI = CALLOC(1, sizeof(C_RNTI_t)); + cba_RNTI_buf = CALLOC(1, 2 * sizeof(uint8_t)); + cba_RNTI->buf = cba_RNTI_buf; + cba_RNTI->size = 2; + cba_RNTI->bits_unused = 0; + + // associate UEs to the CBa groups as a function of their UE id + if (rrc_inst->num_active_cba_groups) { + cba_RNTI->buf[0] = rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups] & 0xff; + cba_RNTI->buf[1] = 0xff; + LOG_D(RRC, + "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n", + enb_mod_idP, frameP, + rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups], + ue_mod_idP % rrc_inst->num_active_cba_groups, ue_mod_idP); + } else { + cba_RNTI->buf[0] = 0x0; + cba_RNTI->buf[1] = 0x0; + LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", enb_mod_idP, frameP, ue_mod_idP); + } + +#endif + +#if defined(ENABLE_ITTI) + /* Initialize NAS list */ + dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); + + /* Add all NAS PDUs to the list */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { + if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { + dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); + memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedInfoNas, + (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); + LOG_D(RRC, "Add dedicatedInfoNas(%d) to dedicatedInfoNASList\n", i); + ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); + } + + /* TODO parameters yet to process ... */ + { + // ue_context_pP->ue_context.e_rab[i].param.qos; + // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + } + + /* TODO should test if e RAB are Ok before! */ + ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; + LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", + i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_STATUS_DONE"); + } + + /* If list is empty free the list and reset the address */ + if (dedicatedInfoNASList->list.count == 0) { + free(dedicatedInfoNASList); + dedicatedInfoNASList = NULL; + } + +#endif + + // send RRCConnectionReconfiguration + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCConnectionReconfiguration(ctxt_pP, + buffer, + next_xid, //Transaction_id, + (SRB_ToAddModList_t*)*SRB_configList2, // SRB_configList + (DRB_ToAddModList_t*)DRB_configList, + (DRB_ToReleaseList_t*)NULL, // DRB2_list, + (struct SPS_Config*)NULL, // maybe ue_context_pP->ue_context.sps_Config, + (struct PhysicalConfigDedicated*)ue_context_pP->ue_context.physicalConfigDedicated, +#ifdef EXMIMO_IOT + NULL, NULL, NULL,NULL, +#else + (MeasObjectToAddModList_t*)MeasObj_list, // MeasObj_list, + (ReportConfigToAddModList_t*)ReportConfig_list, // ReportConfig_list, + (QuantityConfig_t*)quantityConfig, //quantityConfig, + (MeasIdToAddModList_t*)NULL, +#endif + (MAC_MainConfig_t*)ue_context_pP->ue_context.mac_MainConfig, + (MeasGapConfig_t*)NULL, + (MobilityControlInfo_t*)NULL, + (struct MeasConfig__speedStatePars*)Sparams, // Sparams, + (RSRP_Range_t*)rsrp, // rsrp, + (C_RNTI_t*)cba_RNTI, // cba_RNTI + (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList //dedicatedInfoNASList +#if defined(Rel10) || defined(Rel14) + , (SCellToAddMod_r10_t*)NULL +#endif + ); + +#ifdef RRC_MSG_PRINT + LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n"); + for (i = 0; i < size; i++) { + LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); + } + LOG_F(RRC,"\n"); + //////////////////////////////////////// +#endif + +#if defined(ENABLE_ITTI) + + /* Free all NAS PDUs */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { + if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; + } + } + +#endif + + LOG_I(RRC, + "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + + LOG_D(RRC, + "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" rrcConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req( + ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + + // delete UE data of prior RNTI. UE use current RNTI. + protocol_ctxt_t ctxt_prior = *ctxt_pP; + ctxt_prior.rnti = reestablish_rnti; + + LTE_eNB_ULSCH_t *ulsch = NULL; + nfapi_ul_config_request_body_t *ul_req_tmp = NULL; + PHY_VARS_eNB *eNB_PHY = NULL; + eNB_MAC_INST *eNB_MAC = RC.mac[ctxt_prior.module_id]; + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + eNB_PHY = RC.eNB[ctxt_prior.module_id][CC_id]; + for (int i=0; i<NUMBER_OF_UE_MAX; i++) { + ulsch = eNB_PHY->ulsch[i]; + if((ulsch != NULL) && (ulsch->rnti == ctxt_prior.rnti)){ + LOG_I(RRC, "clean_eNb_ulsch UE %x \n", ctxt_prior.rnti); + clean_eNb_ulsch(ulsch); + break; + } + } + + for(int j = 0; j < 10; j++){ + ul_req_tmp = &eNB_MAC->UL_req_tmp[CC_id][j].ul_config_request_body; + if(ul_req_tmp){ + int pdu_number = ul_req_tmp->number_of_pdus; + for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){ + if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == ctxt_prior.rnti){ + LOG_I(RRC, "remove UE %x from ul_config_pdu_list %d/%d\n", ctxt_prior.rnti, pdu_index, pdu_number); + if(pdu_index < pdu_number -1){ + memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t)); + } + ul_req_tmp->number_of_pdus--; + } + } + } + } + } + rrc_mac_remove_ue(ctxt_prior.module_id, ctxt_prior.rnti); + rrc_rlc_remove_ue(&ctxt_prior); + pdcp_remove_UE(&ctxt_prior); +} + +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_RRCConnectionReestablishmentReject( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const int CC_id +) +//----------------------------------------------------------------------------- +{ +#ifdef RRC_MSG_PRINT + int cnt; +#endif + int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); + RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 20; + + T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size = + do_RRCConnectionReestablishmentReject(ctxt_pP->module_id, + (uint8_t*) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload); + +#ifdef RRC_MSG_PRINT + LOG_F(RRC,"[MSG] RRCConnectionReestablishmentReject\n"); + + for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { + LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload)[cnt]); + } + + LOG_F(RRC,"\n"); +#endif + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Header, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCConnectionReestablishmentReject UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); + + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReestablishmentReject (bytes %d)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); +} + +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_RRCConnectionRelease( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP +) +//----------------------------------------------------------------------------- +{ + + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + + T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCConnectionRelease(ctxt_pP->module_id, buffer,rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); + // set release timer + //ue_context_pP->ue_context.ue_release_timer=1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + //ue_context_pP->ue_context.ue_release_timer_thres=100; + // set release timer + ue_context_pP->ue_context.ue_release_timer_rrc = 1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres_rrc = 100; + ue_context_pP->ue_context.ue_reestablishment_timer = 0; + ue_context_pP->ue_context.ue_release_timer = 0; + ue_context_pP->ue_context.ue_release_timer_s1 = 0; + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCConnectionRelease (bytes %d)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + size); + + LOG_D(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcConnectionRelease MUI %d) --->[PDCP][RB %u]\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + size, + rrc_eNB_mui, + DCCH); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" rrcConnectionRelease UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req( + ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +} + +uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9}; + +// TBD: this directive can be remived if we create a similar e_rab_param_t structure in RRC context +#if defined(ENABLE_ITTI) +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const uint8_t ho_state + ) +//----------------------------------------------------------------------------- +{ + + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int i; + + struct DRB_ToAddMod *DRB_config = NULL; + struct RLC_Config *DRB_rlc_config = NULL; + struct PDCP_Config *DRB_pdcp_config = NULL; + struct PDCP_Config__rlc_AM *PDCP_rlc_AM = NULL; + struct PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; + struct LogicalChannelConfig *DRB_lchan_config = NULL; + struct LogicalChannelConfig__ul_SpecificParameters + *DRB_ul_SpecificParameters = NULL; + // DRB_ToAddModList_t** DRB_configList=&ue_context_pP->ue_context.DRB_configList; + DRB_ToAddModList_t* DRB_configList=ue_context_pP->ue_context.DRB_configList; + DRB_ToAddModList_t** DRB_configList2=NULL; + //DRB_ToAddModList_t** RRC_DRB_configList=&ue_context_pP->ue_context.DRB_configList; + + struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; + DedicatedInfoNAS_t *dedicatedInfoNas = NULL; + /* for no gcc warnings */ + (void)dedicatedInfoNas; + + long *logicalchannelgroup_drb; +// int drb_identity_index=0; + + uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, + DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; + if (*DRB_configList2) { + free(*DRB_configList2); + } + //*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + /* Initialize NAS list */ + dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); + + int e_rab_done=0; + + for ( i = 0 ; + i < ue_context_pP->ue_context.setup_e_rabs ; + i++){ + + if (e_rab_done >= ue_context_pP->ue_context.nb_of_e_rabs){ + break; + } + + // bypass the new and already configured erabs + if (ue_context_pP->ue_context.e_rab[i].status >= E_RAB_STATUS_DONE) { +// drb_identity_index++; + continue; + } + + 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) = 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 = i+1; + + DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); + *(DRB_config->logicalChannelIdentity) = DRB_config->drb_Identity + 2; //(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 = PDCP_Config__discardTimer_infinity; + DRB_pdcp_config->rlc_AM = NULL; + DRB_pdcp_config->rlc_UM = NULL; + + + switch (ue_context_pP->ue_context.e_rab[i].param.qos.qci){ + /* + * type: realtime data with medium packer error rate + * action: swtich to RLC UM + */ + case 1: // 100ms, 10^-2, p2, GBR + case 2: // 150ms, 10^-3, p4, GBR + case 3: // 50ms, 10^-3, p3, GBR + case 4: // 300ms, 10^-6, p5 + case 7: // 100ms, 10^-3, p7, GBR + case 9: // 300ms, 10^-6, p9 + case 65: // 75ms, 10^-2, p0.7, mission critical voice, GBR + case 66: // 100ms, 10^-2, p2, non-mission critical voice , GBR + // RLC + DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional; + DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = 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 = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; + break; + + /* + * type: non-realtime data with low packer error rate + * action: swtich to RLC AM + */ case 5: // 100ms, 10^-6, p1 , IMS signaling case 6: // 300ms, 10^-6, p6 case 8: // 300ms, 10^-6, p8 @@ -1261,6 +2072,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co LOG_E(RRC,"not supported qci %d\n", ue_context_pP->ue_context.e_rab[i].param.qos.qci); ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_FAILED; ue_context_pP->ue_context.e_rab[i].xid = xid; + e_rab_done++; continue; } @@ -1281,49 +2093,317 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; DRB_ul_SpecificParameters->bucketSizeDuration = LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - - logicalchannelgroup_drb = CALLOC(1, sizeof(long)); - *logicalchannelgroup_drb = 1;//(i+1) % 3; - DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; + + 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); + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); + //ue_context_pP->ue_context.DRB_configList2[drb_identity_index] = &(*DRB_configList); + + LOG_I(RRC,"EPS ID %ld, DRB ID %ld (index %d), QCI %d, priority %ld, LCID %ld LCGID %ld \n", + *DRB_config->eps_BearerIdentity, + DRB_config->drb_Identity, i, + ue_context_pP->ue_context.e_rab[i].param.qos.qci, + DRB_ul_SpecificParameters->priority, + *(DRB_config->logicalChannelIdentity), + *DRB_ul_SpecificParameters->logicalChannelGroup + ); + + e_rab_done++; + ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; + ue_context_pP->ue_context.e_rab[i].xid = xid; + + { + if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { + dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); + memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedInfoNas, + (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); + LOG_I(RRC,"add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length, i); + } + else { + LOG_W(RRC,"Not received activate dedicated EPS bearer context request\n"); + } + /* TODO parameters yet to process ... */ + { + // ue_context_pP->ue_context.e_rab[i].param.qos; + // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + } + } + + } + + /* If list is empty free the list and reset the address */ + if (dedicatedInfoNASList != NULL) { + if (dedicatedInfoNASList->list.count == 0) { + free(dedicatedInfoNASList); + dedicatedInfoNASList = NULL; + LOG_W(RRC,"dedlicated NAS list is empty, free the list and reset the address\n"); + } + } else { + LOG_W(RRC,"dedlicated NAS list is empty\n"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCConnectionReconfiguration(ctxt_pP, + buffer, + xid, + (SRB_ToAddModList_t*)NULL, + (DRB_ToAddModList_t*)*DRB_configList2, + (DRB_ToReleaseList_t*)NULL, // DRB2_list, + (struct SPS_Config*)NULL, // *sps_Config, + NULL, NULL, NULL, NULL,NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList +#if defined(Rel10) || defined(Rel14) + , (SCellToAddMod_r10_t*)NULL +#endif + ); + + +#ifdef RRC_MSG_PRINT + LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n"); + for (i = 0; i < size; i++) { + LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); + } + LOG_F(RRC,"\n"); + //////////////////////////////////////// +#endif + +#if defined(ENABLE_ITTI) + + /* Free all NAS PDUs */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { + if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; + } + } +#endif + + LOG_I(RRC, + "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + + LOG_D(RRC, + "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated rrcConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req( + ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + + +} +int +rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const uint8_t ho_state + ) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int i, j; + + struct DRB_ToAddMod *DRB_config = NULL; + struct RLC_Config *DRB_rlc_config = NULL; + struct PDCP_Config *DRB_pdcp_config = NULL; + struct PDCP_Config__rlc_AM *PDCP_rlc_AM = NULL; + struct PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; + struct LogicalChannelConfig *DRB_lchan_config = NULL; + struct LogicalChannelConfig__ul_SpecificParameters + *DRB_ul_SpecificParameters = NULL; + DRB_ToAddModList_t* DRB_configList = ue_context_pP->ue_context.DRB_configList; + DRB_ToAddModList_t* DRB_configList2 = NULL; + + struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; + DedicatedInfoNAS_t *dedicatedInfoNas = NULL; + /* for no gcc warnings */ + (void)dedicatedInfoNas; + + uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); // Transaction_id, + DRB_configList2 = CALLOC(1, sizeof(*DRB_configList2)); + /* Initialize NAS list */ + dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); + + for (i = 0; i < ue_context_pP->ue_context.nb_of_modify_e_rabs; i++) { + // bypass the new and already configured erabs + if (ue_context_pP->ue_context.modify_e_rab[i].status >= E_RAB_STATUS_DONE) { + ue_context_pP->ue_context.modify_e_rab[i].xid = xid; + continue; + } + + if (ue_context_pP->ue_context.modify_e_rab[i].cause != S1AP_CAUSE_NOTHING) { + // set xid of failure RAB + ue_context_pP->ue_context.modify_e_rab[i].xid = xid; + ue_context_pP->ue_context.modify_e_rab[i].status = E_RAB_STATUS_FAILED; + continue; + } + + DRB_config = NULL; + // search exist DRB_config + for (j = 0; j < DRB_configList->list.count; j++) { + if((uint8_t)*(DRB_configList->list.array[j]->eps_BearerIdentity) == ue_context_pP->ue_context.modify_e_rab[i].param.e_rab_id) { + DRB_config = DRB_configList->list.array[j]; + break; + } + } + if (NULL == DRB_config) { + ue_context_pP->ue_context.modify_e_rab[i].xid = xid; + ue_context_pP->ue_context.modify_e_rab[i].status = E_RAB_STATUS_FAILED; + // TODO use which cause + ue_context_pP->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_pP->ue_context.modify_e_rab[i].cause_value = 0;//S1ap_CauseRadioNetwork_unspecified; + ue_context_pP->ue_context.nb_of_failed_e_rabs++; + continue; + } + + DRB_rlc_config = DRB_config->rlc_Config; + + DRB_pdcp_config = DRB_config->pdcp_Config; + *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity; + switch (ue_context_pP->ue_context.modify_e_rab[i].param.qos.qci) { + /* + * type: realtime data with medium packer error rate + * action: swtich to RLC UM + */ + case 1: // 100ms, 10^-2, p2, GBR + case 2: // 150ms, 10^-3, p4, GBR + case 3: // 50ms, 10^-3, p3, GBR + case 4: // 300ms, 10^-6, p5 + case 7: // 100ms, 10^-3, p7, GBR + case 9: // 300ms, 10^-6, p9 + case 65: // 75ms, 10^-2, p0.7, mission critical voice, GBR + case 66: // 100ms, 10^-2, p2, non-mission critical voice , GBR + // RLC + DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional; + DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35; + // PDCP + if (DRB_pdcp_config->rlc_AM) { + free(DRB_pdcp_config->rlc_AM); + DRB_pdcp_config->rlc_AM = NULL; + } + if (DRB_pdcp_config->rlc_UM) { + free(DRB_pdcp_config->rlc_UM); + DRB_pdcp_config->rlc_UM = NULL; + } + PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); + DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; + PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; + break; + + /* + * type: non-realtime data with low packer error rate + * action: swtich to RLC AM + */ + case 5: // 100ms, 10^-6, p1 , IMS signaling + case 6: // 300ms, 10^-6, p6 + case 8: // 300ms, 10^-6, p8 + case 69: // 60ms, 10^-6, p0.5, mission critical delay sensitive data, Lowest Priority + case 70: // 200ms, 10^-6, p5.5, mision critical data + // RLC + DRB_rlc_config->present = RLC_Config_PR_am; + DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms50; + DRB_rlc_config->choice.am.ul_AM_RLC.pollPDU = PollPDU_p16; + DRB_rlc_config->choice.am.ul_AM_RLC.pollByte = PollByte_kBinfinity; + DRB_rlc_config->choice.am.ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t8; + DRB_rlc_config->choice.am.dl_AM_RLC.t_Reordering = T_Reordering_ms35; + DRB_rlc_config->choice.am.dl_AM_RLC.t_StatusProhibit = T_StatusProhibit_ms25; + + // PDCP + if (DRB_pdcp_config->rlc_AM) { + free(DRB_pdcp_config->rlc_AM); + DRB_pdcp_config->rlc_AM = NULL; + } + if (DRB_pdcp_config->rlc_UM) { + free(DRB_pdcp_config->rlc_UM); + DRB_pdcp_config->rlc_UM = NULL; + } + PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); + DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; + PDCP_rlc_AM->statusReportRequired = FALSE; + + break; + default : + LOG_E(RRC, "not supported qci %d\n", ue_context_pP->ue_context.modify_e_rab[i].param.qos.qci); + ue_context_pP->ue_context.modify_e_rab[i].status = E_RAB_STATUS_FAILED; + ue_context_pP->ue_context.modify_e_rab[i].xid = xid; + ue_context_pP->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_pP->ue_context.modify_e_rab[i].cause_value = 37;//S1ap_CauseRadioNetwork_not_supported_QCI_value; + ue_context_pP->ue_context.nb_of_failed_e_rabs++; + continue; + } + + DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed; + + DRB_lchan_config = DRB_config->logicalChannelConfig; + DRB_ul_SpecificParameters = DRB_lchan_config->ul_SpecificParameters; + + if (ue_context_pP->ue_context.modify_e_rab[i].param.qos.qci < 9 ) + DRB_ul_SpecificParameters->priority = qci_to_priority[ue_context_pP->ue_context.modify_e_rab[i].param.qos.qci-1] + 3; + else + DRB_ul_SpecificParameters->priority= 4; + + DRB_ul_SpecificParameters->prioritisedBitRate = LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; + + DRB_ul_SpecificParameters->bucketSizeDuration = + LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - ASN_SEQUENCE_ADD(&DRB_configList->list, DRB_config); - ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); - //ue_context_pP->ue_context.DRB_configList2[drb_identity_index] = &(*DRB_configList); - - LOG_I(RRC,"EPS ID %ld, DRB ID %ld (index %d), QCI %d, priority %ld, LCID %ld LCGID %ld \n", - *DRB_config->eps_BearerIdentity, - DRB_config->drb_Identity, i, - ue_context_pP->ue_context.e_rab[i].param.qos.qci, - DRB_ul_SpecificParameters->priority, - *(DRB_config->logicalChannelIdentity), - *DRB_ul_SpecificParameters->logicalChannelGroup - ); + ASN_SEQUENCE_ADD(&(DRB_configList2)->list, DRB_config); + + LOG_I(RRC, "EPS ID %ld, DRB ID %ld (index %d), QCI %d, priority %ld, LCID %ld LCGID %ld \n", + *DRB_config->eps_BearerIdentity, + DRB_config->drb_Identity, i, + ue_context_pP->ue_context.modify_e_rab[i].param.qos.qci, + DRB_ul_SpecificParameters->priority, + *(DRB_config->logicalChannelIdentity), + *DRB_ul_SpecificParameters->logicalChannelGroup + ); + + //e_rab_done++; + ue_context_pP->ue_context.modify_e_rab[i].status = E_RAB_STATUS_DONE; + ue_context_pP->ue_context.modify_e_rab[i].xid = xid; - e_rab_done++; - ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; - ue_context_pP->ue_context.e_rab[i].xid = xid; - { - if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { - dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); - memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(dedicatedInfoNas, - (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer, - ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length); - ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); - LOG_I(RRC,"add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length, i); - } - else { - LOG_W(RRC,"Not received activate dedicated EPS bearer context request\n"); + if (ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.buffer != NULL) { + dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); + memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedInfoNas, + (char*)ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.buffer, + ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); + LOG_I(RRC, "add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.length, i); } - /* TODO parameters yet to process ... */ - { - // ue_context_pP->ue_context.e_rab[i].param.qos; - // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; - // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + else { + LOG_W(RRC, "Not received activate dedicated EPS bearer context request\n"); } } - } /* If list is empty free the list and reset the address */ @@ -1332,28 +2412,28 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co free(dedicatedInfoNASList); dedicatedInfoNASList = NULL; LOG_W(RRC,"dedlicated NAS list is empty, free the list and reset the address\n"); - } + } } else { LOG_W(RRC,"dedlicated NAS list is empty\n"); } memset(buffer, 0, RRC_BUF_SIZE); - size = do_RRCConnectionReconfiguration(ctxt_pP, - buffer, - xid, - (SRB_ToAddModList_t*)NULL, - (DRB_ToAddModList_t*)*DRB_configList2, - (DRB_ToReleaseList_t*)NULL, // DRB2_list, - (struct SPS_Config*)NULL, // *sps_Config, - NULL, NULL, NULL, NULL,NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList + size = do_RRCConnectionReconfiguration(ctxt_pP, + buffer, + xid, + (SRB_ToAddModList_t*)NULL, + (DRB_ToAddModList_t*)DRB_configList2, + (DRB_ToReleaseList_t*)NULL, // DRB2_list, + (struct SPS_Config*)NULL, // *sps_Config, + NULL, NULL, NULL, NULL,NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList #if defined(Rel10) || defined(Rel14) - , (SCellToAddMod_r10_t*)NULL + , (SCellToAddMod_r10_t*)NULL #endif - ); - + ); + #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n"); @@ -1367,11 +2447,11 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co #if defined(ENABLE_ITTI) /* Free all NAS PDUs */ - for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { - if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) { + for (i = 0; i < ue_context_pP->ue_context.nb_of_modify_e_rabs; i++) { + if (ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.buffer != NULL) { /* Free the NAS PDU buffer and invalidate it */ - free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer); - ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; + free(ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.modify_e_rab[i].param.nas_pdu.buffer = NULL; } } #endif @@ -1403,7 +2483,125 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + return 0; +} +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release( const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t* nas_buffer) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + int i; + uint16_t size = 0; + DRB_ToReleaseList_t** DRB_Release_configList2=NULL; + DRB_Identity_t* DRB_release; + struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; + + DRB_Release_configList2=&ue_context_pP->ue_context.DRB_Release_configList2[xid]; + if (*DRB_Release_configList2) { + free(*DRB_Release_configList2); + } + *DRB_Release_configList2 = CALLOC(1, sizeof(**DRB_Release_configList2)); + + for(i = 0; i < NB_RB_MAX; i++){ + if((ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_TORELEASE) && ue_context_pP->ue_context.e_rab[i].xid == xid){ + DRB_release = CALLOC(1, sizeof(DRB_Identity_t)); + *DRB_release = i+1; + ASN_SEQUENCE_ADD(&(*DRB_Release_configList2)->list, DRB_release); + //free(DRB_release); + } + } + + /* If list is empty free the list and reset the address */ + if (nas_length > 0) { + DedicatedInfoNAS_t *dedicatedInfoNas = NULL; + dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); + dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t)); + memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedInfoNas, + (char*)nas_buffer, + nas_length); + ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas); + LOG_I(RRC,"add NAS info with size %d\n",nas_length); + } else { + LOG_W(RRC,"dedlicated NAS list is empty\n"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCConnectionReconfiguration(ctxt_pP, + buffer, + xid, + NULL, + NULL, + (DRB_ToReleaseList_t*)*DRB_Release_configList2, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList +#if defined(Rel10) || defined(Rel14) + , (SCellToAddMod_r10_t*)NULL +#endif + ); + ue_context_pP->ue_context.e_rab_release_command_flag = 1; + +#ifdef RRC_MSG_PRINT + LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n"); + for (i = 0; i < size; i++) { + LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]); + } + LOG_F(RRC,"\n"); + //////////////////////////////////////// +#endif + +#if defined(ENABLE_ITTI) + /* Free all NAS PDUs */ + if (nas_length > 0) { + /* Free the NAS PDU buffer and invalidate it */ + free(nas_buffer); + } +#endif + + LOG_I(RRC, + "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + + LOG_D(RRC, + "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated rrcConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req( + ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); } #endif @@ -2138,7 +3336,113 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons PDCP_TRANSMISSION_MODE_CONTROL); } - +typedef enum { BAND_TYPE_FDD, BAND_TYPE_TDD } band_type; + +typedef struct { + band_type t; + int band; + unsigned long ul_minfreq, ul_maxfreq; + unsigned long dl_minfreq, dl_maxfreq; +} band_freq; + +static band_freq bands[] = { + { BAND_TYPE_FDD, 1, 1920000000UL, 1980000000UL, 2110000000UL, 2170000000UL }, + { BAND_TYPE_FDD, 2, 1850000000UL, 1910000000UL, 1930000000UL, 1990000000UL }, + { BAND_TYPE_FDD, 3, 1710000000UL, 1785000000UL, 1805000000UL, 1880000000UL }, + { BAND_TYPE_FDD, 4, 1710000000UL, 1755000000UL, 2110000000UL, 2155000000UL }, + { BAND_TYPE_FDD, 5, 824000000UL, 849000000UL, 869000000UL, 894000000UL }, + /* to remove? */{ BAND_TYPE_FDD, 6, 830000000UL, 840000000UL, 875000000UL, 885000000UL }, + { BAND_TYPE_FDD, 7, 2500000000UL, 2570000000UL, 2620000000UL, 2690000000UL }, + { BAND_TYPE_FDD, 8, 880000000UL, 915000000UL, 925000000UL, 960000000UL }, + { BAND_TYPE_FDD, 9, 1749900000UL, 1784900000UL, 1844900000UL, 1879900000UL }, + { BAND_TYPE_FDD, 10, 1710000000UL, 1770000000UL, 2110000000UL, 2170000000UL }, + { BAND_TYPE_FDD, 11, 1427900000UL, 1447900000UL, 1475900000UL, 1495900000UL }, + { BAND_TYPE_FDD, 12, 699000000UL, 716000000UL, 729000000UL, 746000000UL }, + { BAND_TYPE_FDD, 13, 777000000UL, 787000000UL, 746000000UL, 756000000UL }, + { BAND_TYPE_FDD, 14, 788000000UL, 798000000UL, 758000000UL, 768000000UL }, + { BAND_TYPE_FDD, 17, 704000000UL, 716000000UL, 734000000UL, 746000000UL }, + { BAND_TYPE_FDD, 18, 815000000UL, 830000000UL, 860000000UL, 875000000UL }, + { BAND_TYPE_FDD, 19, 830000000UL, 845000000UL, 875000000UL, 890000000UL }, + { BAND_TYPE_FDD, 20, 832000000UL, 862000000UL, 791000000UL, 821000000UL }, + { BAND_TYPE_FDD, 21, 1447900000UL, 1462900000UL, 1495900000UL, 1510900000UL }, + { BAND_TYPE_FDD, 22, 3410000000UL, 3490000000UL, 3510000000UL, 3590000000UL }, + { BAND_TYPE_FDD, 23, 2000000000UL, 2020000000UL, 2180000000UL, 2200000000UL }, + { BAND_TYPE_FDD, 24, 1626500000UL, 1660500000UL, 1525000000UL, 1559000000UL }, + { BAND_TYPE_FDD, 25, 1850000000UL, 1915000000UL, 1930000000UL, 1995000000UL }, + + { BAND_TYPE_TDD, 33, 1900000000UL, 1920000000UL, 1900000000UL, 1920000000UL }, + { BAND_TYPE_TDD, 34, 2010000000UL, 2025000000UL, 2010000000UL, 2025000000UL }, + { BAND_TYPE_TDD, 35, 1850000000UL, 1910000000UL, 1850000000UL, 1910000000UL }, + { BAND_TYPE_TDD, 36, 1930000000UL, 1990000000UL, 1930000000UL, 1990000000UL }, + { BAND_TYPE_TDD, 37, 1910000000UL, 1930000000UL, 1910000000UL, 1930000000UL }, + { BAND_TYPE_TDD, 38, 2570000000UL, 2620000000UL, 2570000000UL, 2620000000UL }, + { BAND_TYPE_TDD, 39, 1880000000UL, 1920000000UL, 1880000000UL, 1920000000UL }, + { BAND_TYPE_TDD, 40, 2300000000UL, 2400000000UL, 2300000000UL, 2400000000UL }, + { BAND_TYPE_TDD, 41, 2496000000UL, 2690000000UL, 2496000000UL, 2690000000UL }, + { BAND_TYPE_TDD, 42, 3400000000UL, 3600000000UL, 3400000000UL, 3600000000UL }, + { BAND_TYPE_TDD, 43, 3600000000UL, 3800000000UL, 3600000000UL, 3800000000UL }, +}; + +typedef struct { + int band; + unsigned long dl_flow; + int dl_off; + int dl_offmin, dl_offmax; + unsigned long ul_flow; + int ul_off; + int ul_offmin, ul_offmax; +} earfcn; + +static earfcn earfcn_table[] = { + { 1, 2110000000UL, 0, 0, 599, 1920000000UL, 18000, 18000, 18599 }, + { 2, 1930000000UL, 600, 600, 1199, 1850000000UL, 18600, 18600, 19199 }, + { 3, 1805000000UL, 1200, 1200, 1949, 1710000000UL, 19200, 19200, 19949 }, + { 4, 2110000000UL, 1950, 1950, 2399, 1710000000UL, 19950, 19950, 20399 }, + { 5, 869000000UL, 2400, 2400, 2649, 824000000UL, 20400, 20400, 20649 }, + { 6, 875000000UL, 2650, 2650, 2749, 830000000UL, 20650, 20650, 20749 }, + { 7, 2620000000UL, 2750, 2750, 3449, 2500000000UL, 20750, 20750, 21449 }, + { 8, 925000000UL, 3450, 3450, 3799, 880000000UL, 21450, 21450, 21799 }, + { 9, 1844900000UL, 3800, 3800, 4149, 1749900000UL, 21800, 21800, 22149 }, + { 10, 2110000000UL, 4150, 4150, 4749, 1710000000UL, 22150, 22150, 22749 }, + { 11, 1475900000UL, 4750, 4750, 4949, 1427900000UL, 22750, 22750, 22949 }, + { 12, 729000000UL, 5010, 5010, 5179, 699000000UL, 23010, 23010, 23179 }, + { 13, 746000000UL, 5180, 5180, 5279, 777000000UL, 23180, 23180, 23279 }, + { 14, 758000000UL, 5280, 5280, 5379, 788000000UL, 23280, 23280, 23379 }, + { 17, 734000000UL, 5730, 5730, 5849, 704000000UL, 23730, 23730, 23849 }, + { 18, 860000000UL, 5850, 5850, 5999, 815000000UL, 23850, 23850, 23999 }, + { 19, 875000000UL, 6000, 6000, 6149, 830000000UL, 24000, 24000, 24149 }, + { 20, 791000000UL, 6150, 6150, 6449, 832000000UL, 24150, 24150, 24449 }, + { 21, 1495900000UL, 6450, 6450, 6599, 1447900000UL, 24450, 24450, 24599 }, + { 22, 3510000000UL, 6600, 6600, 7399, 3410000000UL, 24600, 24600, 25399 }, + { 23, 2180000000UL, 7500, 7500, 7699, 2000000000UL, 25500, 25500, 25699 }, + { 24, 1525000000UL, 7700, 7700, 8039, 1626500000UL, 25700, 25700, 26039 }, + { 25, 1930000000UL, 8040, 8040, 8689, 1850000000UL, 26040, 26040, 26689 }, + { 33, 1900000000UL, 36000, 36000, 36199, 1900000000UL, 36000, 36000, 36199 }, + { 34, 2010000000UL, 36200, 36200, 36349, 2010000000UL, 36200, 36200, 36349 }, + { 35, 1850000000UL, 36350, 36350, 36949, 1850000000UL, 36350, 36350, 36949 }, + { 36, 1930000000UL, 36950, 36950, 37549, 1930000000UL, 36950, 36950, 37549 }, + { 37, 1910000000UL, 37550, 37550, 37749, 1910000000UL, 37550, 37550, 37749 }, + { 38, 2570000000UL, 37750, 37750, 38249, 2570000000UL, 37750, 37750, 38249 }, + { 39, 1880000000UL, 38250, 38250, 38649, 1880000000UL, 38250, 38250, 38649 }, + { 40, 2300000000UL, 38650, 38650, 39649, 2300000000UL, 38650, 38650, 39649 }, + { 41, 2496000000UL, 39650, 39650, 41589, 2496000000UL, 39650, 39650, 41589 }, + { 42, 3400000000UL, 41590, 41590, 43589, 3400000000UL, 41590, 41590, 43589 }, + { 43, 3600000000UL, 43590, 43590, 45589, 3600000000UL, 43590, 43590, 45589 }, +}; + +int freq_to_arfcn10(int band, unsigned long freq) +{ + int N = sizeof(earfcn_table) / sizeof(earfcn_table[0]); + int i; + + for (i = 0; i < N; i++) if (bands[i].band == band) break; + if (i == N) return -1; + + if (!(bands[i].dl_minfreq < freq && freq < bands[i].dl_maxfreq)) + return -1; + + return (freq - earfcn_table[i].dl_flow) / 100000UL + earfcn_table[i].dl_off; +} //----------------------------------------------------------------------------- int @@ -3436,9 +4740,12 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( uint8_t *kRRCenc = NULL; uint8_t *kRRCint = NULL; uint8_t *kUPenc = NULL; + ue_context_pP->ue_context.ue_reestablishment_timer = 0; DRB_ToAddModList_t* DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid]; SRB_ToAddModList_t* SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid]; + DRB_ToReleaseList_t* DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid]; + DRB_Identity_t* drb_id_p = NULL; T(T_ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); @@ -3472,7 +4779,8 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( ctxt_pP, SRB_configList, //NULL, //LG-RK 14/05/2014 SRB_configList, DRB_configList, - (DRB_ToReleaseList_t *) NULL, +// (DRB_ToReleaseList_t *) NULL, + DRB_Release_configList2, /*RC.rrc[ctxt_pP->module_id]->ciphering_algorithm[ue_mod_idP] | (RC.rrc[ctxt_pP->module_id]->integrity_algorithm[ue_mod_idP] << 4), */ @@ -3489,7 +4797,8 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( ctxt_pP, SRB_configList, // NULL, //LG-RK 14/05/2014 SRB_configList, DRB_configList, - (DRB_ToReleaseList_t *) NULL +// (DRB_ToReleaseList_t *) NULL + DRB_Release_configList2 #if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL #endif @@ -3516,6 +4825,8 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( SRB_configList->list.array[i]->srb_Identity); } } + free(SRB_configList); + ue_context_pP->ue_context.SRB_configList2[xid] = NULL; } // Loop through DRBs and establish if necessary @@ -3691,6 +5002,22 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( } } } + free(DRB_configList); + ue_context_pP->ue_context.DRB_configList2[xid] = NULL; + } + + if(DRB_Release_configList2 != NULL){ + for (i = 0; i < DRB_Release_configList2->list.count; i++) { + if (DRB_Release_configList2->list.array[i]) { + drb_id_p = DRB_Release_configList2->list.array[i]; + drb_id = *drb_id_p; + if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { + ue_context_pP->ue_context.DRB_active[drb_id] = 0; + } + } + } + free(DRB_Release_configList2); + ue_context_pP->ue_context.DRB_Release_configList2[xid] = NULL; } } @@ -3810,9 +5137,13 @@ rrc_eNB_generate_RRCConnectionSetup( RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size); // activate release timer, if RRCSetupComplete not received after 10 frames, remove UE - ue_context_pP->ue_context.ue_release_timer=1; + //ue_context_pP->ue_context.ue_release_timer=1; // remove UE after 10 frames after RRCConnectionRelease is triggered - ue_context_pP->ue_context.ue_release_timer_thres=100; + //ue_context_pP->ue_context.ue_release_timer_thres=100; + // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE + ue_context_pP->ue_context.ue_release_timer=1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres=1000; } @@ -3935,6 +5266,10 @@ openair_rrc_eNB_init( , configuration #endif ); + for (int ue_id = 0; ue_id < NUMBER_OF_UE_MAX; ue_id++) { + RC.rrc[ctxt.module_id]->carrier[CC_id].sizeof_paging[ue_id] = 0; + RC.rrc[ctxt.module_id]->carrier[CC_id].paging[ue_id] = (uint8_t*) malloc16(256); + } } rrc_init_global_param(); @@ -4074,7 +5409,7 @@ rrc_eNB_decode_ccch( T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #ifdef RRC_MSG_PRINT - LOG_F(RRC,"[MSG] RRC Connection Reestablishement Request\n"); + LOG_F(RRC,"[MSG] RRC Connection Reestablishment Request\n"); for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) { LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]); @@ -4109,9 +5444,157 @@ rrc_eNB_decode_ccch( } */ /* reject all reestablishment attempts for the moment */ - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, - rrc_eNB_get_ue_context(RC.rrc[ctxt_pP->module_id], ctxt_pP->rnti), - CC_id); +// rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, +// rrc_eNB_get_ue_context(RC.rrc[ctxt_pP->module_id], ctxt_pP->rnti), +// CC_id); +{ + uint16_t c_rnti = 0; + + if (rrcConnectionReestablishmentRequest->ue_Identity.physCellId != RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId) { + LOG_E(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcConnectionReestablishmentRequest->ue_Identity.physCellId, + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + break; + } + LOG_D(RRC, "physCellId is %ld\n", rrcConnectionReestablishmentRequest->ue_Identity.physCellId); + + for (i = 0; i < rrcConnectionReestablishmentRequest->ue_Identity.shortMAC_I.size; i++) { + LOG_D(RRC, "rrcConnectionReestablishmentRequest->ue_Identity.shortMAC_I.buf[%d] = %x\n", + i, rrcConnectionReestablishmentRequest->ue_Identity.shortMAC_I.buf[i]); + } + + if (rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size == 0 || + rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size > 2) { + LOG_E(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest c_RNTI range error, let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + break; + + } + + c_rnti = BIT_STRING_to_uint16(&rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI); + LOG_D(RRC, "c_rnti is %x\n", c_rnti); + + ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt_pP->module_id], c_rnti); + if (ue_context_p == NULL) { + LOG_E(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest without UE context, let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + break; + } + int UE_id = find_UE_id(ctxt_pP->module_id, c_rnti); + if(ue_context_p->ue_context.ue_reestablishment_timer > 0 || RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0){ + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishment(Previous) don't complete, let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + break; + } + LOG_D(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" UE context: %p\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p); + ue_context_p->ue_context.ul_failure_timer = 0; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + ue_context_p->ue_context.ue_release_timer_s1 = 0; + ue_context_p->ue_context.ue_release_timer_rrc = 0; + + /* reset timers */ + ue_context_p->ue_context.ul_failure_timer = 0; + ue_context_p->ue_context.ue_release_timer = 0; + + // insert C-RNTI to map + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (reestablish_rnti_map[i][0] == 0) { + reestablish_rnti_map[i][0] = ctxt_pP->rnti; + reestablish_rnti_map[i][1] = c_rnti; + break; + } + } + LOG_D(RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + +#if defined(ENABLE_ITTI) + ue_context_p->ue_context.reestablishment_cause = rrcConnectionReestablishmentRequest->reestablishmentCause; + LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept connection reestablishment request from UE physCellId %ld cause %ld\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcConnectionReestablishmentRequest->ue_Identity.physCellId, + ue_context_p->ue_context.reestablishment_cause); +#else + LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept connection restablishment request for UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); +#endif + +#ifndef NO_RRM + send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id)); +#else + + ue_context_p->ue_context.primaryCC_id = CC_id; + + //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; + Idx = DCCH; + // SRB1 + ue_context_p->ue_context.Srb1.Active = 1; + ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + + // SRB2: set it to go through SRB1 with id 1 (DCCH) + ue_context_p->ue_context.Srb2.Active = 1; + ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + + rrc_eNB_generate_RRCConnectionReestablishment(ctxt_pP, ue_context_p, CC_id); + LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1 (rbid %d)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + Idx); + + MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, + MSC_PDCP_ENB, + NULL, + 0, + MSC_AS_TIME_FMT" CONFIG_REQ UE %x SRB", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti); + + rrc_pdcp_config_asn1_req(ctxt_pP, + ue_context_p->ue_context.SRB_configList, + (DRB_ToAddModList_t *) NULL, + (DRB_ToReleaseList_t*) NULL, + 0xff, + NULL, + NULL, + NULL +# if defined(Rel10) || defined(Rel14) + , (PMCH_InfoList_r9_t *) NULL +# endif + ,NULL); + + rrc_rlc_config_asn1_req(ctxt_pP, + ue_context_p->ue_context.SRB_configList, + (DRB_ToAddModList_t*) NULL, + (DRB_ToReleaseList_t*) NULL +# if defined(Rel10) || defined(Rel14) + , (PMCH_InfoList_r9_t *) NULL +# endif + ); +#endif //NO_RRM + } break; case UL_CCCH_MessageType__c1_PR_rrcConnectionRequest: @@ -4160,6 +5643,7 @@ rrc_eNB_decode_ccch( /* if there is already a registered UE (with another RNTI) with this random_value, * the current one must be removed from MAC/PHY (zombie UE) */ +#if 0 if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) { LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n", ctxt_pP->rnti, ue_context_p->ue_context.rnti, ctxt_pP->rnti); @@ -4169,6 +5653,13 @@ rrc_eNB_decode_ccch( } else { ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value); } +#endif + if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) { + LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n", + ctxt_pP->rnti, ue_context_p->ue_context.rnti, ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ul_failure_timer = 20000; + } + ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value); } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest->ue_Identity.present) { /* Save s-TMSI */ S_TMSI_t s_TMSI = rrcConnectionRequest->ue_Identity.choice.s_TMSI; @@ -4189,9 +5680,13 @@ rrc_eNB_decode_ccch( /* reset timers */ ue_context_p->ue_context.ul_failure_timer = 0; ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + ue_context_p->ue_context.ue_release_timer_s1 = 0; + ue_context_p->ue_context.ue_release_timer_rrc = 0; } else { LOG_I(RRC," S-TMSI doesn't exist, setting Initialue_identity_s_TMSI.m_tmsi to %p => %x\n",ue_context_p,m_tmsi); - ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); +// ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); + ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP,random_value); if (ue_context_p == NULL) LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__); if (ue_context_p != NULL) { @@ -4237,6 +5732,7 @@ rrc_eNB_decode_ccch( #if defined(ENABLE_ITTI) ue_context_p->ue_context.establishment_cause = rrcConnectionRequest->establishmentCause; + ue_context_p->ue_context.reestablishment_cause = ReestablishmentCause_spare1; if (stmsi_received==0) LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE random UE identity (0x%" PRIx64 ") MME code %u TMSI %u cause %ld\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -4369,6 +5865,12 @@ rrc_eNB_decode_dcch( UE_EUTRA_Capability_t *UE_EUTRA_Capability = NULL; int i; struct rrc_eNB_ue_context_s* ue_context_p = NULL; +#if defined(ENABLE_ITTI) +# if defined(ENABLE_USE_MME) + MessageDef * msg_delete_tunnels_p = NULL; + uint8_t xid; +#endif +#endif int dedicated_DRB=0; @@ -4529,12 +6031,60 @@ rrc_eNB_decode_dcch( # if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { if (dedicated_DRB == 1){ - rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, - ue_context_p, - ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); +// rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, +// ue_context_p, +// ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); +if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) { + rrc_eNB_send_S1AP_E_RAB_MODIFY_RESP(ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); + + ue_context_p->ue_context.nb_of_modify_e_rabs = 0; + ue_context_p->ue_context.nb_of_failed_e_rabs = 0; + memset(ue_context_p->ue_context.modify_e_rab, 0, sizeof(ue_context_p->ue_context.modify_e_rab)); + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_p->ue_context.modify_e_rab[i].xid = -1; + } + + } else if(ue_context_p->ue_context.e_rab_release_command_flag == 1){ + xid = ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier; + ue_context_p->ue_context.e_rab_release_command_flag = 0; + //gtp tunnel delete + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + for(i = 0; i < NB_RB_MAX; i++){ + if(xid == ue_context_p->ue_context.e_rab[i].xid){ + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] = ue_context_p->ue_context.enb_gtp_ebi[i]; + ue_context_p->ue_context.enb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.enb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[i])); + ue_context_p->ue_context.enb_gtp_ebi[i] = 0; + } + } + itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->instance, msg_delete_tunnels_p); + //S1AP_E_RAB_RELEASE_RESPONSE + rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(ctxt_pP, + ue_context_p, + xid); + } else { + rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); + } }else { - rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, + if(ue_context_p->ue_context.reestablishment_cause == ReestablishmentCause_spare1){ + rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + } else { + ue_context_p->ue_context.reestablishment_cause = ReestablishmentCause_spare1; + for (uint8_t e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) { + if (ue_context_p->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) { + ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED; + } else { + ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED; + } + } + } } } #else // establish a dedicated bearer @@ -4577,6 +6127,53 @@ rrc_eNB_decode_dcch( PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), DCCH, sdu_sizeP); + { + int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); + RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; + rnti_t reestablish_rnti = 0; + // select C-RNTI from map + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (reestablish_rnti_map[i][0] == ctxt_pP->rnti) { + reestablish_rnti = reestablish_rnti_map[i][1]; + ue_context_p = rrc_eNB_get_ue_context( + RC.rrc[ctxt_pP->module_id], + reestablish_rnti); + // clear currentC-RNTI from map + reestablish_rnti_map[i][0] = 0; + reestablish_rnti_map[i][1] = 0; + break; + } + } + LOG_D(RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + + if (!ue_context_p) { + LOG_E(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentComplete without UE context, falt\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + break; + } + + if (ul_dcch_msg->message.choice.c1.choice.rrcConnectionReestablishmentComplete.criticalExtensions.present == + RRCConnectionReestablishmentComplete__criticalExtensions_PR_rrcConnectionReestablishmentComplete_r8) { + rrc_eNB_process_RRCConnectionReestablishmentComplete(ctxt_pP, reestablish_rnti, ue_context_p, + ul_dcch_msg->message.choice.c1.choice.rrcConnectionReestablishmentComplete.rrc_TransactionIdentifier, + &ul_dcch_msg->message.choice.c1.choice.rrcConnectionReestablishmentComplete.criticalExtensions.choice.rrcConnectionReestablishmentComplete_r8); + +#if defined(FLEXRAN_AGENT_SB_IF) + //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future + if (mac_agent_registered[ctxt_pP->module_id]) { + agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id, + ue_context_p->ue_id_rnti, + PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED); + } +#endif + } + //ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 1; + // remove UE after 100 frames after RRCConnectionReestablishmentRelease is triggered + ue_context_p->ue_context.ue_reestablishment_timer_thres = 1000; + } break; case UL_DCCH_MessageType__c1_PR_rrcConnectionSetupComplete: @@ -5029,13 +6626,22 @@ rrc_enb_task( break; case S1AP_PAGING_IND: - LOG_E(RRC, "[eNB %d] Received not yet implemented message %s\n", instance, msg_name_p); + LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p); + rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance); break; case S1AP_E_RAB_SETUP_REQ: rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(msg_p, msg_name_p, instance); LOG_D(RRC, "[eNB %d] Received the message %s\n", instance, msg_name_p); break; + + case S1AP_E_RAB_MODIFY_REQ: + rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(msg_p, msg_name_p, instance); + break; + + case S1AP_E_RAB_RELEASE_COMMAND: + rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(msg_p, msg_name_p, instance); + break; case S1AP_UE_CONTEXT_RELEASE_REQ: rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance); @@ -5049,6 +6655,11 @@ rrc_enb_task( /* Nothing to do. Apparently everything is done in S1AP processing */ //LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n", //instance, msg_name_p); + if (rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti) + && rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0) { + rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc = + rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc; + } break; # endif diff --git a/openair2/RRC/LITE/rrc_eNB_GTPV1U.c b/openair2/RRC/LITE/rrc_eNB_GTPV1U.c index 9aca0491669e8b12899a738c6b8364ed4d853488..e5f2c5aaae1c469c4da1ffbcda1a41a0d7c264d4 100644 --- a/openair2/RRC/LITE/rrc_eNB_GTPV1U.c +++ b/openair2/RRC/LITE/rrc_eNB_GTPV1U.c @@ -47,7 +47,8 @@ extern RAN_CONTEXT_t RC; int rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t* const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP + const gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP, + uint8_t *inde_list ) { rnti_t rnti; @@ -66,15 +67,18 @@ rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { - ue_context_p->ue_context.enb_gtp_teid[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->enb_S1u_teid[i]; - ue_context_p->ue_context.enb_gtp_addrs[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->enb_addr; - ue_context_p->ue_context.enb_gtp_ebi[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->eps_bearer_id[i]; +// ue_context_p->ue_context.enb_gtp_teid[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->enb_S1u_teid[i]; +// ue_context_p->ue_context.enb_gtp_addrs[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->enb_addr; +// ue_context_p->ue_context.enb_gtp_ebi[i+ue_context_p->ue_context.setup_e_rabs] = create_tunnel_resp_pP->eps_bearer_id[i]; + ue_context_p->ue_context.enb_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->enb_S1u_teid[i]; + ue_context_p->ue_context.enb_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->enb_addr; + ue_context_p->ue_context.enb_gtp_ebi[inde_list[i]] = create_tunnel_resp_pP->eps_bearer_id[i]; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp addr len %d \n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->enb_S1u_teid[i], - ue_context_p->ue_context.enb_gtp_teid[i+ue_context_p->ue_context.setup_e_rabs], - i+ue_context_p->ue_context.setup_e_rabs, + ue_context_p->ue_context.enb_gtp_teid[inde_list[i]], + inde_list[i], i, create_tunnel_resp_pP->eps_bearer_id[i], create_tunnel_resp_pP->enb_addr.length); diff --git a/openair2/RRC/LITE/rrc_eNB_GTPV1U.h b/openair2/RRC/LITE/rrc_eNB_GTPV1U.h index 981c3f8d3ba8b1379c0f997c5a89f09513036226..aedbdeac5e12bdd510ad5d286f3d82bf4cab83f2 100644 --- a/openair2/RRC/LITE/rrc_eNB_GTPV1U.h +++ b/openair2/RRC/LITE/rrc_eNB_GTPV1U.h @@ -43,7 +43,8 @@ int rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t* const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP + const gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP, + uint8_t *inde_list ); # endif diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 24ee3c06dafa7a46b8920697db8969b87a806f55..d2c0d0acbe8f7375370fdc3699af8f6d6be1ca86 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -342,6 +342,8 @@ static void process_eNB_security_key ( /* Saves the security key */ memcpy (ue_context_pP->ue_context.kenb, security_key_pP, SECURITY_KEY_LENGTH); + memset (ue_context_pP->ue_context.nh, 0, SECURITY_KEY_LENGTH); + ue_context_pP->ue_context.nh_ncc = -1; for (i = 0; i < 32; i++) { sprintf(&ascii_buffer[2 * i], "%02X", ue_context_pP->ue_context.kenb[i]); @@ -355,7 +357,7 @@ static void process_eNB_security_key ( //------------------------------------------------------------------------------ -static void +void rrc_pdcp_config_security( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, @@ -892,6 +894,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char //MessageDef *message_gtpv1u_p = NULL; gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; + uint8_t inde_list[NB_RB_MAX - 3]={0}; struct rrc_eNB_ue_context_s* ue_context_p = NULL; protocol_ctxt_t ctxt; @@ -937,10 +940,12 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char memcpy(&create_tunnel_req.sgw_addr[i], &S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].sgw_addr, sizeof(transport_layer_addr_t)); + inde_list[create_tunnel_req.num_tunnels]= i; + create_tunnel_req.num_tunnels++; } create_tunnel_req.rnti = ue_context_p->ue_context.rnti; // warning put zero above - create_tunnel_req.num_tunnels = i; +// create_tunnel_req.num_tunnels = i; gtpv1u_create_s1u_tunnel( instance, @@ -949,7 +954,8 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( &ctxt, - &create_tunnel_resp); + &create_tunnel_resp, + &inde_list[0]); ue_context_p->ue_context.setup_e_rabs=ue_context_p->ue_context.nb_of_e_rabs; } @@ -1191,6 +1197,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch } return (-1); } else { + ue_context_p->ue_context.ue_release_timer_s1 = 0; PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context_p); /* @@ -1265,9 +1272,12 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name uint32_t eNB_ue_s1ap_id; gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; + uint8_t inde_list[NB_RB_MAX - 3]={0}; struct rrc_eNB_ue_context_s* ue_context_p = NULL; protocol_ctxt_t ctxt; + uint8_t e_rab_done; + ue_initial_id = S1AP_E_RAB_SETUP_REQ (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_E_RAB_SETUP_REQ (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); @@ -1298,35 +1308,46 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req)); uint8_t nb_e_rabs_tosetup = S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup; + e_rab_done = 0; // keep the previous bearer // the index for the rec for (i = 0; - i < nb_e_rabs_tosetup; + // i < nb_e_rabs_tosetup; + i < NB_RB_MAX - 3; // loop all e-rabs in e_rab[] i++) { - if (ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].status == E_RAB_STATUS_DONE) - LOG_W(RRC,"E-RAB already configured, reconfiguring\n"); - ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].status = E_RAB_STATUS_NEW; - ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].param = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i]; - + //if (ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].status == E_RAB_STATUS_DONE) + // LOG_W(RRC,"E-RAB already configured, reconfiguring\n"); + // check e-rab status, if e rab status is greater than E_RAB_STATUS_DONE, don't not config this one + if(ue_context_p->ue_context.e_rab[i].status >= E_RAB_STATUS_DONE) + continue; + //ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].status = E_RAB_STATUS_NEW; + //ue_context_p->ue_context.e_rab[i+ue_context_p->ue_context.setup_e_rabs].param = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i]; + ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.e_rab[i].param = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[e_rab_done]; - create_tunnel_req.eps_bearer_id[i] = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i].e_rab_id; - create_tunnel_req.sgw_S1u_teid[i] = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i].gtp_teid; + create_tunnel_req.eps_bearer_id[e_rab_done] = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[e_rab_done].e_rab_id; + create_tunnel_req.sgw_S1u_teid[e_rab_done] = S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[e_rab_done].gtp_teid; - memcpy(&create_tunnel_req.sgw_addr[i], - & S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i].sgw_addr, + memcpy(&create_tunnel_req.sgw_addr[e_rab_done], + & S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[e_rab_done].sgw_addr, sizeof(transport_layer_addr_t)); LOG_I(RRC,"E_RAB setup REQ: local index %d teid %u, eps id %d \n", - i+ue_context_p->ue_context.setup_e_rabs, - create_tunnel_req.sgw_S1u_teid[i], + i, + create_tunnel_req.sgw_S1u_teid[e_rab_done], create_tunnel_req.eps_bearer_id[i] ); + inde_list[e_rab_done] = i; + e_rab_done++; + if(e_rab_done >= nb_e_rabs_tosetup){ + break; + } } ue_context_p->ue_context.nb_of_e_rabs=nb_e_rabs_tosetup; create_tunnel_req.rnti = ue_context_p->ue_context.rnti; // warning put zero above - create_tunnel_req.num_tunnels = i; + create_tunnel_req.num_tunnels = e_rab_done; // NN: not sure if we should create a new tunnel: need to check teid, etc. gtpv1u_create_s1u_tunnel( @@ -1336,7 +1357,8 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( &ctxt, - &create_tunnel_resp); + &create_tunnel_resp, + &inde_list[0]); ue_context_p->ue_context.setup_e_rabs+=nb_e_rabs_tosetup; @@ -1400,12 +1422,17 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP, S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs_failed[e_rabs_failed].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; e_rabs_failed++; // TODO add cause when it will be integrated - } - + } S1AP_E_RAB_SETUP_RESP (msg_p).nb_of_e_rabs = e_rabs_done; S1AP_E_RAB_SETUP_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed; // NN: add conditions for e_rabs_failed + } else { + /*debug info for the xid */ + LOG_D(RRC,"xid does not corresponds (context e_rab index %d, status %d, xid %d/%d) \n ", + e_rab, ue_context_pP->ue_context.e_rab[e_rab].status, xid, ue_context_pP->ue_context.e_rab[e_rab].xid); + } + } if ((e_rabs_done > 0) ){ LOG_I(RRC,"S1AP_E_RAB_SETUP_RESP: sending the message: nb_of_erabs %d, total e_rabs %d, index %d\n", @@ -1424,17 +1451,528 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP, itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p); } + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.e_rab[i].xid = -1; + } + + return 0; +} + +int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance) +{ + int i; + uint16_t ue_initial_id; + uint32_t eNB_ue_s1ap_id; + struct rrc_eNB_ue_context_s* ue_context_p = NULL; + protocol_ctxt_t ctxt; + + ue_initial_id = S1AP_E_RAB_MODIFY_REQ (msg_p).ue_initial_id; + eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; + ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); + LOG_D(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", + instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify); + + if (ue_context_p == NULL) { + /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ + LOG_W(RRC, "[eNB %d] In S1AP_E_RAB_MODIFY_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + int nb_of_e_rabs_failed = 0; + MessageDef *msg_fail_p = NULL; + + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs = 0; + + for (nb_of_e_rabs_failed = 0; nb_of_e_rabs_failed < S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; nb_of_e_rabs_failed++) { + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs_failed[nb_of_e_rabs_failed].e_rab_id = + S1AP_E_RAB_MODIFY_REQ (msg_p).e_rab_modify_params[nb_of_e_rabs_failed].e_rab_id; + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs_failed[nb_of_e_rabs_failed].cause = S1AP_CAUSE_RADIO_NETWORK; + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = 31;//S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances; + } + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs_failed = nb_of_e_rabs_failed; + + itti_send_msg_to_task(TASK_S1AP, instance, msg_fail_p); + return (-1); + + } else { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + ue_context_p->ue_context.eNB_ue_s1ap_id = eNB_ue_s1ap_id; + + /* Save e RAB information for later */ + { + int j; + boolean_t is_treated[S1AP_MAX_E_RAB] = {FALSE}; + uint8_t nb_of_failed_e_rabs = 0; + + // keep the previous bearer + // the index for the rec + for (i = 0; i < S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; i++) { + if (is_treated[i] == TRUE) { + // already treated + continue; + } + for (j = i+1; j < S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; j++) { + if (is_treated[j] == FALSE && + S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[j].e_rab_id == S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id) { + // handle multiple E-RAB ID + ue_context_p->ue_context.modify_e_rab[j].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.modify_e_rab[j].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[j].e_rab_id; + ue_context_p->ue_context.modify_e_rab[j].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.modify_e_rab[j].cause_value = 31;//S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances; + nb_of_failed_e_rabs++; + is_treated[i] = TRUE; + is_treated[j] = TRUE; + } + } + if (is_treated[i] == TRUE) { + // handle multiple E-RAB ID + ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; + ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.modify_e_rab[i].cause_value = 31;//S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances; + nb_of_failed_e_rabs++; + continue; + } + + if (S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].nas_pdu.length == 0) { + // nas_pdu.length == 0 + ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; + ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_NAS; + ue_context_p->ue_context.modify_e_rab[i].cause_value = 3;//S1ap_CauseNas_unspecified; + nb_of_failed_e_rabs++; + is_treated[i] = TRUE; + continue; + } + + for (j = 0; j < NB_RB_MAX-3; j++) { + if (ue_context_p->ue_context.e_rab[j].param.e_rab_id == S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id) { + if(ue_context_p->ue_context.e_rab[j].status == E_RAB_STATUS_TORELEASE || ue_context_p->ue_context.e_rab[j].status == E_RAB_STATUS_DONE){ + break; + } + ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_NOTHING; + ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; + ue_context_p->ue_context.modify_e_rab[i].param.qos = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].qos; + ue_context_p->ue_context.modify_e_rab[i].param.nas_pdu.length = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].nas_pdu.length; + ue_context_p->ue_context.modify_e_rab[i].param.nas_pdu.buffer = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].nas_pdu.buffer; + ue_context_p->ue_context.modify_e_rab[i].param.sgw_addr = ue_context_p->ue_context.e_rab[j].param.sgw_addr; + ue_context_p->ue_context.modify_e_rab[i].param.gtp_teid = ue_context_p->ue_context.e_rab[j].param.gtp_teid; + + is_treated[i] = TRUE; + break; + } + } + + if (is_treated[i] == FALSE) { + // handle Unknown E-RAB ID + ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; + ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.modify_e_rab[i].cause_value = 30;//S1ap_CauseRadioNetwork_unknown_E_RAB_ID; + nb_of_failed_e_rabs++; + is_treated[i] = TRUE; + } + } + + ue_context_p->ue_context.nb_of_modify_e_rabs = S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; + ue_context_p->ue_context.nb_of_failed_e_rabs = nb_of_failed_e_rabs; + } + + /* TODO parameters yet to process ... */ + { + // S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_ambr; + } + + if (ue_context_p->ue_context.nb_of_failed_e_rabs < ue_context_p->ue_context.nb_of_modify_e_rabs) { + if (0 == rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0)) { + return (0); + } + } + + { + int nb_of_e_rabs_failed = 0; + MessageDef *msg_fail_p = NULL; + + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; +// S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs[S1AP_MAX_E_RAB]; + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs = 0; + + for(nb_of_e_rabs_failed = 0; nb_of_e_rabs_failed < ue_context_p->ue_context.nb_of_failed_e_rabs; nb_of_e_rabs_failed++) { + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs_failed[nb_of_e_rabs_failed].e_rab_id = + ue_context_p->ue_context.modify_e_rab[nb_of_e_rabs_failed].param.e_rab_id; + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs_failed[nb_of_e_rabs_failed].cause = ue_context_p->ue_context.modify_e_rab[nb_of_e_rabs_failed].cause; + } + S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs_failed = nb_of_e_rabs_failed; + + itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p); + + ue_context_p->ue_context.nb_of_modify_e_rabs = 0; + ue_context_p->ue_context.nb_of_failed_e_rabs = 0; + memset(ue_context_p->ue_context.modify_e_rab, 0, sizeof(ue_context_p->ue_context.modify_e_rab)); + + return (0); + } + } // end of ue_context_p != NULL +} + +/*NN: careful about the typcast of xid (long -> uint8_t*/ +int rrc_eNB_send_S1AP_E_RAB_MODIFY_RESP(const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + uint8_t xid ) { + + MessageDef *msg_p = NULL; + int i; + int e_rab; + int e_rabs_done = 0; + int e_rabs_failed = 0; + msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + S1AP_E_RAB_MODIFY_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; + + for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_modify_e_rabs; e_rab++) { + + /* only respond to the corresponding transaction */ + if (xid == ue_context_pP->ue_context.modify_e_rab[e_rab].xid) { + if (ue_context_pP->ue_context.modify_e_rab[e_rab].status == E_RAB_STATUS_DONE) { + for (i = 0; i < ue_context_pP->ue_context.setup_e_rabs; i++) { + if (ue_context_pP->ue_context.modify_e_rab[e_rab].param.e_rab_id == ue_context_pP->ue_context.e_rab[i].param.e_rab_id) { + // Update ue_context_pP->ue_context.e_rab + ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_ESTABLISHED; + ue_context_pP->ue_context.e_rab[i].param.qos = ue_context_pP->ue_context.modify_e_rab[e_rab].param.qos; + ue_context_pP->ue_context.e_rab[i].cause = S1AP_CAUSE_NOTHING; + break; + } + } + if (i < ue_context_pP->ue_context.setup_e_rabs) { + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs[e_rabs_done].e_rab_id = ue_context_pP->ue_context.modify_e_rab[e_rab].param.e_rab_id; + // TODO add other information from S1-U when it will be integrated + + LOG_D (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d, xid %d): nb_of_modify_e_rabs %d, e_rab_id %d \n ", + e_rabs_done, e_rab, ue_context_pP->ue_context.modify_e_rab[e_rab].status, xid, + ue_context_pP->ue_context.nb_of_modify_e_rabs, + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs[e_rabs_done].e_rab_id); + e_rabs_done++; + } else { + // unexpected + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs_failed[e_rabs_failed].e_rab_id = ue_context_pP->ue_context.modify_e_rab[e_rab].param.e_rab_id; + + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs_failed[e_rabs_failed].cause = S1AP_CAUSE_RADIO_NETWORK; + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs_failed[e_rabs_failed].cause_value = 30;//S1ap_CauseRadioNetwork_unknown_E_RAB_ID; + + e_rabs_failed++; + } + } else if ((ue_context_pP->ue_context.modify_e_rab[e_rab].status == E_RAB_STATUS_NEW) || + (ue_context_pP->ue_context.modify_e_rab[e_rab].status == E_RAB_STATUS_ESTABLISHED)){ + LOG_D (RRC,"E-RAB is NEW or already ESTABLISHED\n"); + } else { /* status == E_RAB_STATUS_FAILED; */ + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs_failed[e_rabs_failed].e_rab_id = ue_context_pP->ue_context.modify_e_rab[e_rab].param.e_rab_id; + // add failure cause when defined + S1AP_E_RAB_MODIFY_RESP (msg_p).e_rabs_failed[e_rabs_failed].cause = ue_context_pP->ue_context.modify_e_rab[e_rab].cause; + + e_rabs_failed++; + } } else { - /*debug info for the xid */ + /*debug info for the xid */ LOG_D(RRC,"xid does not corresponds (context e_rab index %d, status %d, xid %d/%d) \n ", - e_rab, ue_context_pP->ue_context.e_rab[e_rab].status, xid, ue_context_pP->ue_context.e_rab[e_rab].xid); + e_rab, ue_context_pP->ue_context.modify_e_rab[e_rab].status, xid, ue_context_pP->ue_context.modify_e_rab[e_rab].xid); } - } - + + + S1AP_E_RAB_MODIFY_RESP (msg_p).nb_of_e_rabs = e_rabs_done; + S1AP_E_RAB_MODIFY_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed; + // NN: add conditions for e_rabs_failed + if (e_rabs_done > 0 || e_rabs_failed > 0) { + LOG_D(RRC,"S1AP_E_RAB_MODIFY_RESP: sending the message: nb_of_modify_e_rabs %d, total e_rabs %d, index %d\n", + ue_context_pP->ue_context.nb_of_modify_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab); +MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_S1AP_ENB, + (const char *)&S1AP_E_RAB_SETUP_RESP (msg_p), + sizeof(s1ap_e_rab_setup_resp_t), + MSC_AS_TIME_FMT" E_RAB_MODIFY_RESP UE %X eNB_ue_s1ap_id %u e_rabs:%u succ %u fail", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_id_rnti, + S1AP_E_RAB_MODIFY_RESP (msg_p).eNB_ue_s1ap_id, + e_rabs_done, e_rabs_failed); + + itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p); + } + return 0; } +int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *msg_name, instance_t instance){ + uint16_t mme_ue_s1ap_id; + uint32_t eNB_ue_s1ap_id; + struct rrc_eNB_ue_context_s* ue_context_p = NULL; + protocol_ctxt_t ctxt; + e_rab_release_t e_rab_release_params[S1AP_MAX_E_RAB]; + uint8_t nb_e_rabs_torelease; + int erab; + int i; + uint8_t b_existed,is_existed; + uint8_t xid; + uint8_t e_rab_release_drb; + MessageDef * msg_delete_tunnels_p = NULL; + e_rab_release_drb = 0; + memcpy(&e_rab_release_params[0], &(S1AP_E_RAB_RELEASE_COMMAND (msg_p).e_rab_release_params[0]), sizeof(e_rab_release_t)*S1AP_MAX_E_RAB); + + mme_ue_s1ap_id = S1AP_E_RAB_RELEASE_COMMAND (msg_p).mme_ue_s1ap_id; + eNB_ue_s1ap_id = S1AP_E_RAB_RELEASE_COMMAND (msg_p).eNB_ue_s1ap_id; + nb_e_rabs_torelease = S1AP_E_RAB_RELEASE_COMMAND (msg_p).nb_e_rabs_torelease; + ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id); + if(ue_context_p != NULL){ + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + + xid = rrc_eNB_get_next_transaction_identifier(ctxt.module_id); + + LOG_D(RRC,"S1AP-E-RAB Release Command: MME_UE_S1AP_ID %d ENB_UE_S1AP_ID %d release_e_rabs %d \n", + mme_ue_s1ap_id, eNB_ue_s1ap_id,nb_e_rabs_torelease); + for(erab = 0; erab < nb_e_rabs_torelease; erab++){ + b_existed = 0; + is_existed = 0; + for ( i = erab-1; i>= 0; i--){ + if (e_rab_release_params[erab].e_rab_id == e_rab_release_params[i].e_rab_id){ + is_existed = 1; + break; + } + } + if(is_existed == 1){ + //e_rab_id is existed + continue; + } + for ( i = 0; i < NB_RB_MAX; i++){ + if (e_rab_release_params[erab].e_rab_id == ue_context_p->ue_context.e_rab[i].param.e_rab_id){ + b_existed = 1; + break; + } + } + if(b_existed == 0) { + //no e_rab_id + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].e_rab_id = e_rab_release_params[erab].e_rab_id; + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].cause_value = 30; + ue_context_p->ue_context.nb_release_of_e_rabs++; + } else { + if(ue_context_p->ue_context.e_rab[i].status == E_RAB_STATUS_FAILED){ + ue_context_p->ue_context.e_rab[i].xid = xid; + continue; + } else if(ue_context_p->ue_context.e_rab[i].status == E_RAB_STATUS_ESTABLISHED){ + ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE; + ue_context_p->ue_context.e_rab[i].xid = xid; + e_rab_release_drb++; + }else{ + //e_rab_id status NG + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].e_rab_id = e_rab_release_params[erab].e_rab_id; + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].cause = S1AP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.e_rabs_release_failed[ue_context_p->ue_context.nb_release_of_e_rabs].cause_value = 0; + ue_context_p->ue_context.nb_release_of_e_rabs++; + } + } + } + if(e_rab_release_drb > 0) { + //RRCConnectionReconfiguration To UE + rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release(&ctxt, ue_context_p, xid, S1AP_E_RAB_RELEASE_COMMAND (msg_p).nas_pdu.length, S1AP_E_RAB_RELEASE_COMMAND (msg_p).nas_pdu.buffer); + } else { + //gtp tunnel delete + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + for(i = 0; i < NB_RB_MAX; i++){ + if(xid == ue_context_p->ue_context.e_rab[i].xid){ + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] = ue_context_p->ue_context.enb_gtp_ebi[i]; + ue_context_p->ue_context.enb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.enb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[i])); + ue_context_p->ue_context.enb_gtp_ebi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p); + + //S1AP_E_RAB_RELEASE_RESPONSE + rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(&ctxt, ue_context_p, xid); + } + } else { + LOG_E(RRC,"S1AP-E-RAB Release Command: MME_UE_S1AP_ID %d ENB_UE_S1AP_ID %d Error ue_context_p NULL \n", + S1AP_E_RAB_RELEASE_COMMAND (msg_p).mme_ue_s1ap_id, S1AP_E_RAB_RELEASE_COMMAND (msg_p).eNB_ue_s1ap_id); + return -1; + } + + return 0; +} + + +int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid){ + int e_rabs_released = 0; + MessageDef *msg_p; + + msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_RELEASE_RESPONSE); + S1AP_E_RAB_RELEASE_RESPONSE (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; + + for (int i = 0; i < NB_RB_MAX; i++){ + if (xid == ue_context_pP->ue_context.e_rab[i].xid){ + S1AP_E_RAB_RELEASE_RESPONSE (msg_p).e_rab_release[e_rabs_released].e_rab_id = ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + e_rabs_released++; + //clear + memset(&ue_context_pP->ue_context.e_rab[i],0,sizeof(e_rab_param_t)); + } + } + S1AP_E_RAB_RELEASE_RESPONSE (msg_p).nb_of_e_rabs_released = e_rabs_released; + S1AP_E_RAB_RELEASE_RESPONSE (msg_p).nb_of_e_rabs_failed = ue_context_pP->ue_context.nb_release_of_e_rabs; + memcpy(&(S1AP_E_RAB_RELEASE_RESPONSE (msg_p).e_rabs_failed[0]),&ue_context_pP->ue_context.e_rabs_release_failed[0],sizeof(e_rab_failed_t)*ue_context_pP->ue_context.nb_release_of_e_rabs); + + ue_context_pP->ue_context.setup_e_rabs -= e_rabs_released; + LOG_I(RRC,"S1AP-E-RAB RELEASE RESPONSE: ENB_UE_S1AP_ID %d release_e_rabs %d setup_e_rabs %d \n", + S1AP_E_RAB_RELEASE_RESPONSE (msg_p).eNB_ue_s1ap_id, + e_rabs_released, ue_context_pP->ue_context.setup_e_rabs); + + itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p); + //clear xid + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.e_rab[i].xid = -1; + } + //clear release e_rabs + ue_context_pP->ue_context.nb_release_of_e_rabs = 0; + memset(&ue_context_pP->ue_context.e_rabs_release_failed[0],0,sizeof(e_rab_failed_t)*S1AP_MAX_E_RAB); + return 0; +} + +/*------------------------------------------------------------------------------*/ +int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance_t instance) +{ + const unsigned int Ttab[4] = {32,64,128,256}; + uint8_t Tc,Tue; /* DRX cycle of UE */ + uint32_t pcch_nB; /* 4T, 2T, T, T/2, T/4, T/8, T/16, T/32 */ + uint32_t N; /* N: min(T,nB). total count of PF in one DRX cycle */ + uint32_t Ns = 0; /* Ns: max(1,nB/T) */ + uint8_t i_s; /* i_s = floor(UE_ID/N) mod Ns */ + uint32_t T; /* DRX cycle */ + for (uint16_t tai_size = 0; tai_size < S1AP_PAGING_IND(msg_p).tai_size; tai_size++) { + LOG_D(RRC,"[eNB %d] In S1AP_PAGING_IND: MCC %d, MNC %d, TAC %d\n", instance, S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc, + S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc, S1AP_PAGING_IND(msg_p).tac[tai_size]); + if (RC.rrc[instance]->configuration.mcc == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc + && RC.rrc[instance]->configuration.mnc == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc + && RC.rrc[instance]->configuration.tac == S1AP_PAGING_IND(msg_p).tac[tai_size]) { + for (uint8_t CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + lte_frame_type_t frame_type = RC.eNB[instance][CC_id]->frame_parms.frame_type; + /* get nB from configuration */ + /* get default DRX cycle from configuration */ + Tc = (uint8_t)RC.rrc[instance]->configuration.pcch_defaultPagingCycle[CC_id]; + if (Tc < PCCH_Config__defaultPagingCycle_rf32 || Tc > PCCH_Config__defaultPagingCycle_rf256) { + continue; + } + Tue = (uint8_t)S1AP_PAGING_IND(msg_p).paging_drx; + /* set T = min(Tc,Tue) */ + T = Tc < Tue ? Ttab[Tc] : Ttab[Tue]; + /* set pcch_nB = PCCH-Config->nB */ + pcch_nB = (uint32_t)RC.rrc[instance]->configuration.pcch_nB[CC_id]; + switch (pcch_nB) { + case PCCH_Config__nB_fourT: + Ns = 4; + break; + case PCCH_Config__nB_twoT: + Ns = 2; + break; + default: + Ns = 1; + break; + } + /* set N = min(T,nB) */ + if (pcch_nB > PCCH_Config__nB_oneT) { + switch (pcch_nB) { + case PCCH_Config__nB_halfT: + N = T/2; + break; + case PCCH_Config__nB_quarterT: + N = T/4; + break; + case PCCH_Config__nB_oneEighthT: + N = T/8; + break; + case PCCH_Config__nB_oneSixteenthT: + N = T/16; + break; + case PCCH_Config__nB_oneThirtySecondT: + N = T/32; + break; + default: + /* pcch_nB error */ + LOG_E(RRC, "[eNB %d] In S1AP_PAGING_IND: pcch_nB error (pcch_nB %d) \n", + instance, pcch_nB); + return (-1); + } + } else { + N = T; + } + + /* insert data to UE_PF_PO or update data in UE_PF_PO */ + pthread_mutex_lock(&ue_pf_po_mutex); + uint8_t i = 0; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if ((UE_PF_PO[CC_id][i].enable_flag == TRUE && UE_PF_PO[CC_id][i].ue_index_value == (uint16_t)(S1AP_PAGING_IND(msg_p).ue_index_value)) + || (UE_PF_PO[CC_id][i].enable_flag != TRUE)) { + /* set T = min(Tc,Tue) */ + UE_PF_PO[CC_id][i].T = T; + /* set UE_ID */ + UE_PF_PO[CC_id][i].ue_index_value = (uint16_t)S1AP_PAGING_IND(msg_p).ue_index_value; + /* calculate PF and PO */ + /* set PF_min : SFN mod T = (T div N)*(UE_ID mod N) */ + UE_PF_PO[CC_id][i].PF_min = (T / N) * (UE_PF_PO[CC_id][i].ue_index_value % N); + /* set PO */ + /* i_s = floor(UE_ID/N) mod Ns */ + i_s = (uint8_t)((UE_PF_PO[CC_id][i].ue_index_value / N) % Ns); + if (Ns == 1) { + UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? 9 : 0; + } else if (Ns==2) { + UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4+(5*i_s)) : (5*i_s); + } else if (Ns==4) { + UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4*(i_s&1)+(5*(i_s>>1))) : ((i_s&1)+(5*(i_s>>1))); + } + if (UE_PF_PO[CC_id][i].enable_flag == TRUE) { + //paging exist UE log + LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); + } else { + /* set enable_flag */ + UE_PF_PO[CC_id][i].enable_flag = TRUE; + //paging new UE log + LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); + } + break; + } + } + pthread_mutex_unlock(&ue_pf_po_mutex); + + uint32_t length; + uint8_t buffer[RRC_BUF_SIZE]; + uint8_t *message_buffer; + /* Transfer data to PDCP */ + MessageDef *message_p; + message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_PCCH_DATA_REQ); + /* Create message for PDCP (DLInformationTransfer_t) */ + length = do_Paging (instance, + buffer, + S1AP_PAGING_IND(msg_p).ue_paging_identity, + S1AP_PAGING_IND(msg_p).cn_domain); + message_buffer = itti_malloc (TASK_RRC_ENB, TASK_PDCP_ENB, length); + /* Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). */ + memcpy (message_buffer, buffer, length); + RRC_PCCH_DATA_REQ (message_p).sdu_size = length; + RRC_PCCH_DATA_REQ (message_p).sdu_p = message_buffer; + RRC_PCCH_DATA_REQ (message_p).mode = PDCP_TRANSMISSION_MODE_TRANSPARENT; /* not used */ + RRC_PCCH_DATA_REQ (message_p).rnti = P_RNTI; + RRC_PCCH_DATA_REQ (message_p).ue_index = i; + RRC_PCCH_DATA_REQ (message_p).CC_id = CC_id; + LOG_D(RRC, "[eNB %d] CC_id %d In S1AP_PAGING_IND: send encdoed buffer to PDCP buffer_size %d\n", instance, CC_id, length); + itti_send_msg_to_task (TASK_PDCP_ENB, instance, message_p); + } + } + } + + return (0); +} # endif /* defined(ENABLE_ITTI) */ #endif /* defined(ENABLE_USE_MME) */ diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.h b/openair2/RRC/LITE/rrc_eNB_S1AP.h index 6b2de919bd44403e4e3ae99229c41e4d47668fed..a924caf254c664159089e1bcf27579bbbb687b67 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.h +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.h @@ -79,6 +79,11 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co const uint8_t ho_state ); +int +rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const uint8_t ho_state + ); /*! \fn void rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(uint8_t mod_id, uint8_t ue_index) *\brief create a S1AP_INITIAL_CONTEXT_SETUP_RESP for S1AP. @@ -186,6 +191,24 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name */ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ); +/*! \fn rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance); + *\brief process a S1AP dedicated E_RAB modify request message received from S1AP. + *\param msg_p Message received by RRC. + *\param msg_name Message name. + *\param instance Message instance. + *\return 0 when successful, -1 if the UE index can not be retrieved. + */ +int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance); + +/*! \fn rrc_eNB_send_S1AP_E_RAB_MODIFY_RESP(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ) + *\brief send a S1AP dedicated E_RAB modify response + *\param ctxt_pP contxt infirmation + *\param e_contxt_pP ue specific context at the eNB + *\param xid transaction identifier + *\return 0 when successful, -1 if the UE index can not be retrieved. + */ +int rrc_eNB_send_S1AP_E_RAB_MODIFY_RESP(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ); + /*! \fn rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance) *\brief process a S1AP_UE_CTXT_MODIFICATION_REQ message received from S1AP. *\param msg_p Message received by RRC. @@ -213,6 +236,39 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * */ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance); +/*! \fn rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance_t instance) + *\brief process a S1AP_PAGING_IND message received from S1AP. + *\param msg_p Message received by RRC. + *\param msg_name Message name. + *\param instance Message instance. + *\return 0 when successful, -1 if the UE index can not be retrieved. + */ +int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance_t instance); + +void +rrc_pdcp_config_security( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const uint8_t send_security_mode_command +); +/*! \fn rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *msg_name, instance_t instance); + *\brief process a S1AP dedicated E_RAB release command message received from S1AP. + *\param msg_p Message received by RRC. + *\param msg_name Message name. + *\param instance Message instance. + *\return 0 when successful, -1 if the UE index can not be retrieved. + */ +int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *msg_name, instance_t instance); + +/*! \fn rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ) + *\brief send a S1AP dedicated E_RAB release response + *\param ctxt_pP contxt infirmation + *\param e_contxt_pP ue specific context at the eNB + *\param xid transaction identifier + *\return 0 when successful, -1 if the UE index can not be retrieved. + */ +int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid ); + # endif # endif /* defined(ENABLE_USE_MME) */ #endif /* RRC_ENB_S1AP_H_ */ diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context.c b/openair2/RRC/LITE/rrc_eNB_UE_context.c index 78f85a6da2cffeac00853e13964abcf3ae6bff20..0ae3d7ca151fbed5b997f51ac09b5bde03f1e0c6 100644 --- a/openair2/RRC/LITE/rrc_eNB_UE_context.c +++ b/openair2/RRC/LITE/rrc_eNB_UE_context.c @@ -136,6 +136,10 @@ rrc_eNB_allocate_new_UE_context( memset(new_p, 0, sizeof(struct rrc_eNB_ue_context_s)); new_p->local_uid = uid_linear_allocator_new(rrc_instance_pP); + for(int i = 0; i < NB_RB_MAX; i++) { + new_p->ue_context.e_rab[i].xid = -1; + new_p->ue_context.modify_e_rab[i].xid = -1; + } return new_p; } @@ -151,7 +155,21 @@ rrc_eNB_get_ue_context( memset(&temp, 0, sizeof(struct rrc_eNB_ue_context_s)); /* eNB ue rrc id = 24 bits wide */ temp.ue_id_rnti = rntiP; +#if 0 return RB_FIND(rrc_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp); +#endif + struct rrc_eNB_ue_context_s *ue_context_p = NULL; + ue_context_p = RB_FIND(rrc_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp); + if ( ue_context_p != NULL) { + return ue_context_p; + } else { + RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) { + if (ue_context_p->ue_context.rnti == rntiP) { + return ue_context_p; + } + } + return NULL; + } } @@ -184,6 +202,7 @@ void rrc_eNB_remove_ue_context( rrc_eNB_free_mem_UE_context(ctxt_pP, ue_context_pP); uid_linear_allocator_free(rrc_instance_pP, ue_context_pP->local_uid); free(ue_context_pP); + rrc_instance_pP->Nb_ue --; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Removed UE context\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); diff --git a/openair2/RRC/LITE/vars.h b/openair2/RRC/LITE/vars.h index fbf3ae1dff944696e7e1ef745e23315aaec83971..e3bab5f5eb48aa577400a62d92d1397ab2ed25cf 100644 --- a/openair2/RRC/LITE/vars.h +++ b/openair2/RRC/LITE/vars.h @@ -36,6 +36,8 @@ #include "COMMON/mac_rrc_primitives.h" #include "LAYER2/MAC/defs.h" +UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +pthread_mutex_t ue_pf_po_mutex; UE_RRC_INST *UE_rrc_inst; #include "LAYER2/MAC/extern.h" #define MAX_U32 0xFFFFFFFF @@ -236,4 +238,10 @@ float RSRQ_meas_mapping[35] = { -2 }; +// only used for RRC connection re-establishment procedure TS36.331 5.3.7 +// [0]: current C-RNTI, [1]: prior C-RNTI +// insert one when eNB received RRCConnectionReestablishmentRequest message +// delete one when eNB received RRCConnectionReestablishmentComplete message +uint16_t reestablish_rnti_map[NUMBER_OF_UE_MAX][2] = {{0}}; + #endif diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c index aacfa561fd62190031d5ea2d0ca9603ea390f109..4234bc373d70a725414c60706b97aa9b5bbe63ea 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB.c +++ b/openair3/GTPV1-U/gtpv1u_eNB.c @@ -767,6 +767,7 @@ gtpv1u_create_s1u_tunnel( gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB = s1u_teid; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession; gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_sgw = create_tunnel_req_pP->sgw_S1u_teid[i]; + gtpv1u_ue_data_p->num_bearers++; create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid; } else { @@ -808,7 +809,88 @@ gtpv1u_create_s1u_tunnel( return 0; } +int gtpv1u_update_s1u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, + const rnti_t prior_rnti + ) +{ + /* Local tunnel end-point identifier */ + teid_t s1u_teid = 0; + gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; + gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + gtpv1u_ue_data_t *gtpv1u_ue_data_new_p = NULL; + //MessageDef *message_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + int i,j; + uint8_t bearers_num = 0,bearers_total = 0; + + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)>pv1u_ue_data_p); + if(hash_rc != HASH_TABLE_OK){ + LOG_E(GTPU,"Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti); + return -1; + } + + gtpv1u_ue_data_new_p = calloc (1, sizeof(gtpv1u_ue_data_t)); + memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(gtpv1u_ue_data_t)); + gtpv1u_ue_data_new_p->ue_id = create_tunnel_req_pP->rnti; + + hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p); + AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable"); + LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n", + create_tunnel_req_pP->rnti); + + hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, prior_rnti); + LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n", + prior_rnti); + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + bearers_total =gtpv1u_ue_data_new_p->num_bearers; + for(j = 0;j<GTPV1U_MAX_BEARERS_ID;j++){ + + if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG) + continue; + + bearers_num++; + for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) { + if(j == (create_tunnel_req_pP->eps_bearer_id[i]-GTPV1U_BEARER_OFFSET)) + break; + } + if(i < create_tunnel_req_pP->num_tunnels){ + s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB; + hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)>pv1u_teid_data_p); + if (hash_rc == HASH_TABLE_OK) { + gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti; + gtpv1u_teid_data_p->eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i]; + + LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n", + s1u_teid,prior_rnti,create_tunnel_req_pP->rnti); + }else{ + LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid); + } + }else{ + s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB; + hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, s1u_teid); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, s1u_teid); + } + gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN; + gtpv1u_ue_data_new_p->num_bearers--; + LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n", + s1u_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);; + } + if(bearers_num > bearers_total) + break; + } + return 0; + +} //----------------------------------------------------------------------------- static int gtpv1u_delete_s1u_tunnel( diff --git a/openair3/GTPV1-U/gtpv1u_eNB_task.h b/openair3/GTPV1-U/gtpv1u_eNB_task.h index 6f74c73a2926d0074cfca368845f7a797e1d28b3..5a7822fe8c7322e12a6a32d231cec8c6af1d1df6 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB_task.h +++ b/openair3/GTPV1-U/gtpv1u_eNB_task.h @@ -49,5 +49,9 @@ gtpv1u_create_s1u_tunnel( const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP); - +int +gtpv1u_update_s1u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, + const rnti_t prior_rnti); #endif /* GTPV1U_ENB_TASK_H_ */ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 08a18b629e0f58ccd075247f83c8832885a78230..aba32aa494cf41049669a2a096892fc5470296e1 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -364,6 +364,12 @@ void *s1ap_eNB_task(void *arg) &S1AP_E_RAB_SETUP_RESP(received_msg)); } break; + + case S1AP_E_RAB_MODIFY_RESP: { + s1ap_eNB_e_rab_modify_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &S1AP_E_RAB_MODIFY_RESP(received_msg)); + } + break; case S1AP_NAS_NON_DELIVERY_IND: { s1ap_eNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), @@ -397,6 +403,12 @@ void *s1ap_eNB_task(void *arg) } break; + case S1AP_E_RAB_RELEASE_RESPONSE: { + s1ap_eNB_e_rab_release_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &S1AP_E_RAB_RELEASE_RESPONSE(received_msg)); + } + break; + default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index f8daf6c67a7582983e26505a3a63699c5e9ef000..eac52c53ba6fc52cf13340267630a41d1de68c8c 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -108,7 +108,15 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message, ret = s1ap_decode_s1ap_pagingies( &message->msg.s1ap_PagingIEs, &initiating_p->value); s1ap_xer_print_s1ap_paging(s1ap_xer__print2sp, message_string, message); - S1AP_ERROR("TODO Paging initiating message\n"); + message_id = S1AP_PAGING_LOG; + message_string_size = strlen(message_string); + message_p = itti_alloc_new_message_sized(TASK_S1AP, + message_id, + message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_paging_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_paging_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + S1AP_INFO("Paging initiating message\n"); free(message_string); break; @@ -128,12 +136,36 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message, free(message_string); S1AP_INFO("E_RABSetup initiating message\n"); break; + + case S1ap_ProcedureCode_id_E_RABModify: + ret = s1ap_decode_s1ap_e_rabmodifyrequesties( + &message->msg.s1ap_E_RABModifyRequestIEs, &initiating_p->value); + message_id = S1AP_E_RAB_MODIFY_REQUEST_LOG; + message_string_size = strlen(message_string); + message_p = itti_alloc_new_message_sized(TASK_S1AP, + message_id, + message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_e_rab_modify_request_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_e_rab_modify_request_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + free(message_string); + S1AP_INFO("E_RABModify initiating message\n"); + break; + case S1ap_ProcedureCode_id_E_RABRelease: - ret = s1ap_decode_s1ap_e_rabreleasecommandies(&message->msg.s1ap_E_RABReleaseCommandIEs, - &initiating_p->value); - //s1ap_xer_print_s1ap_e_rabsetuprequest(s1ap_xer__print2sp, message_string, message); - S1AP_INFO("TODO E_RABRelease nitiating message\n"); + ret = s1ap_decode_s1ap_e_rabreleasecommandies( + &message->msg.s1ap_E_RABReleaseCommandIEs, &initiating_p->value); + s1ap_xer_print_s1ap_e_rabreleasecommand(s1ap_xer__print2sp, message_string, message); + message_id = S1AP_E_RAB_RELEASE_REQUEST_LOG; + message_string_size = strlen(message_string); + message_p = itti_alloc_new_message_sized(TASK_S1AP, + message_id, + message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_e_rab_release_request_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_e_rab_release_request_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); free(message_string); + S1AP_INFO("TODO E_RABRelease nitiating message\n"); break; default: diff --git a/openair3/S1AP/s1ap_eNB_encoder.c b/openair3/S1AP/s1ap_eNB_encoder.c index 4ab2f1f317f2cbee3f55404c53ed705cce10f158..9a5f422158dc592d685935d01bdbff06c17095c0 100644 --- a/openair3/S1AP/s1ap_eNB_encoder.c +++ b/openair3/S1AP/s1ap_eNB_encoder.c @@ -100,6 +100,16 @@ int s1ap_eNB_encode_e_rab_setup_response(S1ap_E_RABSetupResponseIEs_t *E_RABSet uint8_t **buffer, uint32_t *length); +static inline +int s1ap_eNB_encode_e_rab_modify_response(S1ap_E_RABModifyResponseIEs_t *E_RABModifyResponseIEs, + uint8_t **buffer, + uint32_t *length); + +static inline +int s1ap_eNB_encode_e_rab_release_response(S1ap_E_RABReleaseResponseIEs_t *s1ap_E_RABReleaseResponseIEs, + uint8_t **buffer, + uint32_t *length); + int s1ap_eNB_encode_pdu(s1ap_message *message, uint8_t **buffer, uint32_t *len) { DevAssert(message != NULL); @@ -264,6 +274,32 @@ int s1ap_eNB_encode_successfull_outcome(s1ap_message *s1ap_message_p, free(message_string); S1AP_INFO("E_RABSetup successful message\n"); break; + + case S1ap_ProcedureCode_id_E_RABModify: + ret = s1ap_eNB_encode_e_rab_modify_response ( + &s1ap_message_p->msg.s1ap_E_RABModifyResponseIEs, buffer, len); + message_id = S1AP_E_RAB_MODIFY_RESPONSE_LOG ; + message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_e_rab_modify_response_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_e_rab_modify_response_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + free(message_string); + S1AP_INFO("E_RABModify successful message\n"); + break; + + case S1ap_ProcedureCode_id_E_RABRelease: + ret = s1ap_eNB_encode_e_rab_release_response ( + &s1ap_message_p->msg.s1ap_E_RABReleaseResponseIEs, buffer, len); + s1ap_xer_print_s1ap_e_rabreleaseresponse(s1ap_xer__print2sp, message_string, s1ap_message_p); + message_id = S1AP_E_RAB_RELEASE_RESPONSE_LOG ; + message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_e_rab_release_response_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_e_rab_release_response_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + free(message_string); + S1AP_INFO("E_RAB Release successful message\n"); + break; + default: S1AP_WARN("Unknown procedure ID (%d) for successfull outcome message\n", (int)s1ap_message_p->procedureCode); @@ -563,3 +599,48 @@ int s1ap_eNB_encode_e_rab_setup_response(S1ap_E_RABSetupResponseIEs_t *s1ap_E_R &asn_DEF_S1ap_E_RABSetupResponse, e_rab_setup_response_p); } + +static inline +int s1ap_eNB_encode_e_rab_modify_response(S1ap_E_RABModifyResponseIEs_t *s1ap_E_RABModifyResponseIEs, + uint8_t **buffer, + uint32_t *length) +{ + S1ap_E_RABModifyResponse_t e_rab_modify_response; + S1ap_E_RABModifyResponse_t *e_rab_modify_response_p = &e_rab_modify_response; + + memset((void *)e_rab_modify_response_p, 0, + sizeof(e_rab_modify_response)); + + if (s1ap_encode_s1ap_e_rabmodifyresponseies (e_rab_modify_response_p, s1ap_E_RABModifyResponseIEs) < 0) { + return -1; + } + + return s1ap_generate_successfull_outcome(buffer, + length, + S1ap_ProcedureCode_id_E_RABModify, + S1ap_Criticality_reject, + &asn_DEF_S1ap_E_RABModifyResponse, + e_rab_modify_response_p); +} +static inline +int s1ap_eNB_encode_e_rab_release_response(S1ap_E_RABReleaseResponseIEs_t *s1ap_E_RABReleaseResponseIEs, + uint8_t **buffer, + uint32_t *length) +{ + S1ap_E_RABReleaseResponse_t e_rab_release_response; + S1ap_E_RABReleaseResponse_t *e_rab_release_response_p = &e_rab_release_response; + + memset((void *)e_rab_release_response_p, 0, + sizeof(e_rab_release_response)); + + if (s1ap_encode_s1ap_e_rabreleaseresponseies (e_rab_release_response_p, s1ap_E_RABReleaseResponseIEs) < 0) { + return -1; + } + + return s1ap_generate_successfull_outcome(buffer, + length, + S1ap_ProcedureCode_id_E_RABRelease, + S1ap_Criticality_reject, + &asn_DEF_S1ap_E_RABReleaseResponse, + e_rab_release_response_p); +} diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 186f034644eda4802ee90aa58fc124827b444a0e..0b02fc6db9ee4c0580ec108bdeb50bd162372d52 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -81,6 +81,20 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *s1ap_message_p); +static +int s1ap_eNB_handle_paging(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *message_p); + +static +int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *s1ap_message_p); + +static +int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *s1ap_message_p); /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { @@ -90,11 +104,11 @@ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* PathSwitchRequest */ { 0, 0, 0 }, /* HandoverCancel */ { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */ - { 0, 0, 0 }, /* E_RABModify */ - { 0, 0, 0 }, /* E_RABRelease */ + { s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */ + { s1ap_eNB_handle_e_rab_release_command, 0, 0 }, /* E_RABRelease */ { 0, 0, 0 }, /* E_RABReleaseIndication */ { s1ap_eNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */ - { 0, 0, 0 }, /* Paging */ + { s1ap_eNB_handle_paging, 0, 0 }, /* Paging */ { s1ap_eNB_handle_nas_downlink, 0, 0 }, /* downlinkNASTransport */ { 0, 0, 0 }, /* initialUEMessage */ { 0, 0, 0 }, /* uplinkNASTransport */ @@ -950,7 +964,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL; S1AP_WARN("NAS PDU is not provided, generate a E_RAB_SETUP Failure (TBD) back to MME \n"); - return -1; + // return -1; } /* Set the transport layer address */ @@ -983,4 +997,382 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, return 0; } +static +int s1ap_eNB_handle_paging(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *s1ap_message_p) +{ + S1ap_PagingIEs_t *paging_p; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + s1ap_eNB_instance_t *s1ap_eNB_instance = NULL; + MessageDef *message_p = NULL; + + DevAssert(s1ap_message_p != NULL); + // received Paging Message from MME + S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id); + + paging_p = &s1ap_message_p->msg.s1ap_PagingIEs; + + /* Paging procedure -> stream != 0 */ + if (stream == 0) { + S1AP_ERROR("[SCTP %d] Received Paging procedure on stream (%d)\n", + assoc_id, stream); + return -1; + } + + if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { + S1AP_ERROR("[SCTP %d] Received Paging for non " + "existing MME context\n", assoc_id); + return -1; + } + + s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance; + if (s1ap_eNB_instance == NULL) { + S1AP_ERROR("[SCTP %d] Received Paging for non existing MME context : s1ap_eNB_instance is NULL\n", + assoc_id); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PAGING_IND); + + /* convert S1ap_PagingIEs_t to s1ap_paging_ind_t */ + /* convert UE Identity Index value */ + S1AP_PAGING_IND(message_p).ue_index_value = BIT_STRING_to_uint32(&paging_p->ueIdentityIndexValue); + S1AP_DEBUG("[SCTP %d] Received Paging ue_index_value (%d)\n", + assoc_id,(uint32_t)S1AP_PAGING_IND(message_p).ue_index_value); + + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0; + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0; + + /* convert UE Paging Identity */ + if (paging_p->uePagingID.present == S1ap_UEPagingID_PR_s_TMSI) { + S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask = UE_PAGING_IDENTITY_s_tmsi; + OCTET_STRING_TO_INT8(&paging_p->uePagingID.choice.s_TMSI.mMEC, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code); + OCTET_STRING_TO_INT32(&paging_p->uePagingID.choice.s_TMSI.m_TMSI, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi); + } else if (paging_p->uePagingID.present == S1ap_UEPagingID_PR_iMSI) { + S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask = UE_PAGING_IDENTITY_imsi; + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length = 0; + for (int i = 0; i < paging_p->uePagingID.choice.iMSI.size; i++) { + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i] = (uint8_t)(paging_p->uePagingID.choice.iMSI.buf[i] & 0x0F ); + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++; + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1] = (uint8_t)((paging_p->uePagingID.choice.iMSI.buf[i]>>4) & 0x0F); + LOG_D(S1AP,"paging : i %d %d imsi %d %d \n",2*i,2*i+1,S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1]); + if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2*i+1] == 0x0F) { + if(i != paging_p->uePagingID.choice.iMSI.size - 1){ + /* invalid paging_p->uePagingID.choise.iMSI.buffer */ + S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i); + return -1; + } + } else { + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length++; + } + } + if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) { + /* invalid paging_p->uePagingID.choise.iMSI.size */ + S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH); + return -1; + } +} else { + /* invalid paging_p->uePagingID.present */ + S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, paging_p->uePagingID.present); + return -1; + } + +#if 0 + /* convert Paging DRX(optional) */ + if (paging_p->presenceMask & S1AP_PAGINGIES_PAGINGDRX_PRESENT) { + switch(paging_p->pagingDRX) { + case S1ap_PagingDRX_v32: + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_32; + break; + case S1ap_PagingDRX_v64: + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_64; + break; + case S1ap_PagingDRX_v128: + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_128; + break; + case S1ap_PagingDRX_v256: + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256; + break; + default: + // when UE Paging DRX is no value + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256; + break; + } + } +#endif + S1AP_PAGING_IND(message_p).paging_drx = PAGING_DRX_256; + + /* convert cnDomain */ + if (paging_p->cnDomain == S1ap_CNDomain_ps) { + S1AP_PAGING_IND(message_p).cn_domain = CN_DOMAIN_PS; + } else if (paging_p->cnDomain == S1ap_CNDomain_cs) { + S1AP_PAGING_IND(message_p).cn_domain = CN_DOMAIN_CS; + } else { + /* invalid paging_p->cnDomain */ + S1AP_ERROR("[SCTP %d] Received Paging : cnDomain(%ld) is unknown\n", assoc_id, paging_p->cnDomain); + return -1; + } + + memset (&S1AP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256); + memset (&S1AP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256); + S1AP_PAGING_IND(message_p).tai_size = 0; + + for (int i = 0; i < paging_p->taiList.s1ap_TAIItem.count; i++) { + S1AP_INFO("[SCTP %d] Received Paging taiList: i %d, count %d\n", assoc_id, i, paging_p->taiList.s1ap_TAIItem.count); + S1ap_TAIItem_t s1ap_TAIItem; + memset (&s1ap_TAIItem, 0, sizeof(S1ap_TAIItem_t)); + + memcpy(&s1ap_TAIItem, paging_p->taiList.s1ap_TAIItem.array[i], sizeof(S1ap_TAIItem_t)); + + TBCD_TO_MCC_MNC(&s1ap_TAIItem.tAI.pLMNidentity, S1AP_PAGING_IND(message_p).plmn_identity[i].mcc, + S1AP_PAGING_IND(message_p).plmn_identity[i].mnc, + S1AP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length); + OCTET_STRING_TO_INT16(&s1ap_TAIItem.tAI.tAC, S1AP_PAGING_IND(message_p).tac[i]); + S1AP_PAGING_IND(message_p).tai_size++; + S1AP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id, S1AP_PAGING_IND(message_p).plmn_identity[i].mcc, S1AP_PAGING_IND(message_p).plmn_identity[i].mnc, S1AP_PAGING_IND(message_p).tac[i]); + } + +#if 0 + // CSG Id(optional) List is not used + if (paging_p->presenceMask & S1AP_PAGINGIES_CSG_IDLIST_PRESENT) { + // TODO + } + + /* convert pagingPriority (optional) if has value */ + if (paging_p->presenceMask & S1AP_PAGINGIES_PAGINGPRIORITY_PRESENT) { + switch(paging_p->pagingPriority) { + case S1ap_PagingPriority_priolevel1: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL1; + break; + case S1ap_PagingPriority_priolevel2: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL2; + break; + case S1ap_PagingPriority_priolevel3: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL3; + break; + case S1ap_PagingPriority_priolevel4: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL4; + break; + case S1ap_PagingPriority_priolevel5: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL5; + break; + case S1ap_PagingPriority_priolevel6: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL6; + break; + case S1ap_PagingPriority_priolevel7: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL7; + break; + case S1ap_PagingPriority_priolevel8: + S1AP_PAGING_IND(message_p).paging_priority = PAGING_PRIO_LEVEL8; + break; + default: + /* invalid paging_p->pagingPriority */ + S1AP_ERROR("[SCTP %d] Received paging : pagingPriority(%ld) is invalid\n", assoc_id, paging_p->pagingPriority); + return -1; + } + } +#endif + //paging parameter values + S1AP_DEBUG("[SCTP %d] Received Paging parameters: ue_index_value %d cn_domain %d paging_drx %d paging_priority %d\n",assoc_id, + S1AP_PAGING_IND(message_p).ue_index_value, S1AP_PAGING_IND(message_p).cn_domain, + S1AP_PAGING_IND(message_p).paging_drx, S1AP_PAGING_IND(message_p).paging_priority); + S1AP_DEBUG("[SCTP %d] Received Paging parameters(ue): presenceMask %d s_tmsi.m_tmsi %d s_tmsi.mme_code %d IMSI length %d (0-5) %d%d%d%d%d%d\n",assoc_id, + S1AP_PAGING_IND(message_p).ue_paging_identity.presenceMask, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi, + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[0], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[1], + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[2], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[3], + S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[4], S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.buffer[5]); + + /* send message to RRC */ + itti_send_msg_to_task(TASK_RRC_ENB, s1ap_eNB_instance->instance, message_p); + + return 0; +} + +static +int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *s1ap_message_p) { + + int i; + + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + s1ap_eNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + int nb_of_e_rabs_failed = 0; + + S1ap_E_RABModifyRequestIEs_t *s1ap_E_RABModifyRequest; + DevAssert(s1ap_message_p != NULL); + + s1ap_E_RABModifyRequest = &s1ap_message_p->msg.s1ap_E_RABModifyRequestIEs; + + if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { + S1AP_ERROR("[SCTP %d] Received E-RAB modify request for non " + "existing MME context\n", assoc_id); + return -1; + } + + + if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, + s1ap_E_RABModifyRequest->eNB_UE_S1AP_ID)) == NULL) { + S1AP_ERROR("[SCTP %d] Received E-RAB modify request for non " + "existing UE context 0x%06lx\n", assoc_id, + s1ap_E_RABModifyRequest->eNB_UE_S1AP_ID); + return -1; + } + /* E-RAB modify request = UE-related procedure -> stream != 0 */ + if (stream == 0) { + S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + assoc_id, stream); + return -1; + } + + ue_desc_p->rx_stream = stream; + + if ( ue_desc_p->mme_ue_s1ap_id != s1ap_E_RABModifyRequest->mme_ue_s1ap_id){ + S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)", + ue_desc_p->mme_ue_s1ap_id, s1ap_E_RABModifyRequest->mme_ue_s1ap_id); + message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + + S1AP_E_RAB_MODIFY_RESP (message_p).eNB_ue_s1ap_id = s1ap_E_RABModifyRequest->eNB_UE_S1AP_ID; +// S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs[S1AP_MAX_E_RAB]; + S1AP_E_RAB_MODIFY_RESP (message_p).nb_of_e_rabs = 0; + + for(nb_of_e_rabs_failed = 0; nb_of_e_rabs_failed < s1ap_E_RABModifyRequest->e_RABToBeModifiedListBearerModReq.s1ap_E_RABToBeModifiedItemBearerModReq.count; nb_of_e_rabs_failed++) { + S1AP_E_RAB_MODIFY_RESP (message_p).e_rabs_failed[nb_of_e_rabs_failed].e_rab_id = + ((S1ap_E_RABToBeModifiedItemBearerModReq_t *)s1ap_E_RABModifyRequest->e_RABToBeModifiedListBearerModReq.s1ap_E_RABToBeModifiedItemBearerModReq.array[nb_of_e_rabs_failed])->e_RAB_ID; + S1AP_E_RAB_MODIFY_RESP (message_p).e_rabs_failed[nb_of_e_rabs_failed].cause = S1AP_CAUSE_RADIO_NETWORK; + S1AP_E_RAB_MODIFY_RESP (message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = 13;//S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id; + } + S1AP_E_RAB_MODIFY_RESP (message_p).nb_of_e_rabs_failed = nb_of_e_rabs_failed; + + s1ap_eNB_e_rab_modify_resp(mme_desc_p->s1ap_eNB_instance->instance, + &S1AP_E_RAB_MODIFY_RESP(message_p)); + + message_p = NULL; + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_MODIFY_REQ); + + S1AP_E_RAB_MODIFY_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + + S1AP_E_RAB_MODIFY_REQ(message_p).mme_ue_s1ap_id = s1ap_E_RABModifyRequest->mme_ue_s1ap_id; + S1AP_E_RAB_MODIFY_REQ(message_p).eNB_ue_s1ap_id = s1ap_E_RABModifyRequest->eNB_UE_S1AP_ID; + + S1AP_E_RAB_MODIFY_REQ(message_p).nb_e_rabs_tomodify = + s1ap_E_RABModifyRequest->e_RABToBeModifiedListBearerModReq.s1ap_E_RABToBeModifiedItemBearerModReq.count; + + for (i = 0; i < s1ap_E_RABModifyRequest->e_RABToBeModifiedListBearerModReq.s1ap_E_RABToBeModifiedItemBearerModReq.count; i++) { + S1ap_E_RABToBeModifiedItemBearerModReq_t *item_p; + + item_p = (S1ap_E_RABToBeModifiedItemBearerModReq_t *)s1ap_E_RABModifyRequest->e_RABToBeModifiedListBearerModReq.s1ap_E_RABToBeModifiedItemBearerModReq.array[i]; + + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].e_rab_id = item_p->e_RAB_ID; + + // check for the NAS PDU + if (item_p->nAS_PDU.size > 0 ) { + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.length = item_p->nAS_PDU.size; + + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size); + + memcpy(S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer, + item_p->nAS_PDU.buf, item_p->nAS_PDU.size); + } else { + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.length = 0; + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].nas_pdu.buffer = NULL; + continue; + } + + /* Set the QOS informations */ + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.qci = item_p->e_RABLevelQoSParameters.qCI; + + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.priority_level = + item_p->e_RABLevelQoSParameters.allocationRetentionPriority.priorityLevel; + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.pre_emp_capability = + item_p->e_RABLevelQoSParameters.allocationRetentionPriority.pre_emptionCapability; + S1AP_E_RAB_MODIFY_REQ(message_p).e_rab_modify_params[i].qos.allocation_retention_priority.pre_emp_vulnerability = + item_p->e_RABLevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; + + } + + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; +} +// handle e-rab release command and send it to rrc_end +static +int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, + uint32_t stream, + struct s1ap_message_s *s1ap_message_p) { + + int i; + + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + s1ap_eNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + + S1ap_E_RABReleaseCommandIEs_t *s1ap_E_RABReleaseCommand; + DevAssert(s1ap_message_p != NULL); + s1ap_E_RABReleaseCommand = &s1ap_message_p->msg.s1ap_E_RABReleaseCommandIEs; + + if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { + S1AP_ERROR("[SCTP %d] Received E-RAB release command for non existing MME context\n", assoc_id); + return -1; + } + if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, + s1ap_E_RABReleaseCommand->eNB_UE_S1AP_ID)) == NULL) { + S1AP_ERROR("[SCTP %d] Received E-RAB release command for non existing UE context 0x%06lx\n", assoc_id, + s1ap_E_RABReleaseCommand->eNB_UE_S1AP_ID); + return -1; + } + + /* Initial context request = UE-related procedure -> stream != 0 */ + if (stream == 0) { + S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + assoc_id, stream); + return -1; + } + + ue_desc_p->rx_stream = stream; + + if ( ue_desc_p->mme_ue_s1ap_id != s1ap_E_RABReleaseCommand->mme_ue_s1ap_id){ + S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)", + ue_desc_p->mme_ue_s1ap_id, s1ap_E_RABReleaseCommand->mme_ue_s1ap_id); + } + + S1AP_DEBUG("[SCTP %d] Received E-RAB release command for eNB_UE_S1AP_ID %ld mme_ue_s1ap_id %ld\n", + assoc_id, s1ap_E_RABReleaseCommand->eNB_UE_S1AP_ID, s1ap_E_RABReleaseCommand->mme_ue_s1ap_id); + + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_RELEASE_COMMAND); + + S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = s1ap_E_RABReleaseCommand->eNB_UE_S1AP_ID; + S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = s1ap_E_RABReleaseCommand->mme_ue_s1ap_id; + if(s1ap_E_RABReleaseCommand->nas_pdu.size > 0 ){ + S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = s1ap_E_RABReleaseCommand->nas_pdu.size; + + S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = + malloc(sizeof(uint8_t) * s1ap_E_RABReleaseCommand->nas_pdu.size); + + memcpy(S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer, + s1ap_E_RABReleaseCommand->nas_pdu.buf, + s1ap_E_RABReleaseCommand->nas_pdu.size); + } else { + S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0; + S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; + } + + S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = s1ap_E_RABReleaseCommand->e_RABToBeReleasedList.s1ap_E_RABItem.count; + for(i=0; i < s1ap_E_RABReleaseCommand->e_RABToBeReleasedList.s1ap_E_RABItem.count; i++){ + S1ap_E_RABItem_t *item_p; + item_p = (S1ap_E_RABItem_t*)s1ap_E_RABReleaseCommand->e_RABToBeReleasedList.s1ap_E_RABItem.array[i]; + S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; + S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); + } + + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index ea0dbcb70af653217564fec618977d56de8fb686..d6d9b52c07a2cd6719b9bc63fbcda72bf4d11c4a 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -837,3 +837,282 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance, return ret; } + +//------------------------------------------------------------------------------ +int s1ap_eNB_e_rab_modify_resp(instance_t instance, + s1ap_e_rab_modify_resp_t *e_rab_modify_resp_p) +//------------------------------------------------------------------------------ +{ + s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + + S1ap_E_RABModifyResponseIEs_t *initial_ies_p = NULL; + + s1ap_message message; + + uint8_t *buffer = NULL; + uint32_t length; + int ret = -1; + int i; + + /* Retrieve the S1AP eNB instance associated with Mod_id */ + s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); + + DevAssert(e_rab_modify_resp_p != NULL); + DevAssert(s1ap_eNB_instance_p != NULL); + + if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, + e_rab_modify_resp_p->eNB_ue_s1ap_id)) == NULL) { + /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ + S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n", + e_rab_modify_resp_p->eNB_ue_s1ap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an s1ap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED || + ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) { + S1AP_WARN("You are attempting to send NAS data over non-connected " + "eNB ue s1ap id: %06x, current state: %d\n", + e_rab_modify_resp_p->eNB_ue_s1ap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the S1AP message to encode */ + memset(&message, 0, sizeof(s1ap_message)); + + message.direction = S1AP_PDU_PR_successfulOutcome; + message.procedureCode = S1ap_ProcedureCode_id_E_RABModify; + message.criticality = S1ap_Criticality_reject; + + initial_ies_p = &message.msg.s1ap_E_RABModifyResponseIEs; + + initial_ies_p->eNB_UE_S1AP_ID = e_rab_modify_resp_p->eNB_ue_s1ap_id; + initial_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; + + if ( e_rab_modify_resp_p->nb_of_e_rabs >= 1 ) + initial_ies_p->presenceMask |= S1AP_E_RABMODIFYRESPONSEIES_E_RABMODIFYLISTBEARERMODRES_PRESENT; + + for (i = 0; i < e_rab_modify_resp_p->nb_of_e_rabs; i++) { + S1ap_E_RABModifyItemBearerModRes_t *modify_item; + + modify_item = calloc(1, sizeof(S1ap_E_RABModifyItemBearerModRes_t)); + + modify_item->e_RAB_ID = e_rab_modify_resp_p->e_rabs[i].e_rab_id; + + S1AP_DEBUG("e_rab_modify_resp: modified e_rab ID %ld\n", + modify_item->e_RAB_ID); + + S1ap_IE_t *ie = s1ap_new_ie(S1ap_ProtocolIE_ID_id_E_RABModifyItemBearerModRes, + S1ap_Criticality_ignore, + &asn_DEF_S1ap_E_RABModifyItemBearerModRes, + modify_item); + + ASN_SEQUENCE_ADD(&initial_ies_p->e_RABModifyListBearerModRes.s1ap_E_RABModifyItemBearerModRes, + ie); + } + + if ( e_rab_modify_resp_p->nb_of_e_rabs_failed >= 1 ) + initial_ies_p->presenceMask |= S1AP_E_RABMODIFYRESPONSEIES_E_RABFAILEDTOMODIFYLIST_PRESENT; + + for (i = 0; i < e_rab_modify_resp_p->nb_of_e_rabs_failed; i++) { + S1ap_E_RABItem_t *failed_item; + + failed_item = calloc(1, sizeof(S1ap_E_RABItem_t)); + + failed_item->e_RAB_ID = e_rab_modify_resp_p->e_rabs_failed[i].e_rab_id; + switch(e_rab_modify_resp_p->e_rabs_failed[i].cause) + { + case S1AP_CAUSE_RADIO_NETWORK: + failed_item->cause.present = S1ap_Cause_PR_radioNetwork; + failed_item->cause.choice.radioNetwork = e_rab_modify_resp_p->e_rabs_failed[i].cause_value; + break; + case S1AP_CAUSE_TRANSPORT: + failed_item->cause.present = S1ap_Cause_PR_transport; + failed_item->cause.choice.transport = e_rab_modify_resp_p->e_rabs_failed[i].cause_value; + break; + case S1AP_CAUSE_NAS: + failed_item->cause.present = S1ap_Cause_PR_nas; + failed_item->cause.choice.nas = e_rab_modify_resp_p->e_rabs_failed[i].cause_value; + break; + case S1AP_CAUSE_PROTOCOL: + failed_item->cause.present = S1ap_Cause_PR_protocol; + failed_item->cause.choice.protocol = e_rab_modify_resp_p->e_rabs_failed[i].cause_value; + break; + case S1AP_CAUSE_MISC: + failed_item->cause.present = S1ap_Cause_PR_misc; + failed_item->cause.choice.misc = e_rab_modify_resp_p->e_rabs_failed[i].cause_value; + break; + default: + break; + } + S1AP_DEBUG("e_rab_modify_resp: failed e_rab ID %ld\n", + failed_item->e_RAB_ID); + + S1ap_IE_t *ie = s1ap_new_ie(S1ap_ProtocolIE_ID_id_E_RABItem, + S1ap_Criticality_ignore, + &asn_DEF_S1ap_E_RABItem, + failed_item); + + ASN_SEQUENCE_ADD(&initial_ies_p->e_RABFailedToModifyList.s1ap_E_RABItem, + ie); + } + + fprintf(stderr, "start encode\n"); + if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { + S1AP_ERROR("Failed to encode uplink transport\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_S1AP_ENB, + MSC_S1AP_MME, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" E_RAN Modify successful Outcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + initial_ies_p->eNB_UE_S1AP_ID, + initial_ies_p->mme_ue_s1ap_id); + + /* UE associated signalling -> use the allocated stream */ + s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance, + ue_context_p->mme_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return ret; +} +//------------------------------------------------------------------------------ +int s1ap_eNB_e_rab_release_resp(instance_t instance, + s1ap_e_rab_release_resp_t *e_rab_release_resp_p) +//------------------------------------------------------------------------------ +{ + s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + + S1ap_E_RABReleaseResponseIEs_t *release_response_ies_p = NULL; + + s1ap_message message; + + uint8_t *buffer = NULL; + uint32_t length; + int ret = -1; + int i; + /* Retrieve the S1AP eNB instance associated with Mod_id */ + s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); + DevAssert(e_rab_release_resp_p != NULL); + DevAssert(s1ap_eNB_instance_p != NULL); + + /* Prepare the S1AP message to encode */ + memset(&message, 0, sizeof(s1ap_message)); + + message.direction = S1AP_PDU_PR_successfulOutcome; + message.procedureCode = S1ap_ProcedureCode_id_E_RABRelease; + message.criticality = S1ap_Criticality_ignore; + + if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, + e_rab_release_resp_p->eNB_ue_s1ap_id)) == NULL) { + /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ + S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n", + e_rab_release_resp_p->eNB_ue_s1ap_id); + return -1; + } + + release_response_ies_p = &message.msg.s1ap_E_RABReleaseResponseIEs; + release_response_ies_p->eNB_UE_S1AP_ID = e_rab_release_resp_p->eNB_ue_s1ap_id; + release_response_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; + + if ( e_rab_release_resp_p->nb_of_e_rabs_released > 0 ) + release_response_ies_p->presenceMask |= S1AP_E_RABRELEASERESPONSEIES_E_RABRELEASELISTBEARERRELCOMP_PRESENT; + + //release + for (i = 0; i < e_rab_release_resp_p->nb_of_e_rabs_released; i++) { + + S1ap_E_RABReleaseItemBearerRelComp_t *new_item; + + new_item = calloc(1, sizeof(S1ap_E_RABReleaseItemBearerRelComp_t)); + + new_item->e_RAB_ID = e_rab_release_resp_p->e_rab_release[i].e_rab_id; + + S1AP_DEBUG("e_rab_release_resp: e_rab ID %ld\n",new_item->e_RAB_ID); + + ASN_SEQUENCE_ADD(&release_response_ies_p->e_RABReleaseListBearerRelComp.s1ap_E_RABReleaseItemBearerRelComp, + new_item); + + } + + if ( e_rab_release_resp_p->nb_of_e_rabs_failed > 0 ) + release_response_ies_p->presenceMask |= S1AP_E_RABRELEASERESPONSEIES_E_RABFAILEDTORELEASELIST_PRESENT; + + //release failed + for (i = 0; i < e_rab_release_resp_p->nb_of_e_rabs_failed; i++) { + S1ap_E_RABItem_t *new_rabitem; + new_rabitem = calloc(1, sizeof(S1ap_E_RABItem_t)); + //e_rab_id + new_rabitem->e_RAB_ID = e_rab_release_resp_p->e_rabs_failed[i].e_rab_id; + //cause + switch(e_rab_release_resp_p->e_rabs_failed[i].cause) + { + case S1AP_CAUSE_NOTHING: + new_rabitem->cause.present = S1ap_Cause_PR_NOTHING; + break; + + case S1AP_CAUSE_RADIO_NETWORK: + new_rabitem->cause.present = S1ap_Cause_PR_radioNetwork; + new_rabitem->cause.choice.radioNetwork = e_rab_release_resp_p->e_rabs_failed[i].cause_value; + break; + + case S1AP_CAUSE_TRANSPORT: + new_rabitem->cause.present = S1ap_Cause_PR_transport; + new_rabitem->cause.choice.transport = e_rab_release_resp_p->e_rabs_failed[i].cause_value; + break; + + case S1AP_CAUSE_NAS: + new_rabitem->cause.present = S1ap_Cause_PR_nas; + new_rabitem->cause.choice.nas = e_rab_release_resp_p->e_rabs_failed[i].cause_value; + break; + + case S1AP_CAUSE_PROTOCOL: + new_rabitem->cause.present = S1ap_Cause_PR_protocol; + new_rabitem->cause.choice.protocol = e_rab_release_resp_p->e_rabs_failed[i].cause_value; + break; + + case S1AP_CAUSE_MISC: + default: + new_rabitem->cause.present = S1ap_Cause_PR_misc; + new_rabitem->cause.choice.misc = e_rab_release_resp_p->e_rabs_failed[i].cause_value; + break; + } + S1AP_DEBUG("e_rab_release_resp: failed e_rab ID %ld\n",new_rabitem->e_RAB_ID); + ASN_SEQUENCE_ADD(&release_response_ies_p->e_RABFailedToReleaseList.s1ap_E_RABItem, new_rabitem); + } + + fprintf(stderr, "start encode\n"); + if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { + S1AP_ERROR("Failed to encode release response\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_S1AP_ENB, + MSC_S1AP_MME, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" E_RAN Release successfulOutcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + e_rab_release_resp_p->eNB_ue_s1ap_id, + ue_context_p->mme_ue_s1ap_id); + + /* UE associated signalling -> use the allocated stream */ + s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance, + ue_context_p->mme_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + S1AP_INFO("e_rab_release_response sended eNB_UE_S1AP_ID %d mme_ue_s1ap_id %d nb_of_e_rabs_released %d nb_of_e_rabs_failed %d\n", + e_rab_release_resp_p->eNB_ue_s1ap_id, ue_context_p->mme_ue_s1ap_id,e_rab_release_resp_p->nb_of_e_rabs_released,e_rab_release_resp_p->nb_of_e_rabs_failed); + + return ret; +} diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.h b/openair3/S1AP/s1ap_eNB_nas_procedures.h index 269387257653e30efef12d630f58fd9b48bcde44..bb2a0488bfd898fb5ec87a62e0d205767c19d467 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.h +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.h @@ -44,4 +44,9 @@ int s1ap_eNB_ue_capabilities(instance_t instance, int s1ap_eNB_e_rab_setup_resp(instance_t instance, s1ap_e_rab_setup_resp_t *e_rab_setup_resp_p); +int s1ap_eNB_e_rab_modify_resp(instance_t instance, + s1ap_e_rab_modify_resp_t *e_rab_modify_resp_p); + +int s1ap_eNB_e_rab_release_resp(instance_t instance, + s1ap_e_rab_release_resp_t *e_rab_release_resp_p); #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */ diff --git a/openair3/SECU/kdf.c b/openair3/SECU/kdf.c index 0717d17c59dbcac17a4e553eaa1c50902998bbc1..1073df8ebedf7f0e6a647b183122e394ce141982 100644 --- a/openair3/SECU/kdf.c +++ b/openair3/SECU/kdf.c @@ -63,3 +63,43 @@ int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB } #endif +int derive_keNB_star( + const uint8_t *kenb_32, + const uint16_t pci, + const uint32_t earfcn_dl, + const bool is_rel8_only, + uint8_t *kenb_star) +{ + // see 33.401 section A.5 KeNB* derivation function + uint8_t s[10] = {0}; + + // FC = 0x13 + s[0] = FC_KENB_STAR; + // P0 = PCI (target physical cell id) + s[1] = (pci & 0x0000ff00) >> 8; + s[2] = (pci & 0x000000ff); + // L0 = length of PCI (i.e. 0x00 0x02) + s[3] = 0x00; + s[4] = 0x02; + // P1 = EARFCN-DL (target physical cell downlink frequency) + if (is_rel8_only) { + s[5] = (earfcn_dl & 0x0000ff00) >> 8; + s[6] = (earfcn_dl & 0x000000ff); + s[7] = 0x00; + s[8] = 0x02; + kdf (kenb_32, 32, s, 9, kenb_star, 32); + } else { + s[5] = (earfcn_dl & 0x00ff0000) >> 16; + s[6] = (earfcn_dl & 0x0000ff00) >> 8; + s[7] = (earfcn_dl & 0x000000ff); + s[8] = 0x00; + s[9] = 0x03; + kdf (kenb_32, 32, s, 10, kenb_star, 32); + } + // L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between 65536 and 262143) + // NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8 + // entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This + // would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the + // EARFCN-DL. + return 0; +} diff --git a/openair3/SECU/secu_defs.h b/openair3/SECU/secu_defs.h index 4130098c991199bc2ef916bb4680ac9c54f62a11..8ec05f3dafe58afeb6ddb5cd9c542c3818487e6c 100644 --- a/openair3/SECU/secu_defs.h +++ b/openair3/SECU/secu_defs.h @@ -23,6 +23,7 @@ #define SECU_DEFS_H_ #include "security_types.h" +#include <stdbool.h> #define EIA0_ALG_ID 0x00 #define EIA1_128_ALG_ID 0x01 @@ -44,6 +45,9 @@ void kdf(const uint8_t *key, int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB); +int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl, + const bool is_rel8_only, uint8_t * kenb_star); + int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t kasme[32], uint8_t *knas); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 792f16e92a1bcdf6aeb9f843170befeb4bb48962..04a8f72505aaab5cda5fbe4c33ddbc11b0235dcc 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1188,6 +1188,10 @@ int main( int argc, char **argv ) RCconfig_L1(); } #endif + + // init UE_PF_PO and mutex lock + pthread_mutex_init(&ue_pf_po_mutex, NULL); + memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); mlockall(MCL_CURRENT | MCL_FUTURE); @@ -1457,7 +1461,7 @@ int main( int argc, char **argv ) pthread_cond_destroy(&nfapi_sync_cond); pthread_mutex_destroy(&nfapi_sync_mutex); - + pthread_mutex_destroy(&ue_pf_po_mutex); // *** Handle per CC_id openair0 if (UE_flag==1) {