Commit 0ef04198 authored by winckel's avatar winckel

Added a mechanism to wait for eNB MME link to be establish for all eNB before starting L2L1 task.

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4577 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 8d2f5e89
......@@ -66,7 +66,7 @@ static int s1ap_eNB_generate_s1_setup_request(
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
static
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_eNB_t *s1ap_register_eNB);
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB);
static
void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
......@@ -126,47 +126,56 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
* but not yet associated.
*/
RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
instance_p->s1ap_mme_nb ++;
instance_p->s1ap_mme_pending_nb ++;
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
}
static
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_eNB_t *s1ap_register_eNB)
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB)
{
s1ap_eNB_instance_t *new_instance;
uint8_t index;
DevAssert(s1ap_register_eNB != NULL);
/* Look if the provided instance already exists
* If so notify user...
*/
/* Look if the provided instance already exists */
new_instance = s1ap_eNB_get_instance(instance);
DevAssert(new_instance == NULL);
new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->s1ap_ue_head);
RB_INIT(&new_instance->s1ap_mme_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc;
new_instance->default_drx = s1ap_register_eNB->default_drx;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
s1ap_eNB_insert_new_instance(new_instance);
S1AP_DEBUG("Registered new eNB[%d] and %s eNB id %u\n",
instance,
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
s1ap_register_eNB->eNB_id);
if (new_instance != NULL) {
/* Checks if it is a retry on the same eNB */
DevCheck(new_instance->eNB_id == s1ap_register_eNB->eNB_id, new_instance->eNB_id, s1ap_register_eNB->eNB_id, 0);
DevCheck(new_instance->cell_type == s1ap_register_eNB->cell_type, new_instance->cell_type, s1ap_register_eNB->cell_type, 0);
DevCheck(new_instance->tac == s1ap_register_eNB->tac, new_instance->tac, s1ap_register_eNB->tac, 0);
DevCheck(new_instance->mcc == s1ap_register_eNB->mcc, new_instance->mcc, s1ap_register_eNB->mcc, 0);
DevCheck(new_instance->mnc == s1ap_register_eNB->mnc, new_instance->mnc, s1ap_register_eNB->mnc, 0);
DevCheck(new_instance->default_drx == s1ap_register_eNB->default_drx, new_instance->default_drx, s1ap_register_eNB->default_drx, 0);
} else {
new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->s1ap_ue_head);
RB_INIT(&new_instance->s1ap_mme_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc;
new_instance->default_drx = s1ap_register_eNB->default_drx;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
s1ap_eNB_insert_new_instance(new_instance);
S1AP_DEBUG("Registered new eNB[%d] and %s eNB id %u\n",
instance,
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
s1ap_register_eNB->eNB_id);
}
DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0);
......@@ -198,6 +207,9 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
sctp_new_association_resp->sctp_state,
instance,
sctp_new_association_resp->ulp_cnx_id);
s1ap_handle_s1_setup_message(s1ap_mme_data_p);
return;
}
......@@ -238,14 +250,14 @@ void *s1ap_eNB_task(void *arg)
case TERMINATE_MESSAGE:
itti_exit_task();
break;
case S1AP_REGISTER_ENB: {
case S1AP_REGISTER_ENB_REQ: {
/* Register a new eNB.
* in Virtual mode eNBs will be distinguished using the mod_id/
* Each eNB has to send an S1AP_REGISTER_ENB message with its
* own parameters.
*/
s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.s1ap_register_eNB);
&S1AP_REGISTER_ENB_REQ(received_msg));
} break;
case SCTP_NEW_ASSOCIATION_RESP: {
s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
......@@ -318,6 +330,8 @@ static int s1ap_eNB_generate_s1_setup_request(
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
&s1SetupRequest_p->global_ENB_ID.pLMNidentity);
S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
INT16_TO_OCTET_STRING(instance_p->tac, &ta.tAC);
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, &plmnIdentity);
......
......@@ -172,6 +172,12 @@ typedef struct s1ap_eNB_instance_s {
*/
STAILQ_ENTRY(s1ap_eNB_instance_s) s1ap_eNB_entries;
/* Number of MME requested by eNB (tree size) */
uint32_t s1ap_mme_nb;
/* Number of MME for which association is pending */
uint32_t s1ap_mme_pending_nb;
/* Number of MME successfully associated to eNB */
uint32_t s1ap_mme_associated_nb;
/* Tree of S1AP MME associations ordered by association ID */
RB_HEAD(s1ap_mme_map, s1ap_eNB_mme_data_s) s1ap_mme_head;
......
......@@ -55,6 +55,7 @@
#include "s1ap_eNB_default_values.h"
#include "assertions.h"
#include "conversions.h"
static
......@@ -132,6 +133,24 @@ static const char *direction2String[] = {
"UnSuccessfull outcome", /* successfull outcome */
};
void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p) {
/* Check that at least one setup message is pending */
DevCheck(mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb > 0, mme_desc_p->s1ap_eNB_instance->instance,
mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb, 0);
/* Decrease pending messages number */
mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb --;
/* If there are no more pending messages, inform eNB app */
if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb == 0)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_REGISTER_ENB_CNF);
S1AP_REGISTER_ENB_CNF(message_p).nb_mme = mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb;
itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p);
}
}
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length)
{
......@@ -173,13 +192,25 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p)
{
s1ap_eNB_mme_data_t *mme_desc_p;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
"MME context\n", assoc_id);
return -1;
}
S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
mme_desc_p->state = S1AP_ENB_STATE_WAITING;
s1ap_handle_s1_setup_message(mme_desc_p);
return 0;
}
......@@ -278,6 +309,8 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
* Mark the association as UP to enable UE contexts creation.
*/
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++;
s1ap_handle_s1_setup_message(mme_desc_p);
#if 0
/* We call back our self
......
......@@ -31,6 +31,8 @@
#ifndef S1AP_ENB_HANDLERS_H_
#define S1AP_ENB_HANDLERS_H_
void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p);
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length);
......
......@@ -237,7 +237,7 @@ void sctp_handle_new_association_req(
close(sd);
return;
} else {
SCTP_DEBUG("connectx in progress...\n");
SCTP_DEBUG("connectx %d in progress...\n", assoc_id);
}
}
} else {
......@@ -270,6 +270,7 @@ void sctp_handle_new_association_req(
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_cnx->ppid = sctp_new_association_req_p->ppid;
sctp_cnx->instance = instance;
sctp_cnx->assoc_id = assoc_id;
/* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries);
......@@ -412,6 +413,7 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0);
close(sctp_cnx->sd);
STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries);
sctp_nb_cnx--;
free(sctp_cnx);
} else {
......
/* eNB application layer -> S1AP messages */
MESSAGE_DEF(S1AP_REGISTER_ENB , MESSAGE_PRIORITY_MED, s1ap_register_eNB_t , s1ap_register_eNB )
MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req)
/* S1AP -> eNB application layer messages */
MESSAGE_DEF(S1AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, s1ap_register_enb_cnf_t , s1ap_register_enb_cnf)
/* RRC -> S1AP messages */
MESSAGE_DEF(S1AP_NAS_FIRST_REQ , MESSAGE_PRIORITY_MED, s1ap_nas_first_req_t , s1ap_nas_first_req)
MESSAGE_DEF(S1AP_UPLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_uplink_nas_t , s1ap_uplink_nas )
MESSAGE_DEF(S1AP_UPLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_uplink_nas_t , s1ap_uplink_nas)
MESSAGE_DEF(S1AP_UE_CAPABILITIES_IND , MESSAGE_PRIORITY_MED, s1ap_ue_cap_info_ind_t , s1ap_ue_cap_info_ind)
MESSAGE_DEF(S1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, s1ap_initial_context_setup_resp_t, s1ap_initial_context_setup_resp)
MESSAGE_DEF(S1AP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, s1ap_initial_context_setup_fail_t, s1ap_initial_context_setup_fail)
......
......@@ -4,6 +4,10 @@
//-------------------------------------------------------------------------------------------//
// Defines to access message fields.
#define S1AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_register_enb_req
#define S1AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.s1ap_register_enb_cnf
#define S1AP_NAS_FIRST_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_nas_first_req
#define S1AP_UPLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_uplink_nas
#define S1AP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_cap_info_ind
......@@ -22,6 +26,24 @@
#define S1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_req
//-------------------------------------------------------------------------------------------//
/* Maximum number of e-rabs to be setup/deleted in a single message.
* Even if only one bearer will be modified by message.
*/
#define S1AP_MAX_E_RAB 11
/* Length of the transport layer address string
* 160 bits / 8 bits by char.
*/
#define S1AP_TRANSPORT_LAYER_ADDRESS_SIZE (160 / 8)
#define S1AP_MAX_NB_MME_IP_ADDRESS 10
#define S1AP_IMSI_LENGTH 16
/* Security key length used within eNB
* Even if only 16 bytes will be effectively used,
* the key length is 32 bytes (256 bits)
*/
#define SECURITY_KEY_LENGTH 32
typedef enum cell_type_e {
CELL_MACRO_ENB,
......@@ -63,7 +85,7 @@ typedef struct net_ip_address_s {
typedef uint64_t bitrate_t;
typedef struct {
typedef struct ambr_s {
bitrate_t br_ul;
bitrate_t br_dl;
} ambr_t;
......@@ -75,19 +97,19 @@ typedef enum priority_level_s {
PRIORITY_LEVEL_NO_PRIORITY = 15
} priority_level_t;
typedef enum {
typedef enum pre_emp_capability_e {
PRE_EMPTION_CAPABILITY_ENABLED = 0,
PRE_EMPTION_CAPABILITY_DISABLED = 1,
PRE_EMPTION_CAPABILITY_MAX,
} pre_emp_capability_t;
typedef enum {
typedef enum pre_emp_vulnerability_e {
PRE_EMPTION_VULNERABILITY_ENABLED = 0,
PRE_EMPTION_VULNERABILITY_DISABLED = 1,
PRE_EMPTION_VULNERABILITY_MAX,
} pre_emp_vulnerability_t;
typedef struct {
typedef struct allocation_retention_priority_s {
priority_level_t priority_level;
pre_emp_capability_t pre_emp_capability;
pre_emp_vulnerability_t pre_emp_vulnerability;
......@@ -98,25 +120,6 @@ typedef struct security_capabilities_s {
uint16_t integrity_algorithms;
} security_capabilities_t;
/* Maximum number of e-rabs to be setup/deleted in a single message.
* Even if only one bearer will be modified by message.
*/
#define S1AP_MAX_E_RAB 11
/* Length of the transport layer address string
* 160 bits / 8 bits by char.
*/
#define S1AP_TRANSPORT_LAYER_ADDRESS_SIZE (160 / 8)
#define S1AP_MAX_NB_MME_IP_ADDRESS 10
#define S1AP_IMSI_LENGTH 16
/* Security key length used within eNB
* Even if only 16 bytes will be effectively used,
* the key length is 32 bytes (256 bits)
*/
#define SECURITY_KEY_LENGTH 32
/* Provides the establishment cause for the RRC connection request as provided
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
......@@ -226,7 +229,20 @@ typedef struct e_rab_failed_s {
// cause_t cause;
} e_rab_failed_t;
typedef struct s1ap_register_eNB_s {
typedef enum s1ap_ue_ctxt_modification_present_s {
S1AP_UE_CONTEXT_MODIFICATION_SECURITY_KEY = (1 << 0),
S1AP_UE_CONTEXT_MODIFICATION_UE_AMBR = (1 << 1),
S1AP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP = (1 << 2),
} s1ap_ue_ctxt_modification_present_t;
typedef enum s1ap_paging_ind_present_s {
S1AP_PAGING_IND_PAGING_DRX = (1 << 0),
S1AP_PAGING_IND_PAGING_PRIORITY = (1 << 1),
} s1ap_paging_ind_present_t;
//-------------------------------------------------------------------------------------------//
// eNB application layer -> S1AP messages
typedef struct s1ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long.
......@@ -260,7 +276,18 @@ typedef struct s1ap_register_eNB_s {
uint8_t nb_mme;
/* List of MME to connect to */
net_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
} s1ap_register_eNB_t;
} s1ap_register_enb_req_t;
//-------------------------------------------------------------------------------------------//
// S1AP -> eNB application layer messages
typedef struct s1ap_register_enb_cnf_s {
/* Nb of MME connected */
uint8_t nb_mme;
} s1ap_register_enb_cnf_t;
//-------------------------------------------------------------------------------------------//
// RRC -> S1AP messages
/* The NAS First Req is the first message exchanged between RRC and S1AP
* for an UE.
......@@ -291,38 +318,10 @@ typedef struct s1ap_uplink_nas_s {
nas_pdu_t nas_pdu;
} s1ap_uplink_nas_t;
typedef struct s1ap_downlink_nas_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
/* Unique UE identifier within an eNB */
unsigned eNB_ue_s1ap_id:24;
/* NAS pdu */
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;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Security algorithms */
security_capabilities_t security_capabilities;
/* Security key */
uint8_t security_key[SECURITY_KEY_LENGTH];
/* 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_t e_rab_param[S1AP_MAX_E_RAB];
} s1ap_initial_context_setup_req_t;
typedef struct s1ap_ue_cap_info_ind_s {
unsigned eNB_ue_s1ap_id:24;
ue_radio_cap_t ue_radio_cap;
} s1ap_ue_cap_info_ind_t;
typedef struct s1ap_initial_context_setup_resp_s {
unsigned eNB_ue_s1ap_id:24;
......@@ -344,21 +343,11 @@ typedef struct s1ap_initial_context_setup_fail_s {
/* TODO add cause */
} s1ap_initial_context_setup_fail_t, s1ap_ue_ctxt_modification_fail_t;
typedef struct s1ap_ue_cap_info_ind_s {
unsigned eNB_ue_s1ap_id:24;
ue_radio_cap_t ue_radio_cap;
} s1ap_ue_cap_info_ind_t;
typedef struct s1ap_ue_release_req_s {
typedef struct s1ap_nas_non_delivery_ind_s {
unsigned eNB_ue_s1ap_id:24;
nas_pdu_t nas_pdu;
/* TODO: add cause */
} s1ap_ue_release_req_t, s1ap_ue_release_resp_t;
typedef enum s1ap_ue_ctxt_modification_present_s {
S1AP_UE_CONTEXT_MODIFICATION_SECURITY_KEY = (1 << 0),
S1AP_UE_CONTEXT_MODIFICATION_UE_AMBR = (1 << 1),
S1AP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP = (1 << 2),
} s1ap_ue_ctxt_modification_present_t;
} s1ap_nas_non_delivery_ind_t;
typedef struct s1ap_ue_ctxt_modification_req_s {
unsigned eNB_ue_s1ap_id:24;
......@@ -382,10 +371,40 @@ typedef struct s1ap_ue_ctxt_modification_resp_s {
unsigned eNB_ue_s1ap_id:24;
} s1ap_ue_ctxt_modification_resp_t;
typedef enum s1ap_paging_ind_present_s {
S1AP_PAGING_IND_PAGING_DRX = (1 << 0),
S1AP_PAGING_IND_PAGING_PRIORITY = (1 << 1),
} s1ap_paging_ind_present_t;
//-------------------------------------------------------------------------------------------//
// S1AP -> RRC messages
typedef struct s1ap_downlink_nas_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
/* Unique UE identifier within an eNB */
unsigned eNB_ue_s1ap_id:24;
/* NAS pdu */
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;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Security algorithms */
security_capabilities_t security_capabilities;
/* Security key */
uint8_t security_key[SECURITY_KEY_LENGTH];
/* 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_t e_rab_param[S1AP_MAX_E_RAB];
} s1ap_initial_context_setup_req_t;
typedef struct s1ap_paging_ind_s {
/* UE identity index value.
......@@ -405,10 +424,11 @@ typedef struct s1ap_paging_ind_s {
paging_priority_t paging_priority;
} s1ap_paging_ind_t;
typedef struct s1ap_nas_non_delivery_ind_s {
//-------------------------------------------------------------------------------------------//
// S1AP <-> RRC messages
typedef struct s1ap_ue_release_req_s {
unsigned eNB_ue_s1ap_id:24;
nas_pdu_t nas_pdu;
/* TODO: add cause */
} s1ap_nas_non_delivery_ind_t;
} s1ap_ue_release_req_t, s1ap_ue_release_resp_t;
#endif /* S1AP_MESSAGES_TYPES_H_ */
......@@ -69,6 +69,7 @@ char smbv_ip[16];
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OTG/otg_kpi.h"
#include "assertions.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
......@@ -372,9 +373,8 @@ static s32 UE_id = 0, eNB_id = 0;
static s32 RN_id=0;
#endif
int itti_create_task_successful(void){
#if defined(ENABLE_ITTI)
int itti_create_task_successful(void){
# if defined(ENABLE_USE_MME)
if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(EMU, "Create task failed");
......@@ -388,103 +388,180 @@ int itti_create_task_successful(void){
}
# endif
if (itti_create_task(TASK_ENB_APP, eNB_app_task, NULL) < 0) {
if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) {
LOG_E(EMU, "Create task failed");
LOG_D(EMU, "Initializing eNB APP task interface: FAILED\n");
LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n");
return -1;
}
if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) {
/* Last task to create, others task must be ready before its start */
if (itti_create_task(TASK_ENB_APP, eNB_app_task, NULL) < 0) {
LOG_E(EMU, "Create task failed");
LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n");
LOG_D(EMU, "Initializing eNB APP task interface: FAILED\n");
return -1;
}
#endif
return 1;
}
#endif
#if defined(ENABLE_ITTI)
/*
* later, the enb task will be moved from here
* later, the eNB task will be moved from here
*/
void *eNB_app_task(void *args_p) {
#if defined(ENABLE_ITTI)
MessageDef *message_p;
# if defined(ENABLE_USE_MME)
/* Trying to register each eNB */
#define ENB_REGISTER_RETRY_DELAY 10
uint32_t eNB_app_register()
{
MessageDef *msg_p;
uint32_t register_enb_pending = 0;
for (eNB_id = oai_emulation.info.first_enb_local;
(eNB_id < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.cli_start_enb[eNB_id] == 1);
eNB_id++) {
char *mme_address_v4;
if (EPC_MODE_ENABLED){
mme_address_v4 = EPC_MODE_MME_ADDRESS;
}else {
mme_address_v4 = "192.168.12.87";
}
char *mme_address_v6 = "2001:660:5502:12:30da:829a:2343:b6cf";
s1ap_register_eNB_t *s1ap_register_eNB;
uint32_t hash;
//note: there is an implicit relationship between the data struct and the message name
message_p = itti_alloc_new_message(TASK_ENB_APP, S1AP_REGISTER_ENB);
s1ap_register_eNB = &message_p->ittiMsg.s1ap_register_eNB;
hash = s1ap_generate_eNB_id();
/* Some default/random parameters */
s1ap_register_eNB->eNB_id = eNB_id + (hash & 0xFFFF8);
s1ap_register_eNB->cell_type = CELL_MACRO_ENB;
s1ap_register_eNB->tac = 0;
s1ap_register_eNB->mcc = 208;
s1ap_register_eNB->mnc = 34;
s1ap_register_eNB->default_drx = PAGING_DRX_256;
s1ap_register_eNB->nb_mme = 1;
s1ap_register_eNB->mme_ip_address[0].ipv4 = 1;
s1ap_register_eNB->mme_ip_address[0].ipv6 = 0;
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv4_address, mme_address_v4,
strlen(mme_address_v4));
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv6_address, mme_address_v6,
strlen(mme_address_v6));
itti_send_msg_to_task(TASK_S1AP, eNB_id, message_p);
(eNB_id < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.cli_start_enb[eNB_id] == 1);
eNB_id++) {
char *mme_address_v4;
if (EPC_MODE_ENABLED){
mme_address_v4 = EPC_MODE_MME_ADDRESS;
} else {
mme_address_v4 = "192.168.12.87";
}
char *mme_address_v6 = "2001:660:5502:12:30da:829a:2343:b6cf";
s1ap_register_enb_req_t *s1ap_register_eNB;
uint32_t hash;
//note: there is an implicit relationship between the data struct and the message name
msg_p = itti_alloc_new_message(TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
s1ap_register_eNB = &S1AP_REGISTER_ENB_REQ(msg_p);
hash = s1ap_generate_eNB_id();
/* Some default/random parameters */
s1ap_register_eNB->eNB_id = eNB_id + (hash & 0xFFFF8);
s1ap_register_eNB->cell_type = CELL_MACRO_ENB;
s1ap_register_eNB->tac = 0;
s1ap_register_eNB->mcc = 208;
s1ap_register_eNB->mnc = 34;
s1ap_register_eNB->default_drx = PAGING_DRX_256;
s1ap_register_eNB->nb_mme = 1;
s1ap_register_eNB->mme_ip_address[0].ipv4 = 1;
s1ap_register_eNB->mme_ip_address[0].ipv6 = 0;
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv4_address, mme_address_v4, strlen(mme_address_v4));
memcpy(s1ap_register_eNB->mme_ip_address[0].ipv6_address, mme_address_v6, strlen(mme_address_v6));
# if defined ENB_APP_ENB_REGISTER_2_MME
s1ap_register_eNB->nb_mme = 2;
s1ap_register_eNB->mme_ip_address[1].ipv4 = 1;
s1ap_register_eNB->mme_ip_address[1].ipv6 = 0;
mme_address_v4 = "192.168.12.88";
memcpy(s1ap_register_eNB->mme_ip_address[1].ipv4_address, mme_address_v4, strlen(mme_address_v4));
memcpy(s1ap_register_eNB->mme_ip_address[1].ipv6_address, mme_address_v6, strlen(mme_address_v6));
# endif
itti_send_msg_to_task(TASK_S1AP, eNB_id, msg_p);
register_enb_pending ++;
}
return register_enb_pending;
}
# endif
#endif
itti_mark_task_ready (TASK_ENB_APP); // at the end of init for the current task
void *eNB_app_task(void *args_p) {
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
static uint32_t register_enb_pending;
static uint32_t registered_enb;
static long enb_register_retry_timer_id;
# endif
MessageDef *msg_p;
const char *msg_name;
instance_t instance;
itti_mark_task_ready (TASK_ENB_APP);
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
register_enb_pending = eNB_app_register();
# else
msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
# endif
do {
// Checks if a message has been sent to L2L1 task
itti_receive_msg (TASK_ENB_APP, &message_p);
// Wait for a message
itti_receive_msg (TASK_ENB_APP, &msg_p);
if (message_p != NULL) {
switch (ITTI_MSG_ID(message_p)) {
msg_name = ITTI_MSG_NAME (msg_p);
instance = ITTI_MSG_INSTANCE (msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
itti_exit_task ();
break;
itti_exit_task ();
break;
case MESSAGE_TEST:
LOG_D(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
break;
/* case MME_REGISTERED:
LOG_D(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
itti_mark_task_ready (TASK_L2L1);
break;
*/
LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(msg_p));
break;
# if defined(ENABLE_USE_MME)
case S1AP_REGISTER_ENB_CNF:
LOG_I(EMU, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name, S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
DevAssert(register_enb_pending > 0);
register_enb_pending--;
/* Check if at least eNB is registered with one MME */
if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) {