Added a HSS connection test in MME before accepting eNB association request.
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4919 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -218,7 +218,12 @@ 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;
|
||||
S1ap_S1SetupFailureIEs_t *s1_setup_failure_p;
|
||||
s1ap_eNB_mme_data_t *mme_desc_p;
|
||||
|
||||
DevAssert(message_p != NULL);
|
||||
|
||||
s1_setup_failure_p = &message_p->msg.s1ap_S1SetupFailureIEs;
|
||||
|
||||
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
|
||||
if (stream != 0) {
|
||||
@@ -232,7 +237,12 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
||||
return -1;
|
||||
}
|
||||
|
||||
S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
|
||||
if ((s1_setup_failure_p->cause.present == S1ap_Cause_PR_misc) &&
|
||||
(s1_setup_failure_p->cause.choice.misc == S1ap_CauseMisc_unspecified)) {
|
||||
S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n");
|
||||
} else {
|
||||
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, 0);
|
||||
|
||||
@@ -62,9 +62,12 @@
|
||||
#if !defined(MME_CLIENT_TEST)
|
||||
// static pthread_t s1ap_task_thread;
|
||||
|
||||
uint32_t nb_eNB_associated = 0;
|
||||
STAILQ_HEAD(eNB_list_s, eNB_description_s) eNB_list_head;
|
||||
static int indent = 0;
|
||||
int hss_associated = 0;
|
||||
uint32_t nb_eNB_associated = 0;
|
||||
STAILQ_HEAD(eNB_list_s, eNB_description_s)
|
||||
eNB_list_head;
|
||||
|
||||
static int indent = 0;
|
||||
|
||||
void *s1ap_mme_thread(void *args);
|
||||
|
||||
@@ -103,6 +106,10 @@ void *s1ap_mme_thread(void *args)
|
||||
|
||||
switch (ITTI_MSG_ID(received_message_p))
|
||||
{
|
||||
case ACTIVATE_MESSAGE: {
|
||||
hss_associated = 1;
|
||||
} break;
|
||||
|
||||
case SCTP_DATA_IND: {
|
||||
/* New message received from SCTP layer.
|
||||
* Decode and handle it.
|
||||
|
||||
@@ -111,8 +111,9 @@ typedef struct eNB_description_s {
|
||||
/*@}*/
|
||||
} eNB_description_t;
|
||||
|
||||
extern uint32_t nb_eNB_associated;
|
||||
extern mme_config_t *global_mme_config_p;
|
||||
extern int hss_associated;
|
||||
extern uint32_t nb_eNB_associated;
|
||||
extern mme_config_t *global_mme_config_p;
|
||||
|
||||
/** \brief S1AP layer top init
|
||||
* @returns -1 in case of failure
|
||||
|
||||
+115
-108
@@ -217,124 +217,131 @@ int s1ap_mme_generate_s1_setup_failure(
|
||||
int s1ap_mme_handle_s1_setup_request(uint32_t assoc_id, uint32_t stream,
|
||||
struct s1ap_message_s *message)
|
||||
{
|
||||
S1ap_S1SetupRequestIEs_t *s1SetupRequest_p;
|
||||
eNB_description_t *eNB_association;
|
||||
uint32_t eNB_id = 0;
|
||||
char *eNB_name = NULL;
|
||||
int ta_ret;
|
||||
uint16_t max_enb_connected;
|
||||
|
||||
DevAssert(message != NULL);
|
||||
|
||||
s1SetupRequest_p = &message->msg.s1ap_S1SetupRequestIEs;
|
||||
|
||||
/* We received a new valid S1 Setup Request on a stream != 0.
|
||||
* This should not happen -> reject eNB s1 setup request.
|
||||
*/
|
||||
if (stream != 0) {
|
||||
S1AP_DEBUG("Received new s1 setup request on stream != 0\n");
|
||||
/* Send a s1 setup failure with protocol cause unspecified */
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_protocol,
|
||||
S1ap_CauseProtocol_unspecified, -1);
|
||||
}
|
||||
|
||||
S1AP_DEBUG("New s1 setup request incoming from ");
|
||||
if (s1SetupRequest_p->presenceMask & S1AP_S1SETUPREQUESTIES_ENBNAME_PRESENT)
|
||||
if (hss_associated)
|
||||
{
|
||||
S1AP_DEBUG("%*s ", s1SetupRequest_p->eNBname.size, s1SetupRequest_p->eNBname.buf);
|
||||
eNB_name = (char *)s1SetupRequest_p->eNBname.buf;
|
||||
}
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.present == S1ap_ENB_ID_PR_homeENB_ID) {
|
||||
// Home eNB ID = 28 bits
|
||||
uint8_t *eNB_id_buf =
|
||||
s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.homeENB_ID.buf;
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.size != 28) {
|
||||
//TODO: handle case were size != 28 -> notify ? reject ?
|
||||
S1ap_S1SetupRequestIEs_t *s1SetupRequest_p;
|
||||
eNB_description_t *eNB_association;
|
||||
uint32_t eNB_id = 0;
|
||||
char *eNB_name = NULL;
|
||||
int ta_ret;
|
||||
uint16_t max_enb_connected;
|
||||
|
||||
DevAssert(message != NULL);
|
||||
|
||||
s1SetupRequest_p = &message->msg.s1ap_S1SetupRequestIEs;
|
||||
|
||||
/* We received a new valid S1 Setup Request on a stream != 0.
|
||||
* This should not happen -> reject eNB s1 setup request.
|
||||
*/
|
||||
if (stream != 0) {
|
||||
S1AP_DEBUG("Received new s1 setup request on stream != 0\n");
|
||||
/* Send a s1 setup failure with protocol cause unspecified */
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_protocol,
|
||||
S1ap_CauseProtocol_unspecified, -1);
|
||||
}
|
||||
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) +
|
||||
(eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
|
||||
S1AP_DEBUG("home eNB id: %07x\n", eNB_id);
|
||||
} else {
|
||||
// Macro eNB = 20 bits
|
||||
uint8_t *eNB_id_buf =
|
||||
s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf;
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.size != 20) {
|
||||
//TODO: handle case were size != 20 -> notify ? reject ?
|
||||
|
||||
S1AP_DEBUG("New s1 setup request incoming from ");
|
||||
if (s1SetupRequest_p->presenceMask & S1AP_S1SETUPREQUESTIES_ENBNAME_PRESENT)
|
||||
{
|
||||
S1AP_DEBUG("%*s ", s1SetupRequest_p->eNBname.size, s1SetupRequest_p->eNBname.buf);
|
||||
eNB_name = (char *)s1SetupRequest_p->eNBname.buf;
|
||||
}
|
||||
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((
|
||||
eNB_id_buf[2] & 0xf0) >> 4);
|
||||
S1AP_DEBUG("macro eNB id: %05x\n", eNB_id);
|
||||
}
|
||||
|
||||
config_read_lock(&mme_config);
|
||||
max_enb_connected = mme_config.max_eNBs;
|
||||
config_unlock(&mme_config);
|
||||
|
||||
if (nb_eNB_associated == max_enb_connected) {
|
||||
S1AP_DEBUG("There is too much eNB connected to MME, rejecting the association\n");
|
||||
S1AP_DEBUG("Connected = %d, maximum allowed = %d\n", nb_eNB_associated,
|
||||
max_enb_connected);
|
||||
|
||||
/* Send an overload cause... */
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
|
||||
S1ap_CauseMisc_control_processing_overload,
|
||||
S1ap_TimeToWait_v20s);
|
||||
}
|
||||
|
||||
/* If none of the provided PLMNs/TAC match the one configured in MME,
|
||||
* the s1 setup should be rejected with a cause set to Unknown PLMN.
|
||||
*/
|
||||
ta_ret = s1ap_mme_compare_ta_lists(&s1SetupRequest_p->supportedTAs);
|
||||
|
||||
/* eNB and MME have no common PLMN */
|
||||
if (ta_ret != TA_LIST_RET_OK) {
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
|
||||
S1ap_CauseMisc_unknown_PLMN,
|
||||
S1ap_TimeToWait_v20s);
|
||||
}
|
||||
|
||||
S1AP_DEBUG("Adding eNB to the list of served eNBs\n");
|
||||
|
||||
if ((eNB_association = s1ap_is_eNB_id_in_list(eNB_id)) == NULL) {
|
||||
/* eNB has not been fount in list of associated eNB,
|
||||
* Add it to the tail of list and initialize data */
|
||||
if ((eNB_association = s1ap_is_eNB_assoc_id_in_list(assoc_id)) == NULL) {
|
||||
/* ?? */
|
||||
return -1;
|
||||
} else {
|
||||
eNB_association->s1_state = S1AP_RESETING;
|
||||
eNB_association->eNB_id = eNB_id;
|
||||
eNB_association->default_paging_drx = s1SetupRequest_p->defaultPagingDRX;
|
||||
|
||||
if (eNB_name != NULL) {
|
||||
memcpy(eNB_association->eNB_name, s1SetupRequest_p->eNBname.buf,
|
||||
s1SetupRequest_p->eNBname.size);
|
||||
eNB_association->eNB_name[s1SetupRequest_p->eNBname.size] = '\0';
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.present == S1ap_ENB_ID_PR_homeENB_ID) {
|
||||
// Home eNB ID = 28 bits
|
||||
uint8_t *eNB_id_buf =
|
||||
s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.homeENB_ID.buf;
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.size != 28) {
|
||||
//TODO: handle case were size != 28 -> notify ? reject ?
|
||||
}
|
||||
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) +
|
||||
(eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
|
||||
S1AP_DEBUG("home eNB id: %07x\n", eNB_id);
|
||||
} else {
|
||||
// Macro eNB = 20 bits
|
||||
uint8_t *eNB_id_buf =
|
||||
s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf;
|
||||
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.size != 20) {
|
||||
//TODO: handle case were size != 20 -> notify ? reject ?
|
||||
}
|
||||
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((
|
||||
eNB_id_buf[2] & 0xf0) >> 4);
|
||||
S1AP_DEBUG("macro eNB id: %05x\n", eNB_id);
|
||||
}
|
||||
} else {
|
||||
eNB_association->s1_state = S1AP_RESETING;
|
||||
/* eNB has been fount in list, consider the s1 setup request as a reset connection,
|
||||
* reseting any previous UE state if sctp association is != than the previous one */
|
||||
if (eNB_association->sctp_assoc_id != assoc_id) {
|
||||
S1ap_S1SetupFailureIEs_t s1SetupFailure;
|
||||
|
||||
memset(&s1SetupFailure, 0, sizeof(s1SetupFailure));
|
||||
config_read_lock(&mme_config);
|
||||
max_enb_connected = mme_config.max_eNBs;
|
||||
config_unlock(&mme_config);
|
||||
|
||||
if (nb_eNB_associated == max_enb_connected) {
|
||||
S1AP_DEBUG("There is too much eNB connected to MME, rejecting the association\n");
|
||||
S1AP_DEBUG("Connected = %d, maximum allowed = %d\n", nb_eNB_associated,
|
||||
max_enb_connected);
|
||||
|
||||
/* Send an overload cause... */
|
||||
s1SetupFailure.cause.present = S1ap_Cause_PR_misc; //TODO: send the right cause
|
||||
s1SetupFailure.cause.choice.misc = S1ap_CauseMisc_control_processing_overload;
|
||||
S1AP_DEBUG("Rejeting s1 setup request as eNB id %d is already associated to an active sctp association"
|
||||
"Previous known: %d, new one: %d\n",
|
||||
eNB_id, eNB_association->sctp_assoc_id, assoc_id);
|
||||
// s1ap_mme_encode_s1setupfailure(&s1SetupFailure,
|
||||
// receivedMessage->msg.s1ap_sctp_new_msg_ind.assocId);
|
||||
return -1;
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
|
||||
S1ap_CauseMisc_control_processing_overload,
|
||||
S1ap_TimeToWait_v20s);
|
||||
}
|
||||
/* TODO: call the reset procedure */
|
||||
|
||||
/* If none of the provided PLMNs/TAC match the one configured in MME,
|
||||
* the s1 setup should be rejected with a cause set to Unknown PLMN.
|
||||
*/
|
||||
ta_ret = s1ap_mme_compare_ta_lists(&s1SetupRequest_p->supportedTAs);
|
||||
|
||||
/* eNB and MME have no common PLMN */
|
||||
if (ta_ret != TA_LIST_RET_OK) {
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
|
||||
S1ap_CauseMisc_unknown_PLMN,
|
||||
S1ap_TimeToWait_v20s);
|
||||
}
|
||||
|
||||
S1AP_DEBUG("Adding eNB to the list of served eNBs\n");
|
||||
|
||||
if ((eNB_association = s1ap_is_eNB_id_in_list(eNB_id)) == NULL) {
|
||||
/* eNB has not been fount in list of associated eNB,
|
||||
* Add it to the tail of list and initialize data */
|
||||
if ((eNB_association = s1ap_is_eNB_assoc_id_in_list(assoc_id)) == NULL) {
|
||||
/* ?? */
|
||||
return -1;
|
||||
} else {
|
||||
eNB_association->s1_state = S1AP_RESETING;
|
||||
eNB_association->eNB_id = eNB_id;
|
||||
eNB_association->default_paging_drx = s1SetupRequest_p->defaultPagingDRX;
|
||||
|
||||
if (eNB_name != NULL) {
|
||||
memcpy(eNB_association->eNB_name, s1SetupRequest_p->eNBname.buf,
|
||||
s1SetupRequest_p->eNBname.size);
|
||||
eNB_association->eNB_name[s1SetupRequest_p->eNBname.size] = '\0';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eNB_association->s1_state = S1AP_RESETING;
|
||||
/* eNB has been fount in list, consider the s1 setup request as a reset connection,
|
||||
* reseting any previous UE state if sctp association is != than the previous one */
|
||||
if (eNB_association->sctp_assoc_id != assoc_id) {
|
||||
S1ap_S1SetupFailureIEs_t s1SetupFailure;
|
||||
|
||||
memset(&s1SetupFailure, 0, sizeof(s1SetupFailure));
|
||||
|
||||
/* Send an overload cause... */
|
||||
s1SetupFailure.cause.present = S1ap_Cause_PR_misc; //TODO: send the right cause
|
||||
s1SetupFailure.cause.choice.misc = S1ap_CauseMisc_control_processing_overload;
|
||||
S1AP_DEBUG("Rejeting s1 setup request as eNB id %d is already associated to an active sctp association"
|
||||
"Previous known: %d, new one: %d\n",
|
||||
eNB_id, eNB_association->sctp_assoc_id, assoc_id);
|
||||
// s1ap_mme_encode_s1setupfailure(&s1SetupFailure,
|
||||
// receivedMessage->msg.s1ap_sctp_new_msg_ind.assocId);
|
||||
return -1;
|
||||
}
|
||||
/* TODO: call the reset procedure */
|
||||
}
|
||||
s1ap_dump_eNB(eNB_association);
|
||||
return s1ap_generate_s1_setup_response(eNB_association);
|
||||
} else {
|
||||
/* Can not process the request, MME is not connected to HSS */
|
||||
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
|
||||
S1ap_CauseMisc_unspecified, -1);
|
||||
}
|
||||
s1ap_dump_eNB(eNB_association);
|
||||
return s1ap_generate_s1_setup_response(eNB_association);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -50,8 +50,15 @@ void s6a_peer_connected_cb(struct peer_info *info, void *arg)
|
||||
if (info == NULL) {
|
||||
S6A_ERROR("Failed to connect to HSS entity\n");
|
||||
} else {
|
||||
MessageDef *message_p;
|
||||
|
||||
S6A_DEBUG("Peer %*s is now connected...\n",
|
||||
(int)info->pi_diamidlen, info->pi_diamid);
|
||||
|
||||
/* Inform S1AP that connection to HSS is established */
|
||||
message_p = itti_alloc_new_message(TASK_S6A, ACTIVATE_MESSAGE);
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
/* For test */
|
||||
|
||||
Reference in New Issue
Block a user