forked from acouzens/open5gs
Fix MME crash on eNB connection when maximum number of eNBs reached (#423)
* Remove mme_enb_t pool and use enb_list instead * Refactor S1 Setup request handler * Implement S1 Setup Failure response when maximum number of eNBs reached
This commit is contained in:
parent
e6ee163140
commit
cde847c53d
|
@ -41,7 +41,6 @@ static OGS_POOL(mme_pgw_pool, mme_pgw_t);
|
|||
static OGS_POOL(mme_vlr_pool, mme_vlr_t);
|
||||
static OGS_POOL(mme_csmap_pool, mme_csmap_t);
|
||||
|
||||
static OGS_POOL(mme_enb_pool, mme_enb_t);
|
||||
static OGS_POOL(mme_ue_pool, mme_ue_t);
|
||||
static OGS_POOL(enb_ue_pool, enb_ue_t);
|
||||
static OGS_POOL(mme_sess_pool, mme_sess_t);
|
||||
|
@ -124,8 +123,6 @@ void mme_context_init()
|
|||
ogs_pool_init(&mme_vlr_pool, ogs_config()->max.vlr);
|
||||
ogs_pool_init(&mme_csmap_pool, ogs_config()->max.csmap);
|
||||
|
||||
ogs_pool_init(&mme_enb_pool, ogs_config()->max.enb);
|
||||
|
||||
ogs_pool_init(&mme_ue_pool, ogs_config()->pool.ue);
|
||||
ogs_pool_init(&enb_ue_pool, ogs_config()->pool.ue);
|
||||
ogs_pool_init(&mme_sess_pool, ogs_config()->pool.sess);
|
||||
|
@ -173,8 +170,6 @@ void mme_context_final()
|
|||
ogs_pool_final(&mme_ue_pool);
|
||||
ogs_pool_final(&enb_ue_pool);
|
||||
|
||||
ogs_pool_final(&mme_enb_pool);
|
||||
|
||||
ogs_pool_final(&mme_sgw_pool);
|
||||
ogs_pool_final(&mme_pgw_pool);
|
||||
ogs_pool_final(&mme_csmap_pool);
|
||||
|
@ -1863,9 +1858,8 @@ mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr)
|
|||
ogs_assert(sock);
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_pool_alloc(&mme_enb_pool, &enb);
|
||||
enb = ogs_calloc(1, sizeof(mme_enb_t));
|
||||
ogs_assert(enb);
|
||||
memset(enb, 0, sizeof *enb);
|
||||
|
||||
enb->sock = sock;
|
||||
enb->addr = addr;
|
||||
|
@ -1925,8 +1919,7 @@ int mme_enb_remove(mme_enb_t *enb)
|
|||
}
|
||||
|
||||
ogs_free(enb->addr);
|
||||
|
||||
ogs_pool_free(&mme_enb_pool, enb);
|
||||
ogs_free(enb);
|
||||
|
||||
stats_remove_enb();
|
||||
|
||||
|
@ -3193,3 +3186,17 @@ uint8_t mme_selected_enc_algorithm(mme_ue_t *mme_ue)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mme_is_maximum_number_of_enbs_reached(void)
|
||||
{
|
||||
mme_enb_t *enb = NULL, *next_enb = NULL;
|
||||
int number_of_enbs_online = 0;
|
||||
|
||||
ogs_list_for_each_safe(&self.enb_list, next_enb, enb) {
|
||||
if (enb->s1_setup_success) {
|
||||
number_of_enbs_online++;
|
||||
}
|
||||
}
|
||||
|
||||
return number_of_enbs_online >= ogs_config()->max.enb;
|
||||
}
|
||||
|
|
|
@ -226,6 +226,8 @@ typedef struct mme_enb_s {
|
|||
ogs_sockaddr_t *addr; /* eNB S1AP Address */
|
||||
ogs_poll_t *poll; /* eNB S1AP Poll */
|
||||
|
||||
bool s1_setup_success; /* eNB S1AP Setup complete successfuly */
|
||||
|
||||
uint16_t max_num_of_ostreams;/* SCTP Max num of outbound streams */
|
||||
uint16_t ostream_id; /* enb_ostream_id generator */
|
||||
|
||||
|
@ -791,6 +793,7 @@ void stats_remove_enb(void);
|
|||
void stats_add_mme_session(void);
|
||||
void stats_remove_mme_session(void);
|
||||
|
||||
bool mme_is_maximum_number_of_enbs_reached(void);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -77,6 +77,25 @@ static uint8_t emm_cause_from_diameter(
|
|||
return EMM_CAUSE_SEVERE_NETWORK_FAILURE;
|
||||
}
|
||||
|
||||
static void handle_mme_s1ap_accept(ogs_sock_t *sock, ogs_sockaddr_t *address)
|
||||
{
|
||||
char address_string_buffer[OGS_ADDRSTRLEN];
|
||||
const char *address_string;
|
||||
|
||||
address_string = OGS_ADDR(address, address_string_buffer);
|
||||
|
||||
if (mme_enb_find_by_addr(address)) {
|
||||
ogs_warn("eNB context duplicated with IP-address [%s]!!!", address_string);
|
||||
ogs_sock_destroy(sock);
|
||||
ogs_warn("S1 Socket Closed");
|
||||
return;
|
||||
}
|
||||
|
||||
mme_enb_add(sock, address);
|
||||
ogs_info("eNB-S1 accepted[%s] in master_sm module", address_string);
|
||||
}
|
||||
|
||||
|
||||
void mme_state_initial(ogs_fsm_t *s, mme_event_t *e)
|
||||
{
|
||||
mme_sm_debug(e);
|
||||
|
@ -162,19 +181,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
addr = e->addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_info("eNB-S1 accepted[%s] in master_sm module",
|
||||
OGS_ADDR(addr, buf));
|
||||
|
||||
enb = mme_enb_find_by_addr(addr);
|
||||
if (!enb) {
|
||||
enb = mme_enb_add(sock, addr);
|
||||
ogs_assert(enb);
|
||||
} else {
|
||||
ogs_warn("eNB context duplicated with IP-address [%s]!!!",
|
||||
OGS_ADDR(addr, buf));
|
||||
ogs_sock_destroy(sock);
|
||||
ogs_warn("S1 Socket Closed");
|
||||
}
|
||||
handle_mme_s1ap_accept(sock, addr);
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -33,6 +33,44 @@
|
|||
#include "mme-path.h"
|
||||
#include "mme-sm.h"
|
||||
|
||||
static void send_s1_setup_failure_response(mme_enb_t *enb, S1AP_Cause_PR group, long cause)
|
||||
{
|
||||
ogs_pkbuf_t *s1ap_buffer;
|
||||
|
||||
ogs_debug("[MME] S1-Setup failure");
|
||||
s1ap_buffer = s1ap_build_setup_failure(group, cause, S1AP_TimeToWait_v10s);
|
||||
ogs_expect_or_return(s1ap_buffer);
|
||||
|
||||
ogs_expect(OGS_OK == s1ap_send_to_enb(enb, s1ap_buffer, S1AP_NON_UE_SIGNALLING));
|
||||
}
|
||||
|
||||
static void send_s1_setup_successful_response(mme_enb_t *enb)
|
||||
{
|
||||
ogs_pkbuf_t *s1ap_buffer;
|
||||
|
||||
ogs_debug("[MME] S1-Setup response");
|
||||
s1ap_buffer = s1ap_build_setup_rsp();
|
||||
ogs_expect_or_return(s1ap_buffer);
|
||||
|
||||
ogs_expect(OGS_OK == s1ap_send_to_enb(enb, s1ap_buffer, S1AP_NON_UE_SIGNALLING));
|
||||
}
|
||||
|
||||
static bool is_mme_serving_enb_supported_tai(mme_enb_t *enb)
|
||||
{
|
||||
int i;
|
||||
int served_tai_index;
|
||||
|
||||
for (i = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
served_tai_index = mme_find_served_tai(&enb->supported_ta_list[i]);
|
||||
if (served_tai_index >= 0 && served_tai_index < MAX_NUM_OF_SERVED_TAI) {
|
||||
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
@ -46,7 +84,6 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
S1AP_SupportedTAs_t *SupportedTAs = NULL;
|
||||
S1AP_PagingDRX_t *PagingDRX = NULL;
|
||||
|
||||
ogs_pkbuf_t *s1apbuf = NULL;
|
||||
uint32_t enb_id;
|
||||
S1AP_Cause_PR group = S1AP_Cause_PR_NOTHING;
|
||||
long cause = 0;
|
||||
|
@ -126,43 +163,38 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
}
|
||||
}
|
||||
|
||||
if (mme_is_maximum_number_of_enbs_reached()) {
|
||||
ogs_warn("S1-Setup failure:");
|
||||
ogs_warn(" Maximum number of eNBs reached");
|
||||
group = S1AP_Cause_PR_misc;
|
||||
cause = S1AP_CauseMisc_unspecified;
|
||||
|
||||
send_s1_setup_failure_response(enb, group, cause);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enb->num_of_supported_ta_list == 0) {
|
||||
ogs_warn("S1-Setup failure:");
|
||||
ogs_warn(" No supported TA exist in S1-Setup request");
|
||||
group = S1AP_Cause_PR_misc;
|
||||
cause = S1AP_CauseMisc_unspecified;
|
||||
} else {
|
||||
int served_tai_index = -1;
|
||||
for (i = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
served_tai_index =
|
||||
mme_find_served_tai(&enb->supported_ta_list[i]);
|
||||
if (served_tai_index >= 0 &&
|
||||
served_tai_index < MAX_NUM_OF_SERVED_TAI) {
|
||||
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (served_tai_index < 0) {
|
||||
ogs_warn("S1-Setup failure:");
|
||||
ogs_warn(" Cannot find Served TAI. Check 'mme.tai' configuration");
|
||||
group = S1AP_Cause_PR_misc;
|
||||
cause = S1AP_CauseMisc_unknown_PLMN;
|
||||
}
|
||||
send_s1_setup_failure_response(enb, group, cause);
|
||||
return;
|
||||
}
|
||||
|
||||
if (group == S1AP_Cause_PR_NOTHING) {
|
||||
ogs_debug("[MME] S1-Setup response");
|
||||
s1apbuf = s1ap_build_setup_rsp();
|
||||
ogs_expect_or_return(s1apbuf);
|
||||
} else {
|
||||
ogs_debug("[MME] S1-Setup failure");
|
||||
s1apbuf = s1ap_build_setup_failure(group, cause, S1AP_TimeToWait_v10s);
|
||||
ogs_expect_or_return(s1apbuf);
|
||||
if (!is_mme_serving_enb_supported_tai(enb)) {
|
||||
ogs_warn("S1-Setup failure:");
|
||||
ogs_warn(" Cannot find Served TAI. Check 'mme.tai' configuration");
|
||||
group = S1AP_Cause_PR_misc;
|
||||
cause = S1AP_CauseMisc_unknown_PLMN;
|
||||
|
||||
send_s1_setup_failure_response(enb, group, cause);
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_expect(OGS_OK ==
|
||||
s1ap_send_to_enb(enb, s1apbuf, S1AP_NON_UE_SIGNALLING));
|
||||
enb->s1_setup_success = true;
|
||||
send_s1_setup_successful_response(enb);
|
||||
}
|
||||
|
||||
void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
||||
|
|
Loading…
Reference in New Issue