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
This commit is contained in:
+42
-28
@@ -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);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
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 {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
/* 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,6 +318,61 @@ typedef struct s1ap_uplink_nas_s {
|
||||
nas_pdu_t nas_pdu;
|
||||
} s1ap_uplink_nas_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;
|
||||
|
||||
/* Number of e_rab setup-ed in the list */
|
||||
uint8_t nb_of_e_rabs;
|
||||
/* list of e_rab setup-ed by RRC layers */
|
||||
e_rab_setup_t e_rabs[S1AP_MAX_E_RAB];
|
||||
|
||||
/* Number of e_rab failed to be setup in list */
|
||||
uint8_t nb_of_e_rabs_failed;
|
||||
/* list of e_rabs that failed to be setup */
|
||||
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
|
||||
} s1ap_initial_context_setup_resp_t;
|
||||
|
||||
typedef struct s1ap_initial_context_setup_fail_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
|
||||
/* TODO add cause */
|
||||
} s1ap_initial_context_setup_fail_t, s1ap_ue_ctxt_modification_fail_t;
|
||||
|
||||
typedef struct s1ap_nas_non_delivery_ind_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
nas_pdu_t nas_pdu;
|
||||
/* TODO: add cause */
|
||||
} s1ap_nas_non_delivery_ind_t;
|
||||
|
||||
typedef struct s1ap_ue_ctxt_modification_req_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
|
||||
/* Bit-mask of possible present parameters */
|
||||
s1ap_ue_ctxt_modification_present_t present;
|
||||
|
||||
/* Following fields are optionnaly present */
|
||||
|
||||
/* Security key */
|
||||
uint8_t security_key[SECURITY_KEY_LENGTH];
|
||||
|
||||
/* UE aggregate maximum bitrate */
|
||||
ambr_t ue_ambr;
|
||||
|
||||
/* Security capabilities */
|
||||
security_capabilities_t security_capabilities;
|
||||
} s1ap_ue_ctxt_modification_req_t;
|
||||
|
||||
typedef struct s1ap_ue_ctxt_modification_resp_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
} s1ap_ue_ctxt_modification_resp_t;
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// S1AP -> RRC messages
|
||||
typedef struct s1ap_downlink_nas_s {
|
||||
/* UE id for initial connection to S1AP */
|
||||
uint16_t ue_initial_id;
|
||||
@@ -324,69 +406,6 @@ typedef struct s1ap_initial_context_setup_req_s {
|
||||
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
|
||||
} s1ap_initial_context_setup_req_t;
|
||||
|
||||
typedef struct s1ap_initial_context_setup_resp_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
|
||||
/* Number of e_rab setup-ed in the list */
|
||||
uint8_t nb_of_e_rabs;
|
||||
/* list of e_rab setup-ed by RRC layers */
|
||||
e_rab_setup_t e_rabs[S1AP_MAX_E_RAB];
|
||||
|
||||
/* Number of e_rab failed to be setup in list */
|
||||
uint8_t nb_of_e_rabs_failed;
|
||||
/* list of e_rabs that failed to be setup */
|
||||
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
|
||||
} s1ap_initial_context_setup_resp_t;
|
||||
|
||||
typedef struct s1ap_initial_context_setup_fail_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
|
||||
/* TODO add cause */
|
||||
} s1ap_initial_context_setup_fail_t, s1ap_ue_ctxt_modification_fail_t;
|
||||
|
||||
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 {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
/* 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;
|
||||
|
||||
typedef struct s1ap_ue_ctxt_modification_req_s {
|
||||
unsigned eNB_ue_s1ap_id:24;
|
||||
|
||||
/* Bit-mask of possible present parameters */
|
||||
s1ap_ue_ctxt_modification_present_t present;
|
||||
|
||||
/* Following fields are optionnaly present */
|
||||
|
||||
/* Security key */
|
||||
uint8_t security_key[SECURITY_KEY_LENGTH];
|
||||
|
||||
/* UE aggregate maximum bitrate */
|
||||
ambr_t ue_ambr;
|
||||
|
||||
/* Security capabilities */
|
||||
security_capabilities_t security_capabilities;
|
||||
} s1ap_ue_ctxt_modification_req_t;
|
||||
|
||||
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;
|
||||
|
||||
typedef struct s1ap_paging_ind_s {
|
||||
/* UE identity index value.
|
||||
* Specified in 3GPP TS 36.304
|
||||
@@ -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_ */
|
||||
|
||||
+159
-74
@@ -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) {
|
||||
LOG_E(EMU, "Create task failed");
|
||||
LOG_D(EMU, "Initializing eNB APP task interface: FAILED\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) {
|
||||
LOG_E(EMU, "Create task failed");
|
||||
LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* 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 eNB APP task interface: FAILED\n");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* later, the enb task will be moved from here
|
||||
*/
|
||||
void *eNB_app_task(void *args_p) {
|
||||
#if defined(ENABLE_ITTI)
|
||||
MessageDef *message_p;
|
||||
/*
|
||||
* later, the eNB task will be moved from here
|
||||
*/
|
||||
|
||||
# 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();
|
||||
(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;
|
||||
|
||||
/* 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);
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
itti_mark_task_ready (TASK_ENB_APP); // at the end of init for the current task
|
||||
|
||||
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;
|
||||
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) {
|
||||
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
|
||||
|
||||
/* case MME_REGISTERED:
|
||||
LOG_D(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
|
||||
itti_mark_task_ready (TASK_L2L1);
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
|
||||
break;
|
||||
}
|
||||
|
||||
free (message_p);
|
||||
LOG_E(EMU, "Received unexpected message %s\n", msg_name);
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
|
||||
itti_terminate_tasks(TASK_ENB_APP);
|
||||
free (msg_p);
|
||||
} while(1);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
@@ -503,10 +580,18 @@ void *l2l1_task(void *args_p) {
|
||||
char fname[64], vname[64];
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
MessageDef *message_p;
|
||||
MessageDef *message_p = NULL;
|
||||
|
||||
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
|
||||
|
||||
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 *
|
||||
|
||||
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
|
||||
int itti_create_task_successful(void);
|
||||
void *eNB_app_task(void *args_p);
|
||||
void *l2l1_task(void *args_p);
|
||||
#endif
|
||||
#ifdef OPENAIR2
|
||||
|
||||
Reference in New Issue
Block a user