Commit 2a305672 authored by Navid Nikaein's avatar Navid Nikaein

Additional RRC procedures (RRCConnectionReconfiguration) for dedicated bearer...

Additional RRC procedures (RRCConnectionReconfiguration) for dedicated bearer estatblishment triggered by S1AP messages.
eNB mac scheduler for dedicated DTCH.
UE MAC logical channel prioritization with additional DTCH.
S1AP messages for dedicated bearer establishment (eNB and UE).
parent 916008f4
......@@ -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) */
......
......@@ -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 {
......
......@@ -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) {
......
......@@ -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
......
......@@ -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,85 +905,93 @@ 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];
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++;
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
// 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
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,
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 ) {
rlc_status = mac_rlc_status_ind(
module_idP,
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,
DTCH,
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->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,
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,
DTCH,
lcid,
(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;
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[DTCH]+=1;
UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DTCH]+=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=2;
header_len_dtch--;
header_len_dtch_last--;
}
num_sdus++;
} else {
header_len_dtch = 0;
} // no data for this LCID
else {
header_len_dtch-=3;
}
} // no TBS left
else {
header_len_dtch-=3;
break;
}
}
// there is a payload
if (((sdu_length_total + header_len_dcch + header_len_dtch )> 0)) {
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 : header_len_dcch; // remove length field
header_len_dcch = (header_len_dcch >0) ? 1 : 0;//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
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;
if (mcs==0) {
......
......@@ -69,8 +69,7 @@
// 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,
void rx_sdu(const module_id_t enb_mod_idP,
const int CC_idP,
const frame_t frameP,
const sub_frame_t subframeP,
......@@ -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,27 +273,23 @@ 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,
......@@ -313,25 +308,18 @@ void rx_sdu(
}
} /* 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(
......@@ -341,25 +329,22 @@ void rx_sdu(
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
DTCH,
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)
} 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];
......
......@@ -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,
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
)
//------------------------------------------------------------------------------
{
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];
......@@ -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,50 +435,36 @@ 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++) {
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,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
DTCH,
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];
}
......@@ -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,
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]]);
(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,7 +1332,13 @@ 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) &&
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
......@@ -1343,27 +1350,45 @@ 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,
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 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]);
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]);
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,
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
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_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,DTCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DTCH]);
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 = 0;
dtch_header_len -= 3;
}
}
lcgid= get_bsr_lcgid(module_idP);
......@@ -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) {
......
......@@ -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];
......
......@@ -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. */
......
......@@ -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_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,6 +4034,7 @@ 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",
......@@ -3946,22 +4163,35 @@ rrc_eNB_decode_dcch(
rrcConnectionReconfigurationComplete.
criticalExtensions.choice.
rrcConnectionReconfigurationComplete_r8);
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 \n",
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,
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;
......@@ -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(
......@@ -4351,6 +4616,11 @@ rrc_enb_task(
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;
......
......@@ -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)
......@@ -898,6 +987,8 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
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) */
......@@ -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));
......
......@@ -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);
......
......@@ -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;
}
......@@ -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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment