diff --git a/openair2/COMMON/s1ap_messages_def.h b/openair2/COMMON/s1ap_messages_def.h index ce51ac78cad021f60a16bd746fdafc20e561e39f..b9f7a0d02f9ee60c39d971c2ba51170d90d4fdcf 100644 --- a/openair2/COMMON/s1ap_messages_def.h +++ b/openair2/COMMON/s1ap_messages_def.h @@ -58,12 +58,15 @@ MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_relea MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, s1ap_ue_release_complete_t , s1ap_ue_release_complete) MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_resp_t , s1ap_ue_ctxt_modification_resp) 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) /* S1AP -> RRC messages */ MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas ) MESSAGE_DEF(S1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, s1ap_initial_context_setup_req_t , s1ap_initial_context_setup_req ) 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_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 c39725b737f1bb6c0750e1317046366b50679207..83c9ca64ca6e91b95a8af5e0be523974389f93c8 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -47,12 +47,15 @@ #define S1AP_NAS_NON_DELIVERY_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_nas_non_delivery_ind #define S1AP_UE_CTXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_resp #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_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas #define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req #define S1AP_UE_CTXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_req #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_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_req @@ -390,7 +393,7 @@ typedef struct s1ap_initial_context_setup_fail_s { unsigned eNB_ue_s1ap_id:24; /* TODO add cause */ -} s1ap_initial_context_setup_fail_t, s1ap_ue_ctxt_modification_fail_t; +} s1ap_initial_context_setup_fail_t, s1ap_ue_ctxt_modification_fail_t, s1ap_e_rab_setup_req_fail_t; typedef struct s1ap_nas_non_delivery_ind_s { unsigned eNB_ue_s1ap_id:24; @@ -439,6 +442,7 @@ typedef struct s1ap_downlink_nas_s { nas_pdu_t nas_pdu; } s1ap_downlink_nas_t; + typedef struct s1ap_initial_context_setup_req_s { /* UE id for initial connection to S1AP */ uint16_t ue_initial_id; @@ -479,6 +483,39 @@ typedef struct s1ap_paging_ind_s { paging_priority_t paging_priority; } s1ap_paging_ind_t; +typedef struct s1ap_e_rab_setup_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 setup in the list */ + uint8_t nb_e_rabs_tosetup; + + /* E RAB setup request */ + e_rab_t e_rab_setup_params[S1AP_MAX_E_RAB]; + +} s1ap_e_rab_setup_req_t; + +typedef struct s1ap_e_rab_setup_resp_s { + unsigned eNB_ue_s1ap_id:24; + + /* Number of e_rab setup-ed in the list */ + uint8_t nb_of_e_rabs; + /* list of e_rab setup-ed by RRC layers */ + e_rab_setup_t e_rabs[S1AP_MAX_E_RAB]; + + /* Number of e_rab failed to be setup in list */ + uint8_t nb_of_e_rabs_failed; + /* list of e_rabs that failed to be setup */ + e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB]; +} s1ap_e_rab_setup_resp_t; + + // S1AP --> RRC messages typedef struct s1ap_ue_release_command_s { diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index e3f6d8e78c13fc86f900a86a14ef2dfff7b8d1e0..e719d6729fa2b97cff038192994f1e5442d55626 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -189,6 +189,10 @@ rrc_mac_config_req( mac_xface->macphy_exit("NULL ul_SpecificParameters"); } } + else { + eNB_mac_inst[Mod_id].lcid_active[logicalChannelIdentity]=1; + LOG_I(MAC,"[CONFIG][eNB %d] lcid %d is active for UE rnti %x on cc_id % \n",Mod_id,rntiP,CC_id); + } } if (mac_MainConfig != NULL) { diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index a0a43b6d7951ea3f4eb9fa1cebb9aa2dad5e34d7..3c9568d41ff14305e442eabde8c3405db84544d7 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -887,7 +887,7 @@ typedef struct { SBMAP_CONF sbmap_conf; /// active flag for Other lcid - // uint8_t lcid_active[NB_RB_MAX]; + uint8_t lcid_active[NB_RB_MAX]; /// eNB stats eNB_STATS eNB_stats[MAX_NUM_CCs]; // MAC function execution peformance profiler diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 52e0f60d65bdd7a7ede16b57c908cd5159b9a125..ca08f076952d3766f7104abc90a3156986a0ba66 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -435,10 +435,12 @@ schedule_ue_spec( int N_RBG[MAX_NUM_CCs]; unsigned char aggregation; mac_rlc_status_resp_t rlc_status; - unsigned char header_len_dcch=0, header_len_dcch_tmp=0,header_len_dtch=0,header_len_dtch_tmp=0, ta_len=0; - unsigned char sdu_lcids[11],offset,num_sdus=0; + unsigned char header_len_dcch=0, header_len_dcch_tmp=0, header_len_dcch_last=0; + unsigned char header_len_dtch=0, header_len_dtch_tmp=0, header_len_dtch_last=0; + unsigned char ta_len=0; + unsigned char sdu_lcids[NB_RB_MAX],lcid,offset,num_sdus=0; uint16_t nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb; - uint16_t TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0; + uint16_t TBS,j,sdu_lengths[NB_RB_MAX],rnti,padding=0,post_padding=0; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; unsigned char round = 0; unsigned char harq_pid = 0; @@ -903,84 +905,92 @@ schedule_ue_spec( ENB_FLAG_YES, MBMS_FLAG_NO, DCCH+1, - (char *)&dlsch_buffer[sdu_lengths[0]]); + (char *)&dlsch_buffer[sdu_lengths[num_sdus]]); sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1]+=1; UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1]+=sdu_lengths[num_sdus]; - num_sdus++; - LOG_D(MAC,"[eNB %d] CC_id %d Got %d bytes for DCCH from RLC\n",module_idP,CC_id,sdu_lengths[0]); - } - } - - // check for DTCH and update header information - // here we should loop over all possible DTCH - - header_len_dtch = 3; // 3 bytes DTCH SDU subheader - - LOG_D(MAC,"[eNB %d], Frame %d, DTCH->DLSCH, CC_id %d, Checking RLC status (rab %d, tbs %d, len %d)\n", - module_idP,frameP,CC_id,DTCH,TBS, - TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); - - if (TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch > 0 ) { - rlc_status = mac_rlc_status_ind( - module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DTCH, - TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); - - if (rlc_status.bytes_in_buffer > 0) { - - LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB], Frame %d, DTCH->DLSCH, CC_id %d, Requesting %d bytes from RLC (hdr len dtch %d)\n", - module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total-header_len_dtch,header_len_dtch); - sdu_lengths[num_sdus] = mac_rlc_data_req( - module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DTCH, - (char*)&dlsch_buffer[sdu_length_total]); - - LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] CC_id %d Got %d bytes for DTCH %d \n", - module_idP,CC_id,sdu_lengths[num_sdus],DTCH); - sdu_lcids[num_sdus] = DTCH; - sdu_length_total += sdu_lengths[num_sdus]; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DTCH]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DTCH]+=sdu_lengths[num_sdus]; - - if (sdu_lengths[num_sdus] < 128) { - header_len_dtch=2; - } - - num_sdus++; - } else { - header_len_dtch = 0; - } + LOG_D(MAC,"[eNB %d] CC_id %d Got %d bytes for DCCH from RLC\n",module_idP,CC_id,sdu_lengths[num_sdus]); + num_sdus++; + } } - // there is a payload - if (((sdu_length_total + header_len_dcch + header_len_dtch )> 0)) { - - // Now compute number of required RBs for total sdu length - // Assume RAH format 2 - // adjust header lengths - header_len_dcch_tmp = header_len_dcch; - header_len_dtch_tmp = header_len_dtch; - - if (header_len_dtch==0) { - header_len_dcch = (header_len_dcch >0) ? 1 : header_len_dcch; // remove length field - } else { - header_len_dtch = (header_len_dtch > 0) ? 1 :header_len_dtch; // remove length field for the last SDU - } - + // assume the max dtch header size, and adjust it later + header_len_dtch=0; + header_len_dtch_last=0; // the header length of the last mac sdu + // lcid has to be sorted before the actual allocation (similar struct as ue_list). + for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){ + // TBD: check if the lcid is active + + header_len_dtch+=3; + header_len_dtch_last=3; + LOG_D(MAC,"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + module_idP,frameP,lcid,TBS, + TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); + + if (TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch > 0 ) { // NN: > 2 ? + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch); + + + if (rlc_status.bytes_in_buffer > 0) { + + LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH%d->DLSCH, Requesting %d bytes from RLC (total hdr len dtch %d)\n", + module_idP,frameP,lcid,TBS-header_len_dcch-sdu_length_total-header_len_dtch,header_len_dtch); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + (char*)&dlsch_buffer[sdu_length_total]); + + LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",module_idP,sdu_lengths[num_sdus],lcid); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]+=1; + UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid]+=sdu_lengths[num_sdus]; + if (sdu_lengths[num_sdus] < 128) { + header_len_dtch--; + header_len_dtch_last--; + } + num_sdus++; + } // no data for this LCID + else { + header_len_dtch-=3; + } + } // no TBS left + else { + header_len_dtch-=3; + break; + } + } + if (header_len_dtch == 0 ) + header_len_dtch_last= 0; + // there is at least one SDU + // if (num_sdus > 0 ){ + if ((sdu_length_total + header_len_dcch + header_len_dtch )> 0) { + + // Now compute number of required RBs for total sdu length + // Assume RAH format 2 + // adjust header lengths + header_len_dcch_tmp = header_len_dcch; + header_len_dtch_tmp = header_len_dtch; + if (header_len_dtch==0) { + header_len_dcch = (header_len_dcch >0) ? 1 : 0;//header_len_dcch; // remove length field + } else { + header_len_dtch_last-=1; // now use it to find how many bytes has to be removed for the last MAC SDU + header_len_dtch = (header_len_dtch > 0) ? header_len_dtch - header_len_dtch_last :header_len_dtch; // remove length field for the last SDU + } mcs = eNB_UE_stats->dlsch_mcs1; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 1018c6e7d8483ff60121c33eb9007f337573ef0d..6bfb598db595d44721ca6573f9ed62dc790daffd 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -69,16 +69,15 @@ // This table holds the allowable PRB sizes for ULSCH transmissions uint8_t rb_table[33] = {1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,54,60,72,75,80,81,90,96,100}; -void rx_sdu( - const module_id_t enb_mod_idP, - const int CC_idP, - const frame_t frameP, - const sub_frame_t subframeP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const int harq_pidP, - uint8_t *msg3_flagP) +void rx_sdu(const module_id_t enb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP, + uint8_t *sduP, + const uint16_t sdu_lenP, + const int harq_pidP, + uint8_t *msg3_flagP) { unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr; @@ -216,8 +215,8 @@ void rx_sdu( for (i=0; i<num_sdu; i++) { LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]); - switch (rx_lcids[i]) { - case CCCH : + if (rx_lcids[i] == CCCH) { + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n", enb_mod_idP,CC_idP,frameP, payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP); @@ -274,94 +273,80 @@ void rx_sdu( } // if process is active } // loop on RA processes - break; - case DCCH : - case DCCH1 : + } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) { // if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){ #if defined(ENABLE_MAC_PAYLOAD_DEBUG) LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP)); - for (j=0; j<32; j++) { LOG_T(MAC,"%x ",payload_ptr[j]); } - LOG_T(MAC,"\n"); #endif if (UE_id != -1) { // This check is just to make sure we didn't get a bogus SDU length, to be removed ... if (rx_lengths[i]<CCCH_PAYLOAD_SIZE_MAX) { - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n", - enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]); - + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH%d, received %d bytes form UE %d \n", + enb_mod_idP,CC_idP,frameP, rx_lcids[i], rx_lengths[i], UE_id); + mac_rlc_data_ind( - enb_mod_idP, - rntiP, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); + enb_mod_idP, + rntiP, + enb_mod_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcids[i], + (char *)payload_ptr, + rx_lengths[i], + 1, + NULL);//(unsigned int*)crc_status); UE_list->eNB_UE_stats[CC_idP][UE_id].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]; } } /* UE_id != -1 */ - - // } - break; - - case DTCH: // default DRB - // if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){ + + } else if ((rx_lcids[i] < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH%d, received %d bytes form UE %d \n", + enb_mod_idP,CC_idP,frameP, rx_lcids[i], rx_lengths[i], UE_id); #if defined(ENABLE_MAC_PAYLOAD_DEBUG) LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP)); - for (j=0; j<32; j++) { LOG_T(MAC,"%x ",payload_ptr[j]); } - LOG_T(MAC,"\n"); #endif - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n", - enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id,rx_lcids[i]); - if (UE_id != -1) { if ((rx_lengths[i] <SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0) ) { // MAX SIZE OF transport block mac_rlc_data_ind( - enb_mod_idP, - rntiP, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DTCH, - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); + enb_mod_idP, + rntiP, + enb_mod_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcids[i], + (char *)payload_ptr, + rx_lengths[i], + 1, + NULL);//(unsigned int*)crc_status); + UE_list->eNB_UE_stats[CC_idP][UE_id].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]; } - } /* UE_id != -1 */ - - // } - break; - - default : //if (rx_lcids[i] >= DTCH) { - if (UE_id != -1) - UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1; + } else { /* UE_id != -1 */ + UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1; + } + } else { + UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1; LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id); - break; } - + payload_ptr+=rx_lengths[i]; } diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index ee6340cb43a4b7dfb6483725b3e57cffeba8d328..90d227eb35a500f27d913845239727c05d565605 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -302,16 +302,12 @@ uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_i //------------------------------------------------------------------------------ void -ue_send_sdu( - module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t* sdu, - uint16_t sdu_len, - uint8_t eNB_index -) -//------------------------------------------------------------------------------ -{ +ue_send_sdu(module_id_t module_idP, + uint8_t CC_id, + frame_t frameP, + uint8_t* sdu, + uint16_t sdu_len, + uint8_t eNB_index) { unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr; unsigned char rx_lcids[NB_RB_MAX]; @@ -401,7 +397,7 @@ ue_send_sdu( #ifdef DEBUG_HEADER_PARSING LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]); #endif - + if (rx_lcids[i] == CCCH) { LOG_D(MAC,"[UE %d] rnti %x Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n", @@ -431,7 +427,7 @@ ue_send_sdu( eNB_index, 0); - } else if (rx_lcids[i] == DCCH) { + } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) { LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i],eNB_index,rx_lengths[i]); mac_rlc_data_ind(module_idP, UE_mac_inst[module_idP].crnti, @@ -439,53 +435,39 @@ ue_send_sdu( frameP, ENB_FLAG_NO, MBMS_FLAG_NO, - DCCH, - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL); - } else if (rx_lcids[i] == DCCH1) { - LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i], eNB_index,rx_lengths[i]); - mac_rlc_data_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - DCCH1, + rx_lcids[i], (char *)payload_ptr, rx_lengths[i], 1, NULL); - } else if (rx_lcids[i] == DTCH) { + + } else if ((rx_lcids[i] < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) { + LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]); #if defined(ENABLE_MAC_PAYLOAD_DEBUG) int j; - - for (j=0; j<rx_lengths[i]; j++) { - LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]); - } - + for (j=0;j<rx_lengths[i];j++) + LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]); LOG_T(MAC,"\n"); #endif - mac_rlc_data_ind(module_idP, - UE_mac_inst[module_idP].crnti, + UE_mac_inst[module_idP].crnti, eNB_index, frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - DTCH, - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL); + ENB_FLAG_NO, + MBMS_FLAG_NO, + rx_lcids[i], + (char *)payload_ptr, + rx_lengths[i], + 1, + NULL); + } else { + LOG_E(MAC,"[UE %d] Frame %d : unknown LCID %d (eNB %d)\n", module_idP, frameP,rx_lcids[i], eNB_index); } - payload_ptr+= rx_lengths[i]; } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); } @@ -1196,10 +1178,11 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf { mac_rlc_status_resp_t rlc_status; - uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0; + uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0,dtch_header_len_last=0; uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0; uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0; uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0; + uint8_t lcid=0; uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t payload_offset=0,num_sdus=0; @@ -1277,18 +1260,27 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf // check for UL bandwidth requests and add SR control element // Check for DCCH first - sdu_lengths[0]=0; if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] == LCID_NOT_EMPTY) { - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index, frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index + rlc_status = mac_rlc_status_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, // eNB_index DCCH, (buflen-dcch_header_len-bsr_len-phr_len)); LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to " "send (Transport Block size %d, mac header len %d)\n", module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch_header_len); - sdu_lengths[0] += mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO, MBMS_FLAG_NO, + sdu_lengths[0] += mac_rlc_data_req(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, DCCH, (char *)&ulsch_buff[sdu_lengths[0]]); @@ -1306,11 +1298,15 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf // if the RLC AM is used, then RLC will only provide 2 bytes for ACK // in this case, we sould add bsr - // DCCH1 if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH1] == LCID_NOT_EMPTY) { - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index + rlc_status = mac_rlc_status_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, // eNB_index DCCH1, (buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-sdu_length_total)); @@ -1318,9 +1314,14 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf " send (Transport Block size %d, mac header len %d)\n", module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch1_header_len); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, - DCCH1, - (char *)&ulsch_buff[sdu_lengths[0]]); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + DCCH1, + (char *)&ulsch_buff[sdu_lengths[num_sdus]]); sdu_length_total += sdu_lengths[num_sdus]; sdu_lcids[num_sdus] = DCCH1; LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH1\n",module_idP,sdu_lengths[num_sdus]); @@ -1331,8 +1332,14 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf dcch1_header_len =0; } - if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_NOT_EMPTY) && - ((bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total) <= buflen)) { + dtch_header_len=0; + dtch_header_len_last=0; + for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){ + dtch_header_len+=3; + dtch_header_len_last=3; + + if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) && + ((bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total) <= buflen)) { // optimize the dtch header lenght //if ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] > 128) && @@ -1343,29 +1350,47 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf else dtch_header_len = 2;//sizeof(SCH_SUBHEADER_SHORT); */ - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index - DTCH, - buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total); - - LOG_D(MAC,"[UE %d] Frame %d : UL-DTCH -> ULSCH, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte[DTCH] %d)\n", - module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dtch_header_len, - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]); - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,UE_mac_inst[module_idP].crnti,eNB_index,frameP, ENB_FLAG_NO, MBMS_FLAG_NO, // eNB_index - DTCH, - (char *)&ulsch_buff[sdu_length_total]); - - //adjust dtch header - dtch_header_len = (sdu_lengths[num_sdus] >= 128) ? 3 : 2; - LOG_D(MAC,"[UE %d] TX Got %d bytes for DTCH\n",module_idP,sdu_lengths[num_sdus]); - sdu_lcids[num_sdus] = DTCH; - sdu_length_total += sdu_lengths[num_sdus]; - num_sdus++; - UE_mac_inst[module_idP].ul_active = update_bsr(module_idP, frameP, eNB_index,DTCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DTCH]); - } else { // no rlc pdu : generate the dummy header - dtch_header_len = 0; + rlc_status = mac_rlc_status_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, // eNB_index + lcid, + buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total); + + LOG_D(MAC,"[UE %d] Frame %d : UL-DTCH -> ULSCH%d, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte[%d] %d)\n", + module_idP,frameP, lcid, rlc_status.bytes_in_buffer,buflen,dtch_header_len, + lcid, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcid]); + + if (rlc_status.bytes_in_buffer > 0) { + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, // eNB_index + lcid, + (char *)&ulsch_buff[sdu_length_total]); + + //adjust dtch header + LOG_D(MAC,"[UE %d] TX Got %d bytes for DTCH\n",module_idP,sdu_lengths[num_sdus]); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + if (sdu_lengths[num_sdus] < 128) { + dtch_header_len --; + dtch_header_len_last --; + } + num_sdus++; + UE_mac_inst[module_idP].ul_active = update_bsr(module_idP, frameP, eNB_index,lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]); + } else { + dtch_header_len -= 3; + } + } else { // no rlc pdu : generate the dummy header + dtch_header_len -= 3; + } } - + lcgid= get_bsr_lcgid(module_idP); if (lcgid < 0 ) { @@ -1406,6 +1431,9 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p); + if (dtch_header_len == 0 ) + dtch_header_len_last =0; + // adjust the header length dcch_header_len_tmp = dcch_header_len; dtch_header_len_tmp = dtch_header_len; @@ -1413,7 +1441,8 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf if (dtch_header_len==0) { dcch_header_len = (dcch_header_len>0)? 1: dcch_header_len; } else { - dtch_header_len= (dtch_header_len >0)? 1: dtch_header_len; // for short and long, cut the length+F fields + dtch_header_len_last-=1; + dtch_header_len= (dtch_header_len >0)? dtch_header_len - dtch_header_len_last : dtch_header_len; } if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) <= 2) { diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h index bae3dc887a7adfe1cfc5163d420a7b00d0f9dc48..1a4d6e0fe1aec4461f2b3e4a3d454fc282f0fae4 100644 --- a/openair2/RRC/LITE/defs.h +++ b/openair2/RRC/LITE/defs.h @@ -220,7 +220,8 @@ typedef struct UE_S_TMSI_s { #if defined(ENABLE_ITTI) typedef enum e_rab_satus_e { E_RAB_STATUS_NEW, - E_RAB_STATUS_DONE, + E_RAB_STATUS_DONE, // from the eNB perspective + E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE E_RAB_STATUS_FAILED, } e_rab_status_t; @@ -232,7 +233,6 @@ typedef struct e_rab_param_s { - /* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */ typedef struct HANDOVER_INFO_s { uint8_t ho_prepare; @@ -347,10 +347,12 @@ typedef struct eNB_RRC_UE_s { security_capabilities_t security_capabilities; + /* Total number of e_rab already setup in the list */ + uint8_t setup_e_rabs; /* Number of e_rab to be setup in the list */ uint8_t nb_of_e_rabs; /* list of e_rab to be setup by RRC layers */ - e_rab_param_t e_rab[S1AP_MAX_E_RAB]; + e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; // LG: For GTPV1 TUNNELS uint32_t enb_gtp_teid[S1AP_MAX_E_RAB]; diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h index 5d77698c8e4a5b3a5465f50c2c91d7b0c3780687..5d5875b03297ee275958e73b56ab5fe863752d1d 100644 --- a/openair2/RRC/LITE/proto.h +++ b/openair2/RRC/LITE/proto.h @@ -257,6 +257,17 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration( const uint8_t ho_state ); +void +rrc_eNB_generate_dedeicatedRRCConnectionReconfiguration( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const uint8_t ho_state +); + +void +rrc_eNB_reconfigure_DRBs (const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* ue_context_pP); + #if defined(ENABLE_ITTI) /**\brief RRC eNB task. \param void *args_p Pointer on arguments to start the task. */ diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index f19c3bced4b9d9d7796b520a8de0a8fed4b87d74..db70e4daf5039aa5c31a96c70998fda69d930d5c 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -1055,13 +1055,232 @@ rrc_eNB_generate_RRCConnectionRelease( PDCP_TRANSMISSION_MODE_CONTROL); } +// 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_defaultRRCConnectionReconfiguration( - const protocol_ctxt_t* const ctxt_pP, - rrc_eNB_ue_context_t* const ue_context_pP, - const uint8_t ho_state -) +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; + //DRB_ToAddModList_t** RRC_DRB_configList=&ue_context_pP->ue_context.DRB_configList; + + struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; + DedicatedInfoNAS_t *dedicatedInfoNas = NULL; + + long *logicalchannelgroup, *logicalchannelgroup_drb; + int drb_Identity_index; + +// Configure DRB + //*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); + *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); + + for ( i = 0 ; + i < ue_context_pP->ue_context.nb_of_e_rabs; + i++){ + // bypass the already configured erabs + if (ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_DONE) { + //drb_identiy_index++; + continue; + } + DRB_config = CALLOC(1, sizeof(*DRB_config)); + + DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); + *(DRB_config->eps_BearerIdentity) = 5L; + + DRB_config->drb_Identity = (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + // 1 + drb_identiy_index; + + DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); + *(DRB_config->logicalChannelIdentity) = (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){ + case 1: // RLC _UM + case 2: + case 3: + case 4: + case 5: + // 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; + // 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; + case 6: + case 7: + case 8: + case 9: + default: + // 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 + PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); + DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; + PDCP_rlc_AM->statusReportRequired = FALSE; + + //LOG_I(RRC,"not supported qci %d\n", ue_context_pP->ue_context.e_rab[i].param.qos.qci); + break; + } + + DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed; + + DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); + DRB_config->logicalChannelConfig = DRB_lchan_config; + DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); + DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; + + DRB_ul_SpecificParameters->priority = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level; + // TO DO + DRB_ul_SpecificParameters->prioritisedBitRate = + LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + DRB_ul_SpecificParameters->bucketSizeDuration = + LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + + // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM) + logicalchannelgroup_drb = CALLOC(1, sizeof(long)); + *logicalchannelgroup_drb = 1; + DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; + + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); + +#if defined(ENABLE_ITTI) + + 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); + } + /* 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->list.count == 0) { + free(dedicatedInfoNASList); + dedicatedInfoNASList = NULL; + } +#endif + + ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; + + } + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCConnectionReconfiguration(ctxt_pP, + buffer, + rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), //Transaction_id, + (SRB_ToAddModList_t*)NULL, + (DRB_ToAddModList_t*)*DRB_configList, + (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 +#ifdef Rel10 + , (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" dedicated rrcConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + pdcp_rrc_data_req( + ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + + +} +#endif +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_defaultRRCConnectionReconfiguration(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]; @@ -1193,7 +1412,6 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration( *(DRB_config->eps_BearerIdentity) = 5L; // LW set to first value, allowed value 5..15, value : x+4 // DRB_config->drb_Identity = (DRB_Identity_t) 1; //allowed values 1..32 // NN: this is the 1st DRB for this ue, so set it to 1 - // NN: this is the 1st DRB for this ue, so set it to 1 DRB_config->drb_Identity = (DRB_Identity_t) 1; // (ue_mod_idP+1); //allowed values 1..32, value: x DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); *(DRB_config->logicalChannelIdentity) = (long)3; // value : x+2 @@ -1625,11 +1843,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration( #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 @@ -3818,7 +4034,8 @@ rrc_eNB_decode_dcch( UE_EUTRA_Capability_t *UE_EUTRA_Capability = NULL; int i; struct rrc_eNB_ue_context_s* ue_context_p = NULL; - + int dedicated_DRB=0; + if ((Srb_id != 1) && (Srb_id != 2)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d, should not have ...\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -3946,23 +4163,36 @@ rrc_eNB_decode_dcch( rrcConnectionReconfigurationComplete. criticalExtensions.choice. rrcConnectionReconfigurationComplete_r8); - ue_context_p->ue_context.Status = RRC_RECONFIGURED; - LOG_I(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED \n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + if (ue_context_p->ue_context.Status == RRC_RECONFIGURED){ + dedicated_DRB = 1; + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + }else { + ue_context_p->ue_context.Status = RRC_RECONFIGURED; + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + } } - -#if defined(ENABLE_USE_MME) -# if defined(ENABLE_ITTI) - +#if defined(ENABLE_ITTI) +# if defined(ENABLE_USE_MME) if (EPC_MODE_ENABLED == 1) { - rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP( - ctxt_pP, - ue_context_p); + if (dedicated_DRB == 1){ + rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, + ue_context_p); + }else { + rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, + ue_context_p); + } + } +#else // establish a dedicated bearer + if (dedicated_DRB == 0 ) { + rrc_eNB_reconfigure_DRBs(ctxt_pP,ue_context_p); } - -# endif + #endif +#endif break; case UL_DCCH_MessageType__c1_PR_rrcConnectionReestablishmentComplete: @@ -4255,6 +4485,41 @@ rrc_eNB_decode_dcch( } #if defined(ENABLE_ITTI) +void rrc_eNB_reconfigure_DRBs (const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* ue_context_pP){ + + int i; + + for (i = 0; + i < NB_RB_MAX; // S1AP_MAX_E_RAB + i++) { + + if ( (ue_context_pP->ue_context.e_rab[i].status != E_RAB_STATUS_ESTABLISHED) || + (ue_context_pP->ue_context.e_rab[i].status != E_RAB_STATUS_DONE) ){ + LOG_I(RRC,"setting up the dedicated DRBs %d \n", i); + ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_NEW; + ue_context_pP->ue_context.e_rab[i].param.e_rab_id = i; + ue_context_pP->ue_context.e_rab[i].param.qos.qci = i % 9; + ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level= i % PRIORITY_LEVEL_LOWEST; + ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability= PRE_EMPTION_CAPABILITY_DISABLED; + ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability= PRE_EMPTION_VULNERABILITY_DISABLED; + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL; + ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length = 0; + // memset (ue_context_pP->ue_context.e_rab[i].param.sgw_addr.buffer,0,20); + ue_context_pP->ue_context.e_rab[i].param.sgw_addr.length = 0; + ue_context_pP->ue_context.e_rab[i].param.gtp_teid=0; + + ue_context_pP->ue_context.nb_of_e_rabs++; + } + + ue_context_pP->ue_context.setup_e_rabs+=ue_context_pP->ue_context.nb_of_e_rabs; + + } + + rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(ctxt_pP, ue_context_pP, 0); +} + + //----------------------------------------------------------------------------- void* rrc_enb_task( @@ -4350,7 +4615,12 @@ rrc_enb_task( case S1AP_PAGING_IND: LOG_E(RRC, "[eNB %d] Received not yet implemented message %s\n", instance, msg_name_p); 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_UE_CONTEXT_RELEASE_REQ: rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance); break; diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 5c41658862149af84f0fd0a5ab48ed3a4070264d..da5c749b119e04fe8ea810fc0b89cfe4c6b8bd81 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -474,8 +474,10 @@ rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP( S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab]; S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab]; S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr.length = 4; + ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED; } else { e_rabs_failed++; + ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED; S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; // TODO add cause when it will be integrated } @@ -842,6 +844,93 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS( return (0); } } +int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance) +{ + uint16_t ue_initial_id; + uint32_t eNB_ue_s1ap_id; + MessageDef *message_gtpv1u_p = NULL; + gtpv1u_enb_create_tunnel_req_t create_tunnel_req; + gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; + + struct rrc_eNB_ue_context_s* ue_context_p = NULL; + protocol_ctxt_t ctxt; + 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); + LOG_I(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_SETUP_REQ (msg_p).nb_e_rabs_tosetup); + + if (ue_context_p == NULL) { + /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ + MessageDef *msg_fail_p = NULL; + + LOG_W(RRC, "[eNB %d] In S1AP_E_RAB_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_SETUP_REQUEST_FAIL); + S1AP_E_RAB_SETUP_REQ (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; + + // TODO add failure cause when defined! + + 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 = S1AP_E_RAB_SETUP_REQ (msg_p).eNB_ue_s1ap_id; + + /* Save e RAB information for later */ + { + int i; + + 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; + + // keep the previous bearer + for (i = ue_context_p->ue_context.setup_e_rabs; + i < ue_context_p->ue_context.setup_e_rabs + nb_e_rabs_tosetup; + i++) { + if (ue_context_p->ue_context.e_rab[i].status == E_RAB_STATUS_DONE) + LOG_W(RRC,"E-RAB already configured, reconfiguring\n"); + 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[i]; + + + 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; + + memcpy(&create_tunnel_req.sgw_addr[i], + & S1AP_E_RAB_SETUP_REQ (msg_p).e_rab_setup_params[i].sgw_addr, + sizeof(transport_layer_addr_t)); + + } + ue_context_p->ue_context.nb_of_e_rabs=nb_e_rabs_tosetup; + ue_context_p->ue_context.setup_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; + + // NN: not sure if we should create a new tunnel: need to check teid, etc. + gtpv1u_create_s1u_tunnel( + instance, + &create_tunnel_req, + &create_tunnel_resp); + + rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( + &ctxt, + &create_tunnel_resp); + + } + + /* TODO parameters yet to process ... */ + { + // S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_ambr; + } + + rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0); + + return (0); + } +} /*------------------------------------------------------------------------------*/ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance) @@ -884,7 +973,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req)); ue_context_p->ue_context.nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs; - + for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++) { ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW; ue_context_p->ue_context.e_rab[i].param = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i]; @@ -897,6 +986,8 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char &S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i].sgw_addr, sizeof(transport_layer_addr_t)); } + + ue_context_p->ue_context.setup_e_rabs =ue_context_p->ue_context.nb_of_e_rabs; create_tunnel_req.rnti = ue_context_p->ue_context.rnti; // warning put zero above create_tunnel_req.num_tunnels = i; @@ -1217,6 +1308,52 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch } } +rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP){ + + MessageDef *msg_p = NULL; + 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_SETUP_RESP); + S1AP_E_RAB_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; + + for (e_rab = ue_context_pP->ue_context.setup_e_rabs - ue_context_pP->ue_context.nb_of_e_rabs; + e_rab < ue_context_pP->ue_context.setup_e_rabs; e_rab++) { + if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) { + e_rabs_done++; + S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; + // TODO add other information from S1-U when it will be integrated + S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs[e_rab].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab]; + S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab]; + S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs[e_rab].eNB_addr.length = 4; + ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED; + } else { + e_rabs_failed++; + ue_context_pP->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED; + S1AP_E_RAB_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; + // TODO add cause when it will be integrated + } + } + + 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_SETUP_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_SETUP_RESP (msg_p).eNB_ue_s1ap_id, + e_rabs_done, e_rabs_failed); + + + 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; + + itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p); +} # endif /* defined(ENABLE_ITTI) */ #endif /* defined(ENABLE_USE_MME) */ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c880c3f3b4bd14ec45b217df4a1ffb6be346a5d9..0b1eee094d743dfc2dd484fc672db5c15066f780 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -328,6 +328,12 @@ void *s1ap_eNB_task(void *arg) } break; + case S1AP_E_RAB_SETUP_RESP: { + s1ap_eNB_e_rab_setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &S1AP_E_RAB_SETUP_RESP(received_msg)); + } + break; + case S1AP_NAS_NON_DELIVERY_IND: { s1ap_eNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_NAS_NON_DELIVERY_IND(received_msg)); diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index f8230520ce25acda109361a94d467f1d4cfc3002..0c4a70a204b627310174c10b1208e0385f6e2494 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -120,6 +120,14 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message, break; + case S1ap_ProcedureCode_id_E_RABSetup: + ret = s1ap_decode_s1ap_e_rabsetuprequesties( + &message->msg.s1ap_E_RABSetupRequestIEs, &initiating_p->value); + s1ap_xer_print_s1ap_paging(s1ap_xer__print2sp, message_string, message); + //message_id = S1AP_E_RABSETUP_REQ_LOG; + S1AP_ERROR("TODO E_RABSetup initiating message\n"); + free(message_string); + break; default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)initiating_p->procedureCode); diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 6f0d4128c7174d1b96a819b240038a3e7f2a99e4..45cf8f4cea9a27fc0b86417566bb6becb922b247 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -82,6 +82,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *s1ap_message_p); + +static +int s1ap_eNB_handle_e_rab_setup_request(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] = { { 0, 0, 0 }, /* HandoverPreparation */ @@ -89,7 +96,7 @@ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverNotification */ { 0, 0, 0 }, /* PathSwitchRequest */ { 0, 0, 0 }, /* HandoverCancel */ - { 0, 0, 0 }, /* E_RABSetup */ + { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */ { 0, 0, 0 }, /* E_RABModify */ { 0, 0, 0 }, /* E_RABRelease */ { 0, 0, 0 }, /* E_RABReleaseIndication */ @@ -872,3 +879,107 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, } } +static +int s1ap_eNB_handle_e_rab_setup_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; + + S1ap_E_RABSetupRequestIEs_t *s1ap_E_RABSetupRequest; + DevAssert(s1ap_message_p != NULL); + + s1ap_E_RABSetupRequest = &s1ap_message_p->msg.s1ap_E_RABSetupRequestIEs; + + if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { + S1AP_ERROR("[SCTP %d] Received initial context setup 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_RABSetupRequest->eNB_UE_S1AP_ID)) == NULL) { + S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + "existing UE context 0x%06x\n", assoc_id, + s1ap_E_RABSetupRequest->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_RABSetupRequest->mme_ue_s1ap_id){ + S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %d)", + ue_desc_p->mme_ue_s1ap_id, s1ap_E_RABSetupRequest->mme_ue_s1ap_id); + + } + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_SETUP_REQ); + + S1AP_E_RAB_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + + S1AP_E_RAB_SETUP_REQ(message_p).mme_ue_s1ap_id = s1ap_E_RABSetupRequest->mme_ue_s1ap_id; + S1AP_E_RAB_SETUP_REQ(message_p).eNB_ue_s1ap_id = s1ap_E_RABSetupRequest->eNB_UE_S1AP_ID; + + S1AP_E_RAB_SETUP_REQ(message_p).nb_e_rabs_tosetup = + s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.count; + + for (i = 0; i < s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.count; i++) { + S1ap_E_RABToBeSetupItemBearerSUReq_t *item_p; + + item_p = (S1ap_E_RABToBeSetupItemBearerSUReq_t *)s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.array[i]; + + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_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_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = item_p->nAS_PDU.size; + + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size); + + memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer, + item_p->nAS_PDU.buf, item_p->nAS_PDU.size); + } else { + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0; + 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; + } + + /* Set the transport layer address */ + memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer, + item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size); + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.length = + item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused; + + /* GTP tunnel endpoint ID */ + OCTET_STRING_TO_INT32(&item_p->gTP_TEID, S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].gtp_teid); + + /* Set the QOS informations */ + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI; + + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.allocation_retention_priority.priority_level = + item_p->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel; + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].qos.allocation_retention_priority.pre_emp_capability = + item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability; + S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_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; +} + + diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index 0cd4c08cb1244d2ab1a53bf3a2a3ccbbe7fecac0..e54a04f00991e77409b0b7d8943dd4a363f7c67a 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -686,3 +686,94 @@ int s1ap_eNB_ue_capabilities(instance_t instance, return ret; } +//------------------------------------------------------------------------------ +int s1ap_eNB_e_rab_setup_resp(instance_t instance, + s1ap_e_rab_setup_resp_t *e_rab_setup_resp_p) +//------------------------------------------------------------------------------ +{ + s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + + S1ap_E_RABSetupResponseIEs_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_setup_resp_p != NULL); + DevAssert(s1ap_eNB_instance_p != NULL); + + if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, + e_rab_setup_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_setup_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_setup_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_RABSetup; + + initial_ies_p = &message.msg.s1ap_E_RABSetupResponseIEs; + + initial_ies_p->eNB_UE_S1AP_ID = e_rab_setup_resp_p->eNB_ue_s1ap_id; + initial_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; + + for (i = 0; i < e_rab_setup_resp_p->nb_of_e_rabs; i++) { + S1ap_E_RABSetupItemBearerSURes_t *new_item; + + new_item = calloc(1, sizeof(S1ap_E_RABSetupItemBearerSURes_t)); + + new_item->e_RAB_ID = e_rab_setup_resp_p->e_rabs[i].e_rab_id; + GTP_TEID_TO_ASN1(e_rab_setup_resp_p->e_rabs[i].gtp_teid, &new_item->gTP_TEID); + new_item->transportLayerAddress.buf = e_rab_setup_resp_p->e_rabs[i].eNB_addr.buffer; + new_item->transportLayerAddress.size = e_rab_setup_resp_p->e_rabs[i].eNB_addr.length; + new_item->transportLayerAddress.bits_unused = 0; + + ASN_SEQUENCE_ADD(&initial_ies_p->e_RABSetupListBearerSURes.s1ap_E_RABSetupItemBearerSURes, + new_item); + } + + if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { + S1AP_ERROR("Failed to encode uplink NAS 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 Setup successfulOutcome 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; +}