From 7a31d752feb3f6924f3f1b6480584c2dd17d31cf Mon Sep 17 00:00:00 2001 From: Cedric Roux <cedric.roux@eurecom.fr> Date: Fri, 8 Nov 2013 08:43:58 +0000 Subject: [PATCH] - Fix an issue when removing UE contexts in S1AP layer after eNB disconnection git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4348 818b1a75-f10b-46b9-bf7c-635c3b92a50f --- openair-cn/S1AP/s1ap_mme.c | 223 +++++++++------------- openair-cn/S1AP/s1ap_mme.h | 9 +- openair-cn/S1AP/s1ap_mme_nas_procedures.c | 10 +- 3 files changed, 101 insertions(+), 141 deletions(-) diff --git a/openair-cn/S1AP/s1ap_mme.c b/openair-cn/S1AP/s1ap_mme.c index c8ed707dd3..39d5b8095c 100644 --- a/openair-cn/S1AP/s1ap_mme.c +++ b/openair-cn/S1AP/s1ap_mme.c @@ -38,6 +38,10 @@ #if !defined(MME_CLIENT_TEST) # include "intertask_interface.h" #endif + +#include "assertions.h" +#include "queue.h" + #include "s1ap_mme.h" #include "s1ap_mme_decoder.h" #include "s1ap_mme_handlers.h" @@ -59,8 +63,7 @@ // static pthread_t s1ap_task_thread; uint32_t nb_eNB_associated = 0; -eNB_description_t *eNB_list_head = NULL; -eNB_description_t *eNB_list_tail = NULL; +STAILQ_HEAD(eNB_list_s, eNB_description_s) eNB_list_head; static int indent = 0; void *s1ap_mme_thread(void *args); @@ -89,6 +92,7 @@ void *s1ap_mme_thread(void *args) MessageDef *received_message_p; itti_mark_task_ready(TASK_S1AP); + while(1) { /* Trying to fetch a message from the message queue. * If the queue is empty, this function will block till a @@ -170,6 +174,8 @@ int s1ap_mme_init(const mme_config_t *mme_config_p) { # endif #endif + STAILQ_INIT(&eNB_list_head); + if (itti_create_task(TASK_S1AP, &s1ap_mme_thread, NULL) < 0) { S1AP_ERROR("Error while creating S1AP task\n"); return -1; @@ -183,11 +189,11 @@ int s1ap_mme_init(const mme_config_t *mme_config_p) { } void s1ap_dump_eNB_list(void) { - eNB_description_t *eNB_ref = eNB_list_head; + eNB_description_t *eNB_ref; - while (eNB_ref != NULL) { + STAILQ_FOREACH(eNB_ref, &eNB_list_head, eNB_entries) + { s1ap_dump_eNB(eNB_ref); - eNB_ref = eNB_ref->next_eNB; } } @@ -196,7 +202,11 @@ void s1ap_dump_eNB(eNB_description_t *eNB_ref) { ue_description_t *ue_ref; //Reset indentation indent = 0; - if (eNB_ref == NULL) return; + + if (eNB_ref == NULL) { + return; + } + eNB_LIST_OUT(""); eNB_LIST_OUT("eNB name: %s", eNB_ref->eNB_name == NULL ? "not present" : eNB_ref->eNB_name); eNB_LIST_OUT("eNB ID: %07x", eNB_ref->eNB_id); @@ -206,13 +216,14 @@ void s1ap_dump_eNB(eNB_description_t *eNB_ref) { eNB_LIST_OUT("UE attache to eNB: %d", eNB_ref->nb_ue_associated); indent++; - for (ue_ref = eNB_ref->ue_list_head; ue_ref; ue_ref = ue_ref->next_ue) { + + STAILQ_FOREACH(ue_ref, &eNB_ref->ue_list_head, ue_entries) + { s1ap_dump_ue(ue_ref); } indent--; eNB_LIST_OUT(""); #else - eNB_ref = eNB_ref; s1ap_dump_ue(NULL); #endif } @@ -233,12 +244,14 @@ eNB_description_t* s1ap_is_eNB_id_in_list(uint32_t eNB_id) { eNB_description_t *eNB_ref; - for (eNB_ref = eNB_list_head; eNB_ref; eNB_ref = eNB_ref->next_eNB) { - if (eNB_ref->eNB_id == eNB_id) - // We fount a matching reference, return it - break; + STAILQ_FOREACH(eNB_ref, &eNB_list_head, eNB_entries) + { + if (eNB_ref->eNB_id == eNB_id) { + /* We fount a matching reference, return it */ + return eNB_ref; + } } - // No matching eNB, return NULL + /* No matching eNB, return NULL */ return eNB_ref; } @@ -246,43 +259,49 @@ eNB_description_t* s1ap_is_eNB_assoc_id_in_list(uint32_t sctp_assoc_id) { eNB_description_t *eNB_ref; - for (eNB_ref = eNB_list_head; eNB_ref; eNB_ref = eNB_ref->next_eNB) { - if (eNB_ref->sctp_assoc_id == sctp_assoc_id) - // We fount a matching reference, return it - break; + STAILQ_FOREACH(eNB_ref, &eNB_list_head, eNB_entries) + { + if (eNB_ref->sctp_assoc_id == sctp_assoc_id) { + /* We fount a matching reference, return it */ + return eNB_ref; + } } - // No matching eNB or no eNB in list, return NULL - return eNB_ref; + /* No matching eNB or no eNB in list, return NULL */ + return NULL; } ue_description_t *s1ap_is_ue_eNB_id_in_list(eNB_description_t *eNB_ref, uint32_t eNB_ue_s1ap_id) { ue_description_t *ue_ref; - // No eNB_list_head in list, simply returning NULL - if (eNB_ref == NULL) return NULL; - for (ue_ref = eNB_ref->ue_list_head; ue_ref; ue_ref = ue_ref->next_ue) { - if (ue_ref->eNB_ue_s1ap_id == eNB_ue_s1ap_id) - break; + DevAssert(eNB_ref != NULL); + + STAILQ_FOREACH(ue_ref, &eNB_ref->ue_list_head, ue_entries) + { + if (ue_ref->eNB_ue_s1ap_id == eNB_ue_s1ap_id) { + return ue_ref; + } } - // No matching UE, return NULL - return ue_ref; + + return NULL; } ue_description_t* s1ap_is_ue_mme_id_in_list(uint32_t mme_ue_s1ap_id) { ue_description_t *ue_ref; eNB_description_t *eNB_ref; - // No eNB_list_head in list, simply returning NULL - if (eNB_list_head == NULL) return NULL; - for (eNB_ref = eNB_list_head; eNB_ref; eNB_ref = eNB_ref->next_eNB) { - for (ue_ref = eNB_ref->ue_list_head; ue_ref; ue_ref = ue_ref->next_ue) { + + STAILQ_FOREACH(eNB_ref, &eNB_list_head, eNB_entries) + { + STAILQ_FOREACH(ue_ref, &eNB_ref->ue_list_head, ue_entries) + { // We fount a matching reference, return it - if (ue_ref->mme_ue_s1ap_id == mme_ue_s1ap_id) + if (ue_ref->mme_ue_s1ap_id == mme_ue_s1ap_id) { return ue_ref; + } } } - // No matching UE, return NULL + return NULL; } @@ -290,16 +309,18 @@ ue_description_t* s1ap_is_teid_in_list(uint32_t teid) { ue_description_t *ue_ref; eNB_description_t *eNB_ref; - // No eNB_list_head in list, simply returning NULL - if (eNB_list_head == NULL) return NULL; - for (eNB_ref = eNB_list_head; eNB_ref; eNB_ref = eNB_ref->next_eNB) { - for (ue_ref = eNB_ref->ue_list_head; ue_ref; ue_ref = ue_ref->next_ue) { + + STAILQ_FOREACH(eNB_ref, &eNB_list_head, eNB_entries) + { + STAILQ_FOREACH(ue_ref, &eNB_ref->ue_list_head, ue_entries) + { // We fount a matching reference, return it - if (ue_ref->teid == teid) + if (ue_ref->teid == teid) { return ue_ref; + } } } - // No matching UE, return NULL + return NULL; } @@ -307,35 +328,22 @@ eNB_description_t* s1ap_new_eNB(void) { eNB_description_t *eNB_ref = NULL; - eNB_ref = malloc(sizeof(eNB_description_t)); - + eNB_ref = calloc(1, sizeof(eNB_description_t)); /* Something bad happened during malloc... * May be we are running out of memory. * TODO: Notify eNB with a cause like Hardware Failure. */ - if (eNB_ref == NULL) return NULL; - - memset(eNB_ref, 0, sizeof(eNB_description_t)); - - eNB_ref->next_eNB = NULL; - eNB_ref->previous_eNB = NULL; - // No eNB present - if (eNB_list_head == NULL) { - eNB_list_head = eNB_ref; - // Point tail to head (single element in list) - eNB_list_tail = eNB_list_head; - } else { - eNB_ref->previous_eNB = eNB_list_tail; - eNB_list_tail->next_eNB = eNB_ref; - // Update list tail with the new eNB added - eNB_list_tail = eNB_ref; - } + DevAssert(eNB_ref != NULL); // Update number of eNB associated nb_eNB_associated++; - eNB_ref->ue_list_head = NULL; - eNB_ref->ue_list_tail = NULL; + + STAILQ_INIT(&eNB_ref->ue_list_head); + eNB_ref->nb_ue_associated = 0; + + STAILQ_INSERT_TAIL(&eNB_list_head, eNB_ref, eNB_entries); + return eNB_ref; } @@ -344,104 +352,59 @@ ue_description_t* s1ap_new_ue(uint32_t sctp_assoc_id) { eNB_description_t *eNB_ref = NULL; ue_description_t *ue_ref = NULL; - if ((eNB_ref = s1ap_is_eNB_assoc_id_in_list(sctp_assoc_id)) == NULL) { - /* No eNB attached to this SCTP assoc ID... - * return NULL. - */ - return NULL; - } - ue_ref = malloc(sizeof(ue_description_t)); + eNB_ref = s1ap_is_eNB_assoc_id_in_list(sctp_assoc_id); + DevAssert(eNB_ref != NULL); + + ue_ref = calloc(1, sizeof(ue_description_t)); /* Something bad happened during malloc... * May be we are running out of memory. * TODO: Notify eNB with a cause like Hardware Failure. */ - if (ue_ref == NULL) return NULL; - - memset(ue_ref, 0, sizeof(ue_description_t)); + DevAssert(ue_ref != NULL); ue_ref->eNB = eNB_ref; - ue_ref->next_ue = NULL; - ue_ref->previous_ue = NULL; // Increment number of UE eNB_ref->nb_ue_associated++; - if (eNB_ref->ue_list_head == NULL) { - // Currently no UE in active list - eNB_ref->ue_list_head = ue_ref; - ue_ref->previous_ue = NULL; - eNB_ref->ue_list_tail = eNB_ref->ue_list_head; - } else { - eNB_ref->ue_list_tail->next_ue = ue_ref; - ue_ref->previous_ue = eNB_ref->ue_list_tail; - eNB_ref->ue_list_tail = ue_ref; - } + STAILQ_INSERT_TAIL(&eNB_ref->ue_list_head, ue_ref, ue_entries); return ue_ref; } -void s1ap_remove_ue(ue_description_t *ue_ref) { +void s1ap_remove_ue(ue_description_t *ue_ref) +{ + eNB_description_t *eNB_ref; + /* NULL reference... */ if (ue_ref == NULL) return; - /* Remove any attached timer */ - s1ap_timer_remove_ue(ue_ref->mme_ue_s1ap_id); - - if (ue_ref->next_ue != NULL) { - if (ue_ref->previous_ue != NULL) { - /* Not head and not tail */ - ue_ref->previous_ue->next_ue = ue_ref->next_ue; - ue_ref->next_ue->previous_ue = ue_ref->previous_ue; - } else { - /* Head but not tail */ - ue_ref->eNB->ue_list_head = ue_ref->next_ue; - ue_ref->next_ue->previous_ue = NULL; - } - } else { - if (ue_ref->previous_ue != NULL) { - /* Not head but tail */ - ue_ref->eNB->ue_list_tail = ue_ref->previous_ue; - ue_ref->previous_ue->next_ue = NULL; - } else { - /* Head and tail */ - ue_ref->eNB->ue_list_tail = ue_ref->eNB->ue_list_head = NULL; - } - } + eNB_ref = ue_ref->eNB; + /* Updating number of UE */ - ue_ref->eNB->nb_ue_associated--; + eNB_ref->nb_ue_associated--; + /* Remove any attached timer */ +// s1ap_timer_remove_ue(ue_ref->mme_ue_s1ap_id); + /* Freeing memory */ free(ue_ref); } -void s1ap_remove_eNB(eNB_description_t *eNB_ref) { +void s1ap_remove_eNB(eNB_description_t *eNB_ref) +{ ue_description_t *ue_ref; if (eNB_ref == NULL) return; - /* Removing any ue context */ - for (ue_ref = eNB_ref->ue_list_head; ue_ref; ue_ref = ue_ref->next_ue) { - s1ap_remove_ue(ue_ref); + while (!STAILQ_EMPTY(&eNB_ref->ue_list_head)) + { + ue_ref = STAILQ_FIRST(&eNB_ref->ue_list_head); + eNB_ref->nb_ue_associated--; + STAILQ_REMOVE_HEAD(&eNB_ref->ue_list_head, ue_entries); + free(ue_ref); } - if (eNB_ref->next_eNB != NULL) { - if (eNB_ref->previous_eNB != NULL) { - /* Not tail and not head */ - eNB_ref->previous_eNB->next_eNB = eNB_ref->next_eNB; - eNB_ref->next_eNB->previous_eNB = eNB_ref->previous_eNB; - } else { - /* Head but not tail */ - eNB_list_head = eNB_ref->next_eNB; - eNB_ref->next_eNB->previous_eNB = NULL; - } - } else { - if (eNB_ref->previous_eNB != NULL) { - /* Not head but tail */ - eNB_list_tail = eNB_ref->previous_eNB; - eNB_ref->previous_eNB->next_eNB = NULL; - } else { - /* Head and tail */ - eNB_list_tail = eNB_list_head = NULL; - } - } + STAILQ_REMOVE(&eNB_list_head, eNB_ref, eNB_description_s, eNB_entries); + free(eNB_ref); nb_eNB_associated--; } diff --git a/openair-cn/S1AP/s1ap_mme.h b/openair-cn/S1AP/s1ap_mme.h index 27329d13bd..c450c24fc7 100644 --- a/openair-cn/S1AP/s1ap_mme.h +++ b/openair-cn/S1AP/s1ap_mme.h @@ -55,8 +55,7 @@ enum s1_ue_state_s { * Generated every time a new InitialUEMessage is received **/ typedef struct ue_description_s { - struct ue_description_s *next_ue; ///< Next UE in the list - struct ue_description_s *previous_ue; ///< Previous UE in the list + STAILQ_ENTRY(ue_description_s) ue_entries; struct eNB_description_s *eNB; ///< Which eNB this UE is attached to @@ -86,8 +85,7 @@ typedef struct ue_description_s { * Generated (or updated) every time a new S1SetupRequest is received. */ typedef struct eNB_description_s { - struct eNB_description_s *next_eNB; ///< Next eNB in the list of eNB - struct eNB_description_s *previous_eNB; ///< Previous eNB in the list of eNB + STAILQ_ENTRY(eNB_description_s) eNB_entries; enum s1_eNB_state_s s1_state; ///< State of the eNB S1AP association over MME @@ -101,8 +99,7 @@ typedef struct eNB_description_s { /** UE list for this eNB **/ /*@{*/ uint32_t nb_ue_associated; ///< Number of NAS associated UE on this eNB - ue_description_t *ue_list_head; ///< List head of NAS associated UE on this eNB - ue_description_t *ue_list_tail; ///< List tail of NAS associated UE on this eNB + STAILQ_HEAD(ue_list_s, ue_description_s) ue_list_head; /*@}*/ /** SCTP stuff **/ diff --git a/openair-cn/S1AP/s1ap_mme_nas_procedures.c b/openair-cn/S1AP/s1ap_mme_nas_procedures.c index 2ffb50b306..54c3f5070a 100644 --- a/openair-cn/S1AP/s1ap_mme_nas_procedures.c +++ b/openair-cn/S1AP/s1ap_mme_nas_procedures.c @@ -282,12 +282,12 @@ int s1ap_handle_attach_accepted(nas_attach_accept_t *attach_accept_p) /* Start the outcome response timer. * When time is reached, MME consider that procedure outcome has failed. */ - timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT, - TIMER_ONE_SHOT, - NULL, - &ue_ref->outcome_response_timer_id); +// timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT, +// TIMER_ONE_SHOT, +// NULL, +// &ue_ref->outcome_response_timer_id); /* Insert the timer in the MAP of mme_ue_s1ap_id <-> timer_id */ - s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id); +// s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id); memset(&message, 0, sizeof(s1ap_message)); memset(&e_RABToBeSetup, 0, sizeof(E_RABToBeSetupItemCtxtSUReq_t)); -- GitLab