Separated RRC <-> S1AP procedures.
Pre-ci OK. git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4497 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -417,7 +417,7 @@ s8 mac_remove_ue(unsigned char Mod_id, unsigned char UE_id) {
|
||||
eNB_dlsch_info[Mod_id][UE_id].rnti = 0;
|
||||
eNB_dlsch_info[Mod_id][UE_id].status = S_DL_NONE;
|
||||
|
||||
rrc_remove_UE(Mod_id,UE_id);
|
||||
rrc_eNB_free_UE_index(Mod_id,UE_id);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ L2_INTERFACE_DIR = $(OPENAIR2_TOP)/RRC/L2_INTERFACE
|
||||
MAC_DIR = $(OPENAIR2_TOP)/LAYER2/MAC
|
||||
RRC_CELL_DIR = $(OPENAIR2_TOP)/RRC/CELLULAR
|
||||
|
||||
SOURCES_L2 +=$(OPENAIR2_TOP)/LAYER2/openair2_proc.c
|
||||
SOURCES_L2 += $(OPENAIR2_TOP)/LAYER2/openair2_proc.c
|
||||
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp.c
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp_fifo.c
|
||||
@@ -69,7 +69,11 @@ SOURCES_L2 += $(RLC_DIR)/rlc.c
|
||||
SOURCES_L2 += $(RLC_DIR)/rlc_rrc.c
|
||||
SOURCES_L2 += $(RLC_DIR)/rlc_mpls.c
|
||||
|
||||
RRC_OBJS = $(RRC_DIR)/rrc_UE.o $(RRC_DIR)/rrc_eNB.o $(RRC_DIR)/rrc_common.o $(RRC_DIR)/L2_interface.o
|
||||
RRC_OBJS = $(RRC_DIR)/rrc_UE.o
|
||||
RRC_OBJS += $(RRC_DIR)/rrc_eNB.o
|
||||
RRC_OBJS += $(RRC_DIR)/rrc_eNB_S1AP.o
|
||||
RRC_OBJS += $(RRC_DIR)/rrc_common.o
|
||||
RRC_OBJS += $(RRC_DIR)/L2_interface.o
|
||||
|
||||
MAC_OBJS = $(MAC_DIR)/lte_transport_init.o
|
||||
MAC_OBJS += $(MAC_DIR)/main.o
|
||||
@@ -86,8 +90,16 @@ L2_INTERFACE_OBJS = $(L2_INTERFACE_DIR)/openair_rrc_L2_interface.o
|
||||
L2_OBJS=$(addsuffix .o,$(basename $(SOURCES_L2))) $(PHY_INTERFACE_OBJS) $(MAC_OBJS) $(L2_INTERFACE_OBJS)
|
||||
#$(OPT_OBJS)
|
||||
|
||||
L2_incl = -I$(OPENAIR2_TOP) -I$(COMMON_DIR) -I$(RLC_DIR) -I$(RLC_AM_DIR) -I$(RLC_UM_DIR) -I$(RLC_TM_DIR) -I$(PDCP_DIR) -I$(OPENAIR3)/MESH -I$(OPENAIR2_TOP)/RRC/LITE/MESSAGES -I$(OPENAIR3)/MESH/RRM
|
||||
|
||||
L2_incl = -I$(OPENAIR2_TOP)
|
||||
L2_incl += -I$(COMMON_DIR)
|
||||
L2_incl += -I$(RLC_DIR)
|
||||
L2_incl += -I$(RLC_AM_DIR)
|
||||
L2_incl += -I$(RLC_UM_DIR)
|
||||
L2_incl += -I$(RLC_TM_DIR)
|
||||
L2_incl += -I$(PDCP_DIR)
|
||||
L2_incl += -I$(OPENAIR3)/MESH
|
||||
L2_incl += -I$(OPENAIR2_TOP)/RRC/LITE/MESSAGES
|
||||
L2_incl += -I$(OPENAIR3)/MESH/RRM
|
||||
|
||||
ifeq ($(rrc_cellular),1)
|
||||
include $(RRC_CELL_DIR)/Makefile.inc
|
||||
|
||||
@@ -93,6 +93,8 @@
|
||||
|
||||
//#define NUM_PRECONFIGURED_LCHAN (NB_CH_CX*2) //BCCH, CCCH
|
||||
|
||||
#define UE_INDEX_INVALID ((uint8_t) ~0)
|
||||
|
||||
typedef enum UE_STATE_e {
|
||||
RRC_IDLE=0,
|
||||
RRC_SI_RECEIVED,
|
||||
@@ -254,7 +256,7 @@ typedef struct RB_INFO_TABLE_ENTRY_s {
|
||||
u8 Status;
|
||||
} RB_INFO_TABLE_ENTRY;
|
||||
|
||||
typedef struct{
|
||||
typedef struct SRB_INFO_TABLE_ENTRY_s {
|
||||
SRB_INFO Srb_info;
|
||||
u8 Active;
|
||||
u8 Status;
|
||||
@@ -512,6 +514,11 @@ void rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_ind
|
||||
|
||||
// eNB/CH RRC Procedures
|
||||
|
||||
/**\brief Function to get the next transaction identifier.
|
||||
\param Mod_id Instance ID for CH/eNB
|
||||
\return a transaction identifier*/
|
||||
uint8_t rrc_eNB_get_next_transaction_identifier(uint8_t Mod_id);
|
||||
|
||||
/**\brief Entry routine to decode a UL-CCCH-Message. Invokes PER decoder and parses message.
|
||||
\param Mod_id Instance ID for CH/eNB
|
||||
\param frame Frame index
|
||||
@@ -617,7 +624,7 @@ u8 check_trigger_meas_event(u8 Mod_id,u32 frame, u8 eNB_index, u8 ue_cnx_index,
|
||||
//void rrc_ue_process_ueCapabilityEnquiry(uint8_t Mod_id,uint32_t frame,UECapabilityEnquiry_t *UECapabilityEnquiry,uint8_t eNB_index);
|
||||
//void rrc_ue_process_securityModeCommand(uint8_t Mod_id,uint32_t frame,SecurityModeCommand_t *securityModeCommand,uint8_t eNB_index);
|
||||
|
||||
void rrc_remove_UE (u8 Mod_id, u8 UE_id);
|
||||
void rrc_eNB_free_UE_index (u8 Mod_id, u8 UE_id);
|
||||
|
||||
long binary_search_int(int elements[], long numElem, int value);
|
||||
|
||||
|
||||
+46
-348
@@ -80,6 +80,7 @@
|
||||
#endif
|
||||
|
||||
#include "pdcp.h"
|
||||
#include "rrc_eNB_S1AP.h"
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
# include "intertask_interface.h"
|
||||
@@ -102,11 +103,7 @@ extern inline unsigned int taus (void);
|
||||
/* TS 36.331: RRC-TransactionIdentifier ::= INTEGER (0..3) */
|
||||
static const uint8_t RRC_TRANSACTION_IDENTIFIER_NUMBER = 4;
|
||||
|
||||
/* Value to indicate an invalid UE index */
|
||||
static const uint8_t UE_INDEX_INVALID = ~0;
|
||||
|
||||
/* Value to indicate an invalid UE initial id */
|
||||
static const uint16_t UE_INITIAL_ID_INVALID = 0;
|
||||
mui_t rrc_eNB_mui = 0;
|
||||
|
||||
void
|
||||
init_SI (u8 Mod_id) {
|
||||
@@ -450,7 +447,7 @@ init_MBMS (u8 Mod_id, u32 frame) {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static uint8_t get_next_rrc_transaction_identifier(uint8_t Mod_id)
|
||||
uint8_t rrc_eNB_get_next_transaction_identifier(uint8_t Mod_id)
|
||||
{
|
||||
static uint8_t rrc_transaction_identifier[NUMBER_OF_eNB_MAX];
|
||||
|
||||
@@ -461,7 +458,8 @@ static uint8_t get_next_rrc_transaction_identifier(uint8_t Mod_id)
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* Functions to handle UE index in eNB UE list */
|
||||
static uint8_t get_next_UE_index (uint8_t Mod_id, uint8_t *UE_identity)
|
||||
|
||||
static uint8_t rrc_eNB_get_next_free_UE_index (uint8_t Mod_id, uint8_t *UE_identity)
|
||||
{
|
||||
uint8_t i, first_index = UE_INDEX_INVALID, reg = 0;
|
||||
static const uint8_t null_identity[5] =
|
||||
@@ -491,7 +489,7 @@ static uint8_t get_next_UE_index (uint8_t Mod_id, uint8_t *UE_identity)
|
||||
}
|
||||
}
|
||||
|
||||
void rrc_remove_UE (uint8_t Mod_id, uint8_t UE_id)
|
||||
void rrc_eNB_free_UE_index (uint8_t Mod_id, uint8_t UE_id)
|
||||
{
|
||||
DevCheck(Mod_id < NB_eNB_INST, Mod_id, UE_id, NB_eNB_INST);
|
||||
DevCheck(UE_id < NUMBER_OF_UE_MAX, Mod_id, UE_id, NUMBER_OF_UE_MAX);
|
||||
@@ -501,85 +499,32 @@ void rrc_remove_UE (uint8_t Mod_id, uint8_t UE_id)
|
||||
memset(eNB_rrc_inst[Mod_id].Info.UE_list[UE_id], 0, sizeof(eNB_rrc_inst[0].Info.UE_list[0]));
|
||||
}
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* Function to handle UE initial ID for S1AP initial communication */
|
||||
static uint16_t get_next_ue_initial_id(uint8_t Mod_id)
|
||||
void rrc_eNB_generate_SecurityModeCommand (u8 Mod_id, u32 frame, u16 UE_index)
|
||||
{
|
||||
static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
|
||||
|
||||
ue_initial_id[Mod_id] ++;
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
|
||||
/* Never use UE_INITIAL_ID_INVALID this is the invalid id! */
|
||||
if(ue_initial_id[Mod_id] == UE_INITIAL_ID_INVALID)
|
||||
{
|
||||
ue_initial_id[Mod_id] ++;
|
||||
}
|
||||
size = do_SecurityModeCommand (Mod_id, buffer, UE_index, 0,
|
||||
eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index],
|
||||
eNB_rrc_inst[Mod_id].integrity_algorithm[UE_index]);
|
||||
|
||||
LOG_I (RRC,
|
||||
"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d, UE id %d)\n",
|
||||
Mod_id, frame, size, UE_index);
|
||||
|
||||
|
||||
LOG_D (RRC,
|
||||
"[MSC_MSG][FRAME %05d][RRC_eNB][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (securityModeCommand to UE %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
frame, Mod_id, size, UE_index, rrc_eNB_mui, Mod_id,
|
||||
(UE_index * NB_RB_MAX) + DCCH);
|
||||
//rrc_rlc_data_req(Mod_id,frame, 1,(UE_index*NB_RB_MAX)+DCCH,rrc_eNB_mui++,0,size,(char*)buffer);
|
||||
pdcp_rrc_data_req (Mod_id, frame, 1, (UE_index * NB_RB_MAX) + DCCH,
|
||||
rrc_eNB_mui++, 0, size, buffer, 1);
|
||||
|
||||
return ue_initial_id[Mod_id];
|
||||
}
|
||||
|
||||
static uint8_t get_UE_index_from_initial_id (uint8_t Mod_id, uint16_t ue_initial_id)
|
||||
{
|
||||
uint8_t ue_index;
|
||||
static const uint8_t null_identity[5] =
|
||||
{0, 0, 0, 0, 0};
|
||||
|
||||
DevCheck(Mod_id < NB_eNB_INST, Mod_id, NB_eNB_INST, 0);
|
||||
|
||||
for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
|
||||
/* Check if this UE is in use */
|
||||
if (memcmp (eNB_rrc_inst[Mod_id].Info.UE_list[ue_index], null_identity, sizeof(eNB_rrc_inst[0].Info.UE_list[ue_index])) != 0) {
|
||||
/* Check if the initial id match */
|
||||
if (eNB_rrc_inst[Mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) {
|
||||
return ue_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UE_INDEX_INVALID;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static uint8_t get_UE_index_from_eNB_ue_s1ap_id (uint8_t Mod_id, uint16_t eNB_ue_s1ap_id)
|
||||
{
|
||||
uint8_t ue_index;
|
||||
static const uint8_t null_identity[5] =
|
||||
{0, 0, 0, 0, 0};
|
||||
|
||||
DevCheck(Mod_id < NB_eNB_INST, Mod_id, NB_eNB_INST, 0);
|
||||
|
||||
for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
|
||||
/* Check if this UE is in use */
|
||||
if (memcmp (eNB_rrc_inst[Mod_id].Info.UE_list[ue_index], null_identity, sizeof(eNB_rrc_inst[0].Info.UE_list[ue_index])) != 0) {
|
||||
/* Check if the initial id match */
|
||||
if (eNB_rrc_inst[Mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) {
|
||||
return ue_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UE_INDEX_INVALID;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static uint8_t get_UE_index_from_s1ap_ids (uint8_t Mod_id, uint16_t ue_initial_id, uint16_t eNB_ue_s1ap_id)
|
||||
{
|
||||
uint8_t ue_index;
|
||||
|
||||
if (ue_initial_id == UE_INITIAL_ID_INVALID)
|
||||
{
|
||||
/* If "ue_initial_id" is not set search if "eNB_ue_s1ap_id" is know by RRC */
|
||||
ue_index = get_UE_index_from_eNB_ue_s1ap_id (Mod_id, eNB_ue_s1ap_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If "ue_initial_id" is set there is probably not yet an associated "eNB_ue_s1ap_id" with S1AP */
|
||||
ue_index = get_UE_index_from_initial_id(Mod_id, ue_initial_id);
|
||||
}
|
||||
|
||||
return ue_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void rrc_lite_eNB_init_security(u8 Mod_id, u8 UE_index)
|
||||
{
|
||||
@@ -821,9 +766,9 @@ int rrc_eNB_decode_dcch (u8 Mod_id, u32 frame, u8 Srb_id, u8 UE_index,
|
||||
#if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED == 1)
|
||||
{
|
||||
eNB_RRC_UE_INFO *UE_info = &eNB_rrc_inst[Mod_id].Info.UE[UE_index];
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
eNB_RRC_UE_INFO *UE_info = &eNB_rrc_inst[Mod_id].Info.UE[UE_index];
|
||||
|
||||
/* Process e RAB parameters received from S1AP one by one (the previous one is completed, eventually process the next one) */
|
||||
if (UE_info->nb_of_e_rabs > 0)
|
||||
{
|
||||
@@ -844,32 +789,7 @@ int rrc_eNB_decode_dcch (u8 Mod_id, u32 frame, u8 Srb_id, u8 UE_index,
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageDef *msg_p;
|
||||
int e_rab;
|
||||
int e_rabs_done = 0;
|
||||
int e_rabs_failed = 0;
|
||||
|
||||
msg_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_RESP);
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = UE_info->eNB_ue_s1ap_id;
|
||||
for (e_rab = 0; e_rab < UE_info->index_of_e_rabs; e_rab++)
|
||||
{
|
||||
if (UE_info->e_rab[e_rab].status == E_RAB_STATUS_DONE)
|
||||
{
|
||||
e_rabs_done ++;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].e_rab_id = UE_info->e_rab[e_rab].param.e_rab_id;
|
||||
// TODO add other information from S1-U when it will be integrated
|
||||
}
|
||||
else
|
||||
{
|
||||
e_rabs_failed ++;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = UE_info->e_rab[e_rab].param.e_rab_id;
|
||||
// TODO add cause when it will be integrated
|
||||
}
|
||||
}
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs = e_rabs_done;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed;
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, Mod_id, msg_p);
|
||||
rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP (Mod_id, UE_index);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
@@ -1020,71 +940,9 @@ int rrc_eNB_decode_dcch (u8 Mod_id, u32 frame, u8 Srb_id, u8 UE_index,
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
|
||||
#if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED == 1)
|
||||
{
|
||||
if (EPC_MODE_ENABLED == 1)
|
||||
# if defined(ENABLE_ITTI)
|
||||
{
|
||||
ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;
|
||||
|
||||
if ((ulInformationTransfer->criticalExtensions.present ==
|
||||
ULInformationTransfer__criticalExtensions_PR_c1)
|
||||
&& (ulInformationTransfer->criticalExtensions.choice.c1.present ==
|
||||
ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
|
||||
&& (ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType.present ==
|
||||
ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS))
|
||||
{
|
||||
/* This message hold a dedicated info NAS payload, forward it to NAS */
|
||||
struct ULInformationTransfer_r8_IEs__dedicatedInfoType *dedicatedInfoType =
|
||||
&ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType;
|
||||
uint32_t pdu_length;
|
||||
uint8_t *pdu_buffer;
|
||||
MessageDef *msg_p;
|
||||
|
||||
pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size;
|
||||
pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf;
|
||||
|
||||
msg_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UPLINK_NAS);
|
||||
S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = eNB_rrc_inst[Mod_id].Info.UE[UE_index].eNB_ue_s1ap_id;
|
||||
S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
|
||||
S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, Mod_id, msg_p);
|
||||
}
|
||||
}
|
||||
# else
|
||||
{
|
||||
ULInformationTransfer_t *ulInformationTransfer;
|
||||
ulInformationTransfer =
|
||||
&ul_dcch_msg->message.choice.c1.choice.
|
||||
ulInformationTransfer;
|
||||
|
||||
if (ulInformationTransfer->criticalExtensions.present ==
|
||||
ULInformationTransfer__criticalExtensions_PR_c1)
|
||||
{
|
||||
if (ulInformationTransfer->criticalExtensions.choice.c1.
|
||||
present ==
|
||||
ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
|
||||
{
|
||||
|
||||
ULInformationTransfer_r8_IEs_t
|
||||
*ulInformationTransferR8;
|
||||
ulInformationTransferR8 =
|
||||
&ulInformationTransfer->criticalExtensions.choice.
|
||||
c1.choice.ulInformationTransfer_r8;
|
||||
if (ulInformationTransferR8->dedicatedInfoType.
|
||||
present ==
|
||||
ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)
|
||||
s1ap_eNB_new_data_request (Mod_id, UE_index,
|
||||
ulInformationTransferR8->
|
||||
dedicatedInfoType.choice.
|
||||
dedicatedInfoNAS.buf,
|
||||
ulInformationTransferR8->
|
||||
dedicatedInfoType.choice.
|
||||
dedicatedInfoNAS.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
rrc_eNB_send_S1AP_UPLINK_NAS(Mod_id, UE_index, ul_dcch_msg);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -1196,7 +1054,7 @@ for (i = 0; i < 8; i++)
|
||||
frame, Mod_id, Mod_id);
|
||||
|
||||
rrcConnectionRequest = &ul_ccch_msg->message.choice.c1.choice.rrcConnectionRequest.criticalExtensions.choice.rrcConnectionRequest_r8;
|
||||
UE_index = get_next_UE_index (Mod_id,
|
||||
UE_index = rrc_eNB_get_next_free_UE_index (Mod_id,
|
||||
(u8 *) rrcConnectionRequest->ue_Identity.
|
||||
choice.randomValue.buf);
|
||||
|
||||
@@ -1324,6 +1182,7 @@ for (i = 0; i < 8; i++)
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
void rrc_eNB_process_RRCConnectionSetupComplete (u8 Mod_id,
|
||||
u32 frame,
|
||||
u8 UE_index,
|
||||
@@ -1332,112 +1191,28 @@ void rrc_eNB_process_RRCConnectionSetupComplete (u8 Mod_id,
|
||||
LOG_I (RRC, "[eNB %d][RAPROC] Frame %d : Logical Channel UL-DCCH, ""processing RRCConnectionSetupComplete from UE %d\n",
|
||||
Mod_id, frame, UE_index);
|
||||
|
||||
// Forward message to S1AP layer
|
||||
#if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED == 1)
|
||||
# if defined(ENABLE_ITTI)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_FIRST_REQ);
|
||||
eNB_rrc_inst[Mod_id].Info.UE[UE_index].ue_initial_id = get_next_ue_initial_id(Mod_id);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_initial_id = eNB_rrc_inst[Mod_id].Info.UE[UE_index].ue_initial_id;
|
||||
|
||||
/* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
|
||||
DevCheck(eNB_rrc_inst[Mod_id].Info.UE[UE_index].establishment_cause < RRC_CAUSE_LAST, eNB_rrc_inst[Mod_id].Info.UE[UE_index].establishment_cause, RRC_CAUSE_LAST, Mod_id);
|
||||
S1AP_NAS_FIRST_REQ (message_p).establishment_cause = eNB_rrc_inst[Mod_id].Info.UE[UE_index].establishment_cause;
|
||||
|
||||
/* Forward NAS message */
|
||||
S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer = rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
|
||||
S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size;
|
||||
|
||||
/* Fill UE identities with available information */
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask = UE_IDENTITIES_NONE;
|
||||
|
||||
if (eNB_rrc_inst[Mod_id].Info.UE[UE_index].Initialue_identity_s_TMSI.presence) {
|
||||
/* Fill s-TMSI */
|
||||
UE_S_TMSI *s_TMSI = &eNB_rrc_inst[Mod_id].Info.UE[UE_index].Initialue_identity_s_TMSI;
|
||||
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_s_tmsi;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code = s_TMSI->mme_code;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi = s_TMSI->m_tmsi;
|
||||
}
|
||||
|
||||
if (rrcConnectionSetupComplete->registeredMME != NULL) {
|
||||
/* Fill GUMMEI */
|
||||
struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
|
||||
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
|
||||
if (r_mme->plmn_Identity != NULL) {
|
||||
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
|
||||
/* Use first indicated PLMN MCC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
|
||||
}
|
||||
if (r_mme->plmn_Identity->mnc.list.count > 0) {
|
||||
/* Use first indicated PLMN MNC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
|
||||
}
|
||||
}
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
|
||||
}
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, Mod_id, message_p);
|
||||
// Forward message to S1AP layer
|
||||
rrc_eNB_send_S1AP_NAS_FIRST_REQ(Mod_id, UE_index, rrcConnectionSetupComplete);
|
||||
}
|
||||
# else
|
||||
{
|
||||
s1ap_eNB_new_data_request (Mod_id, UE_index,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
buf,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
size);
|
||||
}
|
||||
# endif
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
// RRC loop back (no S1AP), send SecurityModeCommand to UE
|
||||
rrc_eNB_generate_SecurityModeCommand (Mod_id, frame, UE_index);
|
||||
// rrc_eNB_generate_UECapabilityEnquiry(Mod_id,frame,UE_index);
|
||||
}
|
||||
}
|
||||
|
||||
mui_t rrc_eNB_mui = 0;
|
||||
|
||||
void rrc_eNB_generate_SecurityModeCommand (u8 Mod_id, u32 frame, u16 UE_index)
|
||||
{
|
||||
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
|
||||
size = do_SecurityModeCommand (Mod_id, buffer, UE_index, 0,
|
||||
eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index],
|
||||
eNB_rrc_inst[Mod_id].integrity_algorithm[UE_index]);
|
||||
|
||||
LOG_I (RRC,
|
||||
"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d, UE id %d)\n",
|
||||
Mod_id, frame, size, UE_index);
|
||||
|
||||
|
||||
LOG_D (RRC,
|
||||
"[MSC_MSG][FRAME %05d][RRC_eNB][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (securityModeCommand to UE %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
frame, Mod_id, size, UE_index, rrc_eNB_mui, Mod_id,
|
||||
(UE_index * NB_RB_MAX) + DCCH);
|
||||
//rrc_rlc_data_req(Mod_id,frame, 1,(UE_index*NB_RB_MAX)+DCCH,rrc_eNB_mui++,0,size,(char*)buffer);
|
||||
pdcp_rrc_data_req (Mod_id, frame, 1, (UE_index * NB_RB_MAX) + DCCH,
|
||||
rrc_eNB_mui++, 0, size, buffer, 1);
|
||||
|
||||
}
|
||||
|
||||
void rrc_eNB_generate_UECapabilityEnquiry (u8 Mod_id, u32 frame, u16 UE_index)
|
||||
{
|
||||
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
|
||||
size = do_UECapabilityEnquiry (Mod_id, buffer, UE_index, get_next_rrc_transaction_identifier(Mod_id));
|
||||
size = do_UECapabilityEnquiry (Mod_id, buffer, UE_index, rrc_eNB_get_next_transaction_identifier(Mod_id));
|
||||
|
||||
LOG_I (RRC,
|
||||
"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate UECapabilityEnquiry (bytes %d, UE id %d)\n",
|
||||
@@ -1903,7 +1678,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration (u8 Mod_id, u32 frame,
|
||||
|
||||
memset (buffer, 0, RRC_BUF_SIZE);
|
||||
|
||||
size = do_RRCConnectionReconfiguration (Mod_id, buffer, UE_index, get_next_rrc_transaction_identifier(Mod_id), //Transaction_id,
|
||||
size = do_RRCConnectionReconfiguration (Mod_id, buffer, UE_index, rrc_eNB_get_next_transaction_identifier(Mod_id), //Transaction_id,
|
||||
SRB_configList2, *DRB_configList, NULL, // DRB2_list,
|
||||
NULL, //*sps_Config,
|
||||
physicalConfigDedicated[UE_index], MeasObj_list, ReportConfig_list,
|
||||
@@ -2016,7 +1791,7 @@ void rrc_eNB_generate_HandoverPreparationInformation (u8 Mod_id, u32 frame, u8 U
|
||||
|
||||
if (mod_id_target != 0xFF) {
|
||||
//UE_id_target = rrc_find_free_ue_index(modid_target);
|
||||
UE_id_target = get_next_UE_index(mod_id_target,(u8 *)eNB_rrc_inst[Mod_id].Info.UE_list[UE_index]); //this should return a new index
|
||||
UE_id_target = rrc_eNB_get_next_free_UE_index(mod_id_target,(u8 *)eNB_rrc_inst[Mod_id].Info.UE_list[UE_index]); //this should return a new index
|
||||
|
||||
if (UE_id_target!=0xFF) {
|
||||
LOG_N(RRC,"[eNB %d] Frame %d : Emulate sending HandoverPreparationInformation msg from eNB source %d to eNB target %d: source UE_id %d target UE_id %d source_modId: %d target_modId: %d\n",Mod_id,frame,eNB_rrc_inst[Mod_id].physCellId,targetPhyId,UE_index,UE_id_target,Mod_id,mod_id_target);
|
||||
@@ -2833,7 +2608,7 @@ void rrc_eNB_generate_RRCConnectionReconfiguration_handover (u8 Mod_id, u32 fram
|
||||
// rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list;
|
||||
memset (buffer, 0, RRC_BUF_SIZE);
|
||||
|
||||
size = do_RRCConnectionReconfiguration (Mod_id, buffer, UE_index, get_next_rrc_transaction_identifier(Mod_id), //Transaction_id,
|
||||
size = do_RRCConnectionReconfiguration (Mod_id, buffer, UE_index, rrc_eNB_get_next_transaction_identifier(Mod_id), //Transaction_id,
|
||||
SRB_configList2, DRB_configList2, NULL, // DRB2_list,
|
||||
NULL, //*sps_Config,
|
||||
physicalConfigDedicated[UE_index], MeasObj_list, ReportConfig_list,
|
||||
@@ -3231,9 +3006,6 @@ void *rrc_enb_task(void *args_p) {
|
||||
const char *msg_name;
|
||||
instance_t instance;
|
||||
SRB_INFO *srb_info_p;
|
||||
uint8_t ue_index;
|
||||
uint32_t length;
|
||||
uint8_t *buffer;
|
||||
|
||||
itti_mark_task_ready (TASK_RRC_ENB);
|
||||
|
||||
@@ -3253,7 +3025,7 @@ void *rrc_enb_task(void *args_p) {
|
||||
LOG_D(RRC, "Received %s\n", msg_name);
|
||||
break;
|
||||
|
||||
/* MAC messages */
|
||||
/* Messages from MAC */
|
||||
case RRC_MAC_CCCH_DATA_IND:
|
||||
LOG_D(RRC, "Received %s: instance %d, frame %d,\n", msg_name, instance,
|
||||
RRC_MAC_CCCH_DATA_IND (msg_p).frame);
|
||||
@@ -3266,7 +3038,7 @@ void *rrc_enb_task(void *args_p) {
|
||||
rrc_eNB_decode_ccch (instance, RRC_MAC_CCCH_DATA_IND (msg_p).frame, srb_info_p);
|
||||
break;
|
||||
|
||||
/* PDCP messages */
|
||||
/* Messages from PDCP */
|
||||
case RRC_DCCH_DATA_IND:
|
||||
LOG_D(RRC, "Received %s: instance %d, frame %d, DCCH %d, UE %d\n", msg_name, instance,
|
||||
RRC_DCCH_DATA_IND (msg_p).frame, RRC_DCCH_DATA_IND (msg_p).dcch_index, RRC_DCCH_DATA_IND (msg_p).ue_index);
|
||||
@@ -3279,90 +3051,16 @@ void *rrc_enb_task(void *args_p) {
|
||||
free (RRC_DCCH_DATA_IND (msg_p).sdu_p);
|
||||
break;
|
||||
|
||||
/* S1AP Messages */
|
||||
#if defined(ENABLE_USE_MME)
|
||||
/* Messages from S1AP */
|
||||
case S1AP_DOWNLINK_NAS:
|
||||
ue_index = get_UE_index_from_s1ap_ids(instance, S1AP_DOWNLINK_NAS (msg_p).ue_initial_id, S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id);
|
||||
|
||||
LOG_D(RRC, "Received %s: instance %d, ue_initial_id %d, eNB_ue_s1ap_id %d, ue_index %d\n", msg_name, instance,
|
||||
S1AP_DOWNLINK_NAS (msg_p).ue_initial_id, S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id, ue_index);
|
||||
|
||||
if (ue_index == UE_INDEX_INVALID)
|
||||
{
|
||||
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
|
||||
MessageDef *msg_fail_p;
|
||||
|
||||
LOG_W(RRC, "In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d) for eNB %d\n",
|
||||
S1AP_DOWNLINK_NAS (msg_p).ue_initial_id, S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id, instance);
|
||||
|
||||
msg_fail_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL); // TODO change message!
|
||||
S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, instance, msg_fail_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create message for PDCP (DLInformationTransfer_t) */
|
||||
length = do_DLInformationTransfer(&buffer, get_next_rrc_transaction_identifier(instance),
|
||||
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length, S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
|
||||
|
||||
/* Transfer data to PDCP */
|
||||
pdcp_rrc_data_req (instance, 0 /* TODO put frame number ! */, 1, (ue_index * NB_RB_MAX) + DCCH, rrc_eNB_mui++, 0, length, buffer, 1);
|
||||
}
|
||||
rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name, instance, &rrc_eNB_mui);
|
||||
break;
|
||||
|
||||
case S1AP_INITIAL_CONTEXT_SETUP_REQ:
|
||||
ue_index = get_UE_index_from_s1ap_ids(instance, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id);
|
||||
|
||||
LOG_D(RRC, "Received %s: instance %d, ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d, ue_index %d\n", msg_name, instance,
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id,
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs, ue_index);
|
||||
|
||||
if (ue_index == UE_INDEX_INVALID)
|
||||
{
|
||||
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
|
||||
MessageDef *msg_fail_p;
|
||||
|
||||
LOG_W(RRC, "In S1AP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d) for eNB %d\n",
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id, instance);
|
||||
|
||||
msg_fail_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL);
|
||||
S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
// TODO add failure cause when defined!
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, instance, msg_fail_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].eNB_ue_s1ap_id =
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
|
||||
/* Save e RAB information for later */
|
||||
{
|
||||
int i;
|
||||
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs;
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].index_of_e_rabs = 0;
|
||||
for (i = 0; i < eNB_rrc_inst[instance].Info.UE[ue_index].nb_of_e_rabs; i++) {
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].e_rab[i].status = E_RAB_STATUS_NEW;
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].e_rab[i].param =
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t send_security_mode_command = TRUE;
|
||||
|
||||
// TODO evaluate if security mode command should be skipped
|
||||
|
||||
if (send_security_mode_command) {
|
||||
rrc_eNB_generate_SecurityModeCommand (instance, 0 /* TODO put frame number ! */, ue_index);
|
||||
}
|
||||
else {
|
||||
rrc_eNB_generate_UECapabilityEnquiry (instance, 0 /* TODO put frame number ! */, ue_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name, instance);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOG_E(RRC, "Received unexpected message %s\n", msg_name);
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Eurecom OpenAirInterface 2
|
||||
Copyright(c) 1999 - 2010 Eurecom
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information
|
||||
Openair Admin: openair_admin@eurecom.fr
|
||||
Openair Tech : openair_tech@eurecom.fr
|
||||
Forums : http://forums.eurecom.fsr/openairinterface
|
||||
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*! \file rrc_eNB_S1AP.c
|
||||
* \brief rrc S1AP procedures for eNB
|
||||
* \author Laurent Winckel
|
||||
* \date 2013
|
||||
* \version 1.0
|
||||
* \company Eurecom
|
||||
* \email: laurent.winckel@eurecom.fr and navid.nikaein@eurecom.fr
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_USE_MME)
|
||||
# include "defs.h"
|
||||
# include "extern.h"
|
||||
# include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
|
||||
# include "RRC/LITE/MESSAGES/asn1_msg.h"
|
||||
# include "rrc_eNB_S1AP.h"
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
# include "asn1_conversions.h"
|
||||
# include "intertask_interface.h"
|
||||
# include "pdcp.h"
|
||||
# include "s1ap_eNB.h"
|
||||
# else
|
||||
# include "../../S1AP/s1ap_eNB.h"
|
||||
# endif
|
||||
|
||||
/* Value to indicate an invalid UE initial id */
|
||||
static const uint16_t UE_INITIAL_ID_INVALID = 0;
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
/*! \fn uint16_t get_next_ue_initial_id(uint8_t mod_id)
|
||||
*\brief provide an UE initial ID for S1AP initial communication.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\return the UE initial ID.
|
||||
*/
|
||||
static uint16_t get_next_ue_initial_id(uint8_t mod_id) {
|
||||
static uint16_t ue_initial_id[NUMBER_OF_eNB_MAX];
|
||||
|
||||
ue_initial_id[mod_id]++;
|
||||
|
||||
/* Never use UE_INITIAL_ID_INVALID this is the invalid id! */
|
||||
if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) {
|
||||
ue_initial_id[mod_id]++;
|
||||
}
|
||||
|
||||
return ue_initial_id[mod_id];
|
||||
}
|
||||
|
||||
/*! \fn uint8_t get_UE_index_from_initial_id (uint8_t mod_id, uint16_t ue_initial_id)
|
||||
*\brief retrieve UE index in the eNB from the UE initial ID.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param ue_initial_id The UE initial ID sent to S1AP.
|
||||
*\return the UE index or UE_INDEX_INVALID if not found.
|
||||
*/
|
||||
static uint8_t get_UE_index_from_initial_id(uint8_t mod_id, uint16_t ue_initial_id) {
|
||||
uint8_t ue_index;
|
||||
static const uint8_t null_identity[5] =
|
||||
{0, 0, 0, 0, 0};
|
||||
|
||||
DevCheck(mod_id < NB_eNB_INST, mod_id, NB_eNB_INST, 0);
|
||||
|
||||
for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
|
||||
/* Check if this UE is in use */
|
||||
if (memcmp (eNB_rrc_inst[mod_id].Info.UE_list[ue_index], null_identity,
|
||||
sizeof(eNB_rrc_inst[0].Info.UE_list[ue_index])) != 0) {
|
||||
/* Check if the initial id match */
|
||||
if (eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id == ue_initial_id) {
|
||||
return ue_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UE_INDEX_INVALID;
|
||||
}
|
||||
|
||||
/*! \fn uint8_t get_UE_index_from_eNB_ue_s1ap_id(uint8_t mod_id, uint16_t eNB_ue_s1ap_id)
|
||||
*\brief retrieve UE index in the eNB from the eNB_ue_s1ap_id previously transmitted by S1AP.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param eNB_ue_s1ap_id The value sent by S1AP.
|
||||
*\return the UE index or UE_INDEX_INVALID if not found.
|
||||
*/
|
||||
static uint8_t get_UE_index_from_eNB_ue_s1ap_id(uint8_t mod_id, uint16_t eNB_ue_s1ap_id) {
|
||||
uint8_t ue_index;
|
||||
static const uint8_t null_identity[5] =
|
||||
{0, 0, 0, 0, 0};
|
||||
|
||||
DevCheck(mod_id < NB_eNB_INST, mod_id, NB_eNB_INST, 0);
|
||||
|
||||
for (ue_index = 0; ue_index < NUMBER_OF_UE_MAX; ue_index++) {
|
||||
/* Check if this UE is in use */
|
||||
if (memcmp (eNB_rrc_inst[mod_id].Info.UE_list[ue_index], null_identity,
|
||||
sizeof(eNB_rrc_inst[0].Info.UE_list[ue_index])) != 0) {
|
||||
/* Check if the initial id match */
|
||||
if (eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id == eNB_ue_s1ap_id) {
|
||||
return ue_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UE_INDEX_INVALID;
|
||||
}
|
||||
|
||||
/*! \fn uint8_t get_UE_index_from_s1ap_ids(uint8_t mod_id, uint16_t ue_initial_id, uint16_t eNB_ue_s1ap_id)
|
||||
*\brief retrieve UE index in the eNB from the UE initial ID if not equal to UE_INDEX_INVALID or
|
||||
*\brief from the eNB_ue_s1ap_id previously transmitted by S1AP.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param ue_initial_id The UE initial ID sent to S1AP.
|
||||
*\param eNB_ue_s1ap_id The value sent by S1AP.
|
||||
*\return the UE index or UE_INDEX_INVALID if not found.
|
||||
*/
|
||||
static uint8_t get_UE_index_from_s1ap_ids(uint8_t mod_id, uint16_t ue_initial_id, uint16_t eNB_ue_s1ap_id) {
|
||||
uint8_t ue_index;
|
||||
|
||||
if (ue_initial_id == UE_INITIAL_ID_INVALID) {
|
||||
/* If "ue_initial_id" is not set search if "eNB_ue_s1ap_id" is know by RRC */
|
||||
ue_index = get_UE_index_from_eNB_ue_s1ap_id (mod_id, eNB_ue_s1ap_id);
|
||||
}
|
||||
else {
|
||||
/* If "ue_initial_id" is set there is probably not yet an associated "eNB_ue_s1ap_id" with S1AP */
|
||||
ue_index = get_UE_index_from_initial_id (mod_id, ue_initial_id);
|
||||
}
|
||||
|
||||
return ue_index;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(uint8_t mod_id, uint8_t ue_index) {
|
||||
eNB_RRC_UE_INFO *UE_info = &eNB_rrc_inst[mod_id].Info.UE[ue_index];
|
||||
MessageDef *msg_p;
|
||||
int e_rab;
|
||||
int e_rabs_done = 0;
|
||||
int e_rabs_failed = 0;
|
||||
|
||||
msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_RESP);
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = UE_info->eNB_ue_s1ap_id;
|
||||
for (e_rab = 0; e_rab < UE_info->index_of_e_rabs; e_rab++) {
|
||||
if (UE_info->e_rab[e_rab].status == E_RAB_STATUS_DONE) {
|
||||
e_rabs_done++;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs[e_rab].e_rab_id = UE_info->e_rab[e_rab].param.e_rab_id;
|
||||
// TODO add other information from S1-U when it will be integrated
|
||||
}
|
||||
else {
|
||||
e_rabs_failed++;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).e_rabs_failed[e_rab].e_rab_id = UE_info->e_rab[e_rab].param.e_rab_id;
|
||||
// TODO add cause when it will be integrated
|
||||
}
|
||||
}
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs = e_rabs_done;
|
||||
S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_e_rabs_failed = e_rabs_failed;
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, mod_id, msg_p);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void rrc_eNB_send_S1AP_UPLINK_NAS(uint8_t mod_id, uint8_t ue_index, UL_DCCH_Message_t *ul_dcch_msg) {
|
||||
#if defined(ENABLE_ITTI)
|
||||
{
|
||||
ULInformationTransfer_t *ulInformationTransfer = &ul_dcch_msg->message.choice.c1.choice.ulInformationTransfer;
|
||||
|
||||
if ((ulInformationTransfer->criticalExtensions.present == ULInformationTransfer__criticalExtensions_PR_c1)
|
||||
&& (ulInformationTransfer->criticalExtensions.choice.c1.present
|
||||
== ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
|
||||
&& (ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType.present
|
||||
== ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)) {
|
||||
/* This message hold a dedicated info NAS payload, forward it to NAS */
|
||||
struct ULInformationTransfer_r8_IEs__dedicatedInfoType *dedicatedInfoType =
|
||||
&ulInformationTransfer->criticalExtensions.choice.c1.choice.ulInformationTransfer_r8.dedicatedInfoType;
|
||||
uint32_t pdu_length;
|
||||
uint8_t *pdu_buffer;
|
||||
MessageDef *msg_p;
|
||||
|
||||
pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size;
|
||||
pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf;
|
||||
|
||||
msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UPLINK_NAS);
|
||||
S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = eNB_rrc_inst[mod_id].Info.UE[ue_index].eNB_ue_s1ap_id;
|
||||
S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length;
|
||||
S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer;
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, mod_id, msg_p);
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
ULInformationTransfer_t *ulInformationTransfer;
|
||||
ulInformationTransfer =
|
||||
&ul_dcch_msg->message.choice.c1.choice.
|
||||
ulInformationTransfer;
|
||||
|
||||
if (ulInformationTransfer->criticalExtensions.present ==
|
||||
ULInformationTransfer__criticalExtensions_PR_c1)
|
||||
{
|
||||
if (ulInformationTransfer->criticalExtensions.choice.c1.present ==
|
||||
ULInformationTransfer__criticalExtensions__c1_PR_ulInformationTransfer_r8)
|
||||
{
|
||||
|
||||
ULInformationTransfer_r8_IEs_t
|
||||
*ulInformationTransferR8;
|
||||
ulInformationTransferR8 =
|
||||
&ulInformationTransfer->criticalExtensions.choice.
|
||||
c1.choice.ulInformationTransfer_r8;
|
||||
if (ulInformationTransferR8->dedicatedInfoType.
|
||||
present ==
|
||||
ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)
|
||||
s1ap_eNB_new_data_request (mod_id, ue_index,
|
||||
ulInformationTransferR8->
|
||||
dedicatedInfoType.choice.
|
||||
dedicatedInfoNAS.buf,
|
||||
ulInformationTransferR8->
|
||||
dedicatedInfoType.choice.
|
||||
dedicatedInfoNAS.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void rrc_eNB_send_S1AP_NAS_FIRST_REQ(uint8_t mod_id, uint8_t ue_index,
|
||||
RRCConnectionSetupComplete_r8_IEs_t *rrcConnectionSetupComplete) {
|
||||
#if defined(ENABLE_ITTI)
|
||||
{
|
||||
MessageDef *message_p;
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_FIRST_REQ);
|
||||
eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id = get_next_ue_initial_id (mod_id);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_initial_id = eNB_rrc_inst[mod_id].Info.UE[ue_index].ue_initial_id;
|
||||
|
||||
/* Assume that cause is coded in the same way in RRC and S1ap, just check that the value is in S1ap range */
|
||||
DevCheck(eNB_rrc_inst[mod_id].Info.UE[ue_index].establishment_cause < RRC_CAUSE_LAST,
|
||||
eNB_rrc_inst[mod_id].Info.UE[ue_index].establishment_cause, RRC_CAUSE_LAST, mod_id);
|
||||
S1AP_NAS_FIRST_REQ (message_p).establishment_cause = eNB_rrc_inst[mod_id].Info.UE[ue_index].establishment_cause;
|
||||
|
||||
/* Forward NAS message */S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer =
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.buf;
|
||||
S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size;
|
||||
|
||||
/* Fill UE identities with available information */
|
||||
{
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask = UE_IDENTITIES_NONE;
|
||||
|
||||
if (eNB_rrc_inst[mod_id].Info.UE[ue_index].Initialue_identity_s_TMSI.presence) {
|
||||
/* Fill s-TMSI */
|
||||
UE_S_TMSI *s_TMSI = &eNB_rrc_inst[mod_id].Info.UE[ue_index].Initialue_identity_s_TMSI;
|
||||
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_s_tmsi;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code = s_TMSI->mme_code;
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi = s_TMSI->m_tmsi;
|
||||
}
|
||||
|
||||
if (rrcConnectionSetupComplete->registeredMME != NULL) {
|
||||
/* Fill GUMMEI */
|
||||
struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
|
||||
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
|
||||
if (r_mme->plmn_Identity != NULL) {
|
||||
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
|
||||
/* Use first indicated PLMN MCC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
|
||||
}
|
||||
if (r_mme->plmn_Identity->mnc.list.count > 0) {
|
||||
/* Use first indicated PLMN MNC if it is defined */
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
|
||||
}
|
||||
}
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
|
||||
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
|
||||
}
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, mod_id, message_p);
|
||||
}
|
||||
#else
|
||||
{
|
||||
s1ap_eNB_new_data_request (mod_id, ue_index,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
buf,
|
||||
rrcConnectionSetupComplete->dedicatedInfoNAS.
|
||||
size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
/*------------------------------------------------------------------------------*/
|
||||
int rrc_eNB_process_S1AP_DOWNLINK_NAS(MessageDef *msg_p, const char *msg_name, instance_t instance, mui_t *rrc_eNB_mui) {
|
||||
uint8_t ue_index;
|
||||
uint32_t length;
|
||||
uint8_t *buffer;
|
||||
|
||||
ue_index = get_UE_index_from_s1ap_ids (instance, S1AP_DOWNLINK_NAS (msg_p).ue_initial_id,
|
||||
S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id);
|
||||
|
||||
LOG_D(RRC, "Received %s: instance %d, ue_initial_id %d, eNB_ue_s1ap_id %d, ue_index %d\n", msg_name, instance,
|
||||
S1AP_DOWNLINK_NAS (msg_p).ue_initial_id, S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id, ue_index);
|
||||
|
||||
if (ue_index == UE_INDEX_INVALID) {
|
||||
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
|
||||
MessageDef *msg_fail_p;
|
||||
|
||||
LOG_W(RRC, "In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d) for eNB %d\n", S1AP_DOWNLINK_NAS (msg_p).ue_initial_id,
|
||||
S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id, instance);
|
||||
|
||||
msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL); // TODO change message!
|
||||
S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
else {
|
||||
/* Create message for PDCP (DLInformationTransfer_t) */
|
||||
length = do_DLInformationTransfer (&buffer, rrc_eNB_get_next_transaction_identifier (instance),
|
||||
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
|
||||
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
|
||||
|
||||
/* Transfer data to PDCP */
|
||||
pdcp_rrc_data_req (instance, 0 /* TODO put frame number ! */, 1, (ue_index * NB_RB_MAX) + DCCH, *rrc_eNB_mui++, 0,
|
||||
length, buffer, 1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance) {
|
||||
uint8_t ue_index;
|
||||
|
||||
ue_index = get_UE_index_from_s1ap_ids (instance, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id,
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id);
|
||||
|
||||
LOG_D(RRC, "Received %s: instance %d, ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d, ue_index %d\n",
|
||||
msg_name, instance, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id,
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs, ue_index);
|
||||
|
||||
if (ue_index == UE_INDEX_INVALID) {
|
||||
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
|
||||
MessageDef *msg_fail_p;
|
||||
|
||||
LOG_W(RRC, "In S1AP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d) for eNB %d\n",
|
||||
S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id, instance);
|
||||
|
||||
msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL);
|
||||
S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
|
||||
// TODO add failure cause when defined!
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
else {
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
|
||||
|
||||
/* Save e RAB information for later */
|
||||
{
|
||||
int i;
|
||||
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].nb_of_e_rabs = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs;
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].index_of_e_rabs = 0;
|
||||
for (i = 0; i < eNB_rrc_inst[instance].Info.UE[ue_index].nb_of_e_rabs; i++) {
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].e_rab[i].status = E_RAB_STATUS_NEW;
|
||||
eNB_rrc_inst[instance].Info.UE[ue_index].e_rab[i].param = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).e_rab_param[i];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t send_security_mode_command = TRUE;
|
||||
|
||||
// TODO evaluate if security mode command should be skipped
|
||||
|
||||
if (send_security_mode_command) {
|
||||
rrc_eNB_generate_SecurityModeCommand (instance, 0 /* TODO put frame number ! */, ue_index);
|
||||
}
|
||||
else {
|
||||
rrc_eNB_generate_UECapabilityEnquiry (instance, 0 /* TODO put frame number ! */, ue_index);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
# endif /* defined(ENABLE_ITTI) */
|
||||
#endif /* defined(ENABLE_USE_MME) */
|
||||
@@ -0,0 +1,67 @@
|
||||
/*! \file rrc_eNB_S1AP.h
|
||||
* \brief rrc S1AP procedures for eNB
|
||||
* \author Laurent Winckel
|
||||
* \date 2013
|
||||
* \version 1.0
|
||||
* \company Eurecom
|
||||
* \email: laurent.winckel@eurecom.fr and navid.nikaein@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef RRC_ENB_S1AP_H_
|
||||
#define RRC_ENB_S1AP_H_
|
||||
|
||||
# if defined(ENABLE_USE_MME)
|
||||
|
||||
/* Up link procedures */
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
/*! \fn void rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(uint8_t mod_id, uint8_t ue_index)
|
||||
*\brief create a S1AP_INITIAL_CONTEXT_SETUP_RESP for S1AP.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param ue_index Instance ID of UE in the eNB.
|
||||
*/
|
||||
void rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(uint8_t Mod_id, uint8_t UE_index);
|
||||
# endif
|
||||
|
||||
/*! \fn void rrc_eNB_send_S1AP_UPLINK_NAS(uint8_t Mod_id, uint8_t UE_index, UL_DCCH_Message_t *ul_dcch_msg)
|
||||
*\brief create a S1AP_UPLINK_NAS to transfer a NAS message to S1AP.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param ue_index Instance ID of UE in the eNB.
|
||||
*\param ul_dcch_msg The message receive by RRC holding the NAS message.
|
||||
*/
|
||||
void rrc_eNB_send_S1AP_UPLINK_NAS(uint8_t Mod_id, uint8_t UE_index, UL_DCCH_Message_t *ul_dcch_msg);
|
||||
|
||||
/*! \fn rrc_eNB_send_S1AP_NAS_FIRST_REQ(uint8_t Mod_id, uint8_t UE_index, RRCConnectionSetupComplete_r8_IEs_t *rrcConnectionSetupComplete)
|
||||
*\brief create a S1AP_NAS_FIRST_REQ to indicate that RRC has completed its first connection setup to S1AP.
|
||||
*\brief eventually forward a NAS message to S1AP.
|
||||
*\param mod_id Instance ID of eNB.
|
||||
*\param ue_index Instance ID of UE in the eNB.
|
||||
*\param rrcConnectionSetupComplete The message receive by RRC that may hold the NAS message.
|
||||
*/
|
||||
void rrc_eNB_send_S1AP_NAS_FIRST_REQ(uint8_t Mod_id, uint8_t UE_index,
|
||||
RRCConnectionSetupComplete_r8_IEs_t *rrcConnectionSetupComplete);
|
||||
|
||||
/* Down link procedures */
|
||||
|
||||
# if defined(ENABLE_ITTI)
|
||||
/*! \fn rrc_eNB_process_S1AP_DOWNLINK_NAS(MessageDef *msg_p, const char *msg_name, instance_t instance, mui_t *rrc_eNB_mui)
|
||||
*\brief process a S1AP_DOWNLINK_NAS message received from S1AP and transfer the embedded NAS message to UE.
|
||||
*\param msg_p Message received by RRC.
|
||||
*\param msg_name Message name.
|
||||
*\param instance Message instance.
|
||||
*\param rrc_eNB_mui Counter for lower level message identification.
|
||||
*\return 0 when successful, -1 if the UE index can not be retrieved.
|
||||
*/
|
||||
int rrc_eNB_process_S1AP_DOWNLINK_NAS(MessageDef *msg_p, const char *msg_name, instance_t instance, mui_t *rrc_eNB_mui);
|
||||
|
||||
/*! \fn rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance)
|
||||
*\brief process a S1AP_INITIAL_CONTEXT_SETUP_REQ message received from S1AP.
|
||||
*\param msg_p Message received by RRC.
|
||||
*\param msg_name Message name.
|
||||
*\param instance Message instance.
|
||||
*\return 0 when successful, -1 if the UE index can not be retrieved.
|
||||
*/
|
||||
int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char *msg_name, instance_t instance);
|
||||
# endif
|
||||
# endif /* defined(ENABLE_USE_MME) */
|
||||
#endif /* RRC_ENB_S1AP_H_ */
|
||||
Reference in New Issue
Block a user