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( ...@@ -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); s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
static 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 static
void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); 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, ...@@ -126,47 +126,56 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
* but not yet associated. * but not yet associated.
*/ */
RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); 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); itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
} }
static 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; s1ap_eNB_instance_t *new_instance;
uint8_t index; uint8_t index;
DevAssert(s1ap_register_eNB != NULL); DevAssert(s1ap_register_eNB != NULL);
/* Look if the provided instance already exists /* Look if the provided instance already exists */
* If so notify user...
*/
new_instance = s1ap_eNB_get_instance(instance); new_instance = s1ap_eNB_get_instance(instance);
DevAssert(new_instance == NULL); if (new_instance != NULL) {
/* Checks if it is a retry on the same eNB */
new_instance = calloc(1, sizeof(s1ap_eNB_instance_t)); DevCheck(new_instance->eNB_id == s1ap_register_eNB->eNB_id, new_instance->eNB_id, s1ap_register_eNB->eNB_id, 0);
DevAssert(new_instance != NULL); 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);
RB_INIT(&new_instance->s1ap_ue_head); DevCheck(new_instance->mcc == s1ap_register_eNB->mcc, new_instance->mcc, s1ap_register_eNB->mcc, 0);
RB_INIT(&new_instance->s1ap_mme_head); 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);
/* Copy usefull parameters */ } else {
new_instance->instance = instance; new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
new_instance->eNB_name = s1ap_register_eNB->eNB_name; DevAssert(new_instance != NULL);
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type; RB_INIT(&new_instance->s1ap_ue_head);
new_instance->tac = s1ap_register_eNB->tac; RB_INIT(&new_instance->s1ap_mme_head);
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc; /* Copy usefull parameters */
new_instance->default_drx = s1ap_register_eNB->default_drx; new_instance->instance = instance;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */ new_instance->eNB_id = s1ap_register_eNB->eNB_id;
s1ap_eNB_insert_new_instance(new_instance); new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
S1AP_DEBUG("Registered new eNB[%d] and %s eNB id %u\n", new_instance->mcc = s1ap_register_eNB->mcc;
instance, new_instance->mnc = s1ap_register_eNB->mnc;
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home", new_instance->default_drx = s1ap_register_eNB->default_drx;
s1ap_register_eNB->eNB_id);
/* 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, DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); 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 ...@@ -198,6 +207,9 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
sctp_new_association_resp->sctp_state, sctp_new_association_resp->sctp_state,
instance, instance,
sctp_new_association_resp->ulp_cnx_id); sctp_new_association_resp->ulp_cnx_id);
s1ap_handle_s1_setup_message(s1ap_mme_data_p);
return; return;
} }
...@@ -238,14 +250,14 @@ void *s1ap_eNB_task(void *arg) ...@@ -238,14 +250,14 @@ void *s1ap_eNB_task(void *arg)
case TERMINATE_MESSAGE: case TERMINATE_MESSAGE:
itti_exit_task(); itti_exit_task();
break; break;
case S1AP_REGISTER_ENB: { case S1AP_REGISTER_ENB_REQ: {
/* Register a new eNB. /* Register a new eNB.
* in Virtual mode eNBs will be distinguished using the mod_id/ * in Virtual mode eNBs will be distinguished using the mod_id/
* Each eNB has to send an S1AP_REGISTER_ENB message with its * Each eNB has to send an S1AP_REGISTER_ENB message with its
* own parameters. * own parameters.
*/ */
s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.s1ap_register_eNB); &S1AP_REGISTER_ENB_REQ(received_msg));
} break; } break;
case SCTP_NEW_ASSOCIATION_RESP: { case SCTP_NEW_ASSOCIATION_RESP: {
s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
...@@ -318,6 +330,8 @@ static int s1ap_eNB_generate_s1_setup_request( ...@@ -318,6 +330,8 @@ static int s1ap_eNB_generate_s1_setup_request(
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
&s1SetupRequest_p->global_ENB_ID.pLMNidentity); &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); INT16_TO_OCTET_STRING(instance_p->tac, &ta.tAC);
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, &plmnIdentity); MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, &plmnIdentity);
......
...@@ -172,6 +172,12 @@ typedef struct s1ap_eNB_instance_s { ...@@ -172,6 +172,12 @@ typedef struct s1ap_eNB_instance_s {
*/ */
STAILQ_ENTRY(s1ap_eNB_instance_s) s1ap_eNB_entries; 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 */ /* Tree of S1AP MME associations ordered by association ID */
RB_HEAD(s1ap_mme_map, s1ap_eNB_mme_data_s) s1ap_mme_head; RB_HEAD(s1ap_mme_map, s1ap_eNB_mme_data_s) s1ap_mme_head;
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include "s1ap_eNB_default_values.h" #include "s1ap_eNB_default_values.h"
#include "assertions.h"
#include "conversions.h" #include "conversions.h"
static static
...@@ -132,6 +133,24 @@ static const char *direction2String[] = { ...@@ -132,6 +133,24 @@ static const char *direction2String[] = {
"UnSuccessfull outcome", /* successfull outcome */ "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, int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length) 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, ...@@ -173,13 +192,25 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
struct s1ap_message_s *message_p) struct s1ap_message_s *message_p)
{ {
s1ap_eNB_mme_data_t *mme_desc_p;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */ /* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) { if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n", S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
assoc_id, stream); 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"); 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; return 0;
} }
...@@ -278,6 +309,8 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, ...@@ -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. * Mark the association as UP to enable UE contexts creation.
*/ */
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; 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 #if 0
/* We call back our self /* We call back our self
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef S1AP_ENB_HANDLERS_H_ #ifndef S1AP_ENB_HANDLERS_H_
#define 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, int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length); const uint8_t * const data, const uint32_t data_length);
......
...@@ -237,7 +237,7 @@ void sctp_handle_new_association_req( ...@@ -237,7 +237,7 @@ void sctp_handle_new_association_req(
close(sd); close(sd);
return; return;
} else { } else {
SCTP_DEBUG("connectx in progress...\n"); SCTP_DEBUG("connectx %d in progress...\n", assoc_id);
} }
} }
} else { } else {
...@@ -270,6 +270,7 @@ void sctp_handle_new_association_req( ...@@ -270,6 +270,7 @@ void sctp_handle_new_association_req(
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id; sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_cnx->ppid = sctp_new_association_req_p->ppid; sctp_cnx->ppid = sctp_new_association_req_p->ppid;
sctp_cnx->instance = instance; sctp_cnx->instance = instance;
sctp_cnx->assoc_id = assoc_id;
/* Insert new element at end of list */ /* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); 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) ...@@ -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); sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0);
close(sctp_cnx->sd); close(sctp_cnx->sd);
STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries);
sctp_nb_cnx--; sctp_nb_cnx--;
free(sctp_cnx); free(sctp_cnx);
} else { } else {
......
/* eNB application layer -> S1AP messages */ /* 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 */ /* RRC -> S1AP messages */
MESSAGE_DEF(S1AP_NAS_FIRST_REQ , MESSAGE_PRIORITY_MED, s1ap_nas_first_req_t , s1ap_nas_first_req) 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_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_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) 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 @@ ...@@ -4,6 +4,10 @@
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
// Defines to access message fields. // 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_NAS_FIRST_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_nas_first_req
#define S1AP_UPLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_uplink_nas #define S1AP_UPLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_uplink_nas
#define S1AP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_cap_info_ind #define S1AP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_cap_info_ind
...@@ -22,6 +26,24 @@ ...@@ -22,6 +26,24 @@
#define S1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_release_req #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 { typedef enum cell_type_e {
CELL_MACRO_ENB, CELL_MACRO_ENB,
...@@ -63,7 +85,7 @@ typedef struct net_ip_address_s { ...@@ -63,7 +85,7 @@ typedef struct net_ip_address_s {
typedef uint64_t bitrate_t; typedef uint64_t bitrate_t;
typedef struct { typedef struct ambr_s {
bitrate_t br_ul; bitrate_t br_ul;
bitrate_t br_dl; bitrate_t br_dl;
} ambr_t; } ambr_t;
...@@ -75,19 +97,19 @@ typedef enum priority_level_s { ...@@ -75,19 +97,19 @@ typedef enum priority_level_s {
PRIORITY_LEVEL_NO_PRIORITY = 15 PRIORITY_LEVEL_NO_PRIORITY = 15
} priority_level_t; } priority_level_t;
typedef enum { typedef enum pre_emp_capability_e {
PRE_EMPTION_CAPABILITY_ENABLED = 0, PRE_EMPTION_CAPABILITY_ENABLED = 0,
PRE_EMPTION_CAPABILITY_DISABLED = 1, PRE_EMPTION_CAPABILITY_DISABLED = 1,
PRE_EMPTION_CAPABILITY_MAX, PRE_EMPTION_CAPABILITY_MAX,
} pre_emp_capability_t; } pre_emp_capability_t;
typedef enum { typedef enum pre_emp_vulnerability_e {
PRE_EMPTION_VULNERABILITY_ENABLED = 0, PRE_EMPTION_VULNERABILITY_ENABLED = 0,
PRE_EMPTION_VULNERABILITY_DISABLED = 1, PRE_EMPTION_VULNERABILITY_DISABLED = 1,
PRE_EMPTION_VULNERABILITY_MAX, PRE_EMPTION_VULNERABILITY_MAX,
} pre_emp_vulnerability_t; } pre_emp_vulnerability_t;
typedef struct { typedef struct allocation_retention_priority_s {
priority_level_t priority_level; priority_level_t priority_level;
pre_emp_capability_t pre_emp_capability; pre_emp_capability_t pre_emp_capability;
pre_emp_vulnerability_t pre_emp_vulnerability; pre_emp_vulnerability_t pre_emp_vulnerability;
...@@ -98,25 +120,6 @@ typedef struct security_capabilities_s { ...@@ -98,25 +120,6 @@ typedef struct security_capabilities_s {
uint16_t integrity_algorithms; uint16_t integrity_algorithms;
} security_capabilities_t; } 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 /* Provides the establishment cause for the RRC connection request as provided
* by the upper layers. W.r.t. the cause value names: highPriorityAccess * by the upper layers. W.r.t. the cause value names: highPriorityAccess
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for * concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
...@@ -226,7 +229,20 @@ typedef struct e_rab_failed_s { ...@@ -226,7 +229,20 @@ typedef struct e_rab_failed_s {
// cause_t cause; // cause_t cause;
} e_rab_failed_t; } 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. /* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long. * For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long. * For home eNB ids this field should be 28 bits long.
...@@ -260,7 +276,18 @@ typedef struct s1ap_register_eNB_s { ...@@ -260,7 +276,18 @@ typedef struct s1ap_register_eNB_s {
uint8_t nb_mme; uint8_t nb_mme;
/* List of MME to connect to */ /* List of MME to connect to */
net_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS]; 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 /* The NAS First Req is the first message exchanged between RRC and S1AP
* for an UE. * for an UE.
...@@ -291,38 +318,10 @@ typedef struct s1ap_uplink_nas_s { ...@@ -291,38 +318,10 @@ typedef struct s1ap_uplink_nas_s {
nas_pdu_t nas_pdu; nas_pdu_t nas_pdu;
} s1ap_uplink_nas_t; } s1ap_uplink_nas_t;
typedef struct s1ap_downlink_nas_s { typedef struct s1ap_ue_cap_info_ind_s {
/* UE id for initial connection to S1AP */ unsigned eNB_ue_s1ap_id:24;
uint16_t ue_initial_id; ue_radio_cap_t ue_radio_cap;
} s1ap_ue_cap_info_ind_t;
/* 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_initial_context_setup_resp_s { typedef struct s1ap_initial_context_setup_resp_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -344,21 +343,11 @@ typedef struct s1ap_initial_context_setup_fail_s { ...@@ -344,21 +343,11 @@ typedef struct s1ap_initial_context_setup_fail_s {
/* TODO add cause */ /* 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;
typedef struct s1ap_ue_cap_info_ind_s { typedef struct s1ap_nas_non_delivery_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 {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
nas_pdu_t nas_pdu;
/* TODO: add cause */ /* TODO: add cause */
} s1ap_ue_release_req_t, s1ap_ue_release_resp_t; } s1ap_nas_non_delivery_ind_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;
typedef struct s1ap_ue_ctxt_modification_req_s { typedef struct s1ap_ue_ctxt_modification_req_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
...@@ -382,10 +371,40 @@ typedef struct s1ap_ue_ctxt_modification_resp_s { ...@@ -382,10 +371,40 @@ typedef struct s1ap_ue_ctxt_modification_resp_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
} s1ap_ue_ctxt_modification_resp_t; } s1ap_ue_ctxt_modification_resp_t;
typedef enum s1ap_paging_ind_present_s { //-------------------------------------------------------------------------------------------//
S1AP_PAGING_IND_PAGING_DRX = (1 << 0), // S1AP -> RRC messages
S1AP_PAGING_IND_PAGING_PRIORITY = (1 << 1), typedef struct s1ap_downlink_nas_s {
} s1ap_paging_ind_present_t; /* 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 { typedef struct s1ap_paging_ind_s {
/* UE identity index value. /* UE identity index value.
...@@ -405,10 +424,11 @@ typedef struct s1ap_paging_ind_s { ...@@ -405,10 +424,11 @@ typedef struct s1ap_paging_ind_s {
paging_priority_t paging_priority; paging_priority_t paging_priority;
} s1ap_paging_ind_t; } 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; unsigned eNB_ue_s1ap_id:24;
nas_pdu_t nas_pdu;
/* TODO: add cause */ /* TODO: add cause */
} s1ap_nas_non_delivery_ind_t; } s1ap_ue_release_req_t, s1ap_ue_release_resp_t;
#endif /* S1AP_MESSAGES_TYPES_H_ */ #endif /* S1AP_MESSAGES_TYPES_H_ */
...@@ -69,6 +69,7 @@ char smbv_ip[16]; ...@@ -69,6 +69,7 @@ char smbv_ip[16];
#include "UTIL/LOG/vcd_signal_dumper.h" #include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OTG/otg_kpi.h" #include "UTIL/OTG/otg_kpi.h"
#include "assertions.h"
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
# include "intertask_interface_init.h" # include "intertask_interface_init.h"
...@@ -372,9 +373,8 @@ static s32 UE_id = 0, eNB_id = 0; ...@@ -372,9 +373,8 @@ static s32 UE_id = 0, eNB_id = 0;
static s32 RN_id=0; static s32 RN_id=0;
#endif #endif
int itti_create_task_successful(void){
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
int itti_create_task_successful(void){
# if defined(ENABLE_USE_MME) # if defined(ENABLE_USE_MME)
if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) { if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(EMU, "Create task failed"); LOG_E(EMU, "Create task failed");
...@@ -388,103 +388,180 @@ int itti_create_task_successful(void){ ...@@ -388,103 +388,180 @@ int itti_create_task_successful(void){
} }
# endif # 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_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; 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_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; return -1;
} }
#endif
return 1; 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) # 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; 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 < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.cli_start_enb[eNB_id] == 1);
eNB_id++) { eNB_id++) {
char *mme_address_v4; char *mme_address_v4;
if (EPC_MODE_ENABLED){ if (EPC_MODE_ENABLED){
mme_address_v4 = EPC_MODE_MME_ADDRESS; mme_address_v4 = EPC_MODE_MME_ADDRESS;
}else { } else {
mme_address_v4 = "192.168.12.87"; 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);
} }
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
#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 { do {
// Checks if a message has been sent to L2L1 task // Wait for a message
itti_receive_msg (TASK_ENB_APP, &message_p); itti_receive_msg (TASK_ENB_APP, &msg_p);
if (message_p != NULL) { msg_name = ITTI_MSG_NAME (msg_p);
switch (ITTI_MSG_ID(message_p)) { instance = ITTI_MSG_INSTANCE (msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE: case TERMINATE_MESSAGE:
itti_exit_task (); itti_exit_task ();
break; break;
case MESSAGE_TEST: case MESSAGE_TEST:
LOG_D(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(msg_p));
break; break;
/* case MME_REGISTERED: # if defined(ENABLE_USE_MME)
LOG_D(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); case S1AP_REGISTER_ENB_CNF:
itti_mark_task_ready (TASK_L2L1); LOG_I(EMU, "[eNB %d] Received %s: associated MME %d\n", instance, msg_name, S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
break;
*/ 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) {
registered_enb ++;
}
/* Check if all register eNB requests have been processed */
if (register_enb_pending == 0) {
if (registered_enb == oai_emulation.info.nb_enb_local) {
/* If all eNB are registered, start L2L1 task */
MessageDef *msg_init_p;
msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
}
else {
uint32_t not_associated = oai_emulation.info.nb_enb_local - registered_enb;
LOG_W(EMU, " %d eNB %s not associated with a MME, retrying registration in %d seconds ...\n",
not_associated, not_associated > 1 ? "are" : "is", ENB_REGISTER_RETRY_DELAY);
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL, &enb_register_retry_timer_id) < 0) {
LOG_E(EMU, " Can not start eNB register retry timer!\n");
}
}
}
break;
case TIMER_HAS_EXPIRED:
LOG_I(EMU, " Received %s: timer_id %d\n", msg_name, TIMER_HAS_EXPIRED(msg_p).timer_id);
if (TIMER_HAS_EXPIRED(msg_p).timer_id == enb_register_retry_timer_id) {
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register();
}
break;
# endif
default: default:
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); LOG_E(EMU, "Received unexpected message %s\n", msg_name);
break; break;
}
free (message_p);
} }
} while(1);
itti_terminate_tasks(TASK_ENB_APP); free (msg_p);
} while(1);
#endif #endif
return NULL; return NULL;
...@@ -503,10 +580,18 @@ void *l2l1_task(void *args_p) { ...@@ -503,10 +580,18 @@ void *l2l1_task(void *args_p) {
char fname[64], vname[64]; char fname[64], vname[64];
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
MessageDef *message_p; MessageDef *message_p = NULL;
itti_mark_task_ready (TASK_L2L1); itti_mark_task_ready (TASK_L2L1);
/* Wait for the initialize message */
do {
if (message_p != NULL) {
free (message_p);
}
itti_receive_msg (TASK_L2L1, &message_p);
} while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
free (message_p);
#endif #endif
for (frame = 0; frame < oai_emulation.info.n_frames; frame++) { for (frame = 0; frame < oai_emulation.info.n_frames; frame++) {
......
...@@ -42,9 +42,9 @@ void calc_path_loss(node_desc_t* node_tx, node_desc_t* node_rx, channel_desc_t * ...@@ -42,9 +42,9 @@ void calc_path_loss(node_desc_t* node_tx, node_desc_t* node_rx, channel_desc_t *
void do_OFDM_mod(mod_sym_t **txdataF, s32 **txdata, uint32_t frame, u16 next_slot, LTE_DL_FRAME_PARMS *frame_parms); void do_OFDM_mod(mod_sym_t **txdataF, s32 **txdata, uint32_t frame, u16 next_slot, LTE_DL_FRAME_PARMS *frame_parms);
void *eNB_app_task(void *args_p);
#ifdef ENABLE_ITTI #ifdef ENABLE_ITTI
int itti_create_task_successful(void); int itti_create_task_successful(void);
void *eNB_app_task(void *args_p);
void *l2l1_task(void *args_p); void *l2l1_task(void *args_p);
#endif #endif
#ifdef OPENAIR2 #ifdef OPENAIR2
......
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