diff --git a/lib/gtp/path.c b/lib/gtp/path.c index 20adef813..e4895e4de 100644 --- a/lib/gtp/path.c +++ b/lib/gtp/path.c @@ -242,6 +242,24 @@ void ogs_gtp_send_error_message( case OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: tlv = &errmsg.release_access_bearers_response.cause; break; + case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE: + tlv = &errmsg.downlink_data_notification_acknowledge.cause; + break; + case OGS_GTP_CREATE_BEARER_RESPONSE_TYPE: + tlv = &errmsg.create_bearer_response.cause; + break; + case OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE: + tlv = &errmsg.update_bearer_response.cause; + break; + case OGS_GTP_DELETE_BEARER_RESPONSE_TYPE: + tlv = &errmsg.delete_bearer_response.cause; + break; + case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: + tlv = &errmsg.create_indirect_data_forwarding_tunnel_response.cause; + break; + case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: + tlv = &errmsg.delete_indirect_data_forwarding_tunnel_response.cause; + break; default: ogs_assert_if_reached(); return; diff --git a/lib/gtp/xact.c b/lib/gtp/xact.c index 65fd35358..184ace54c 100644 --- a/lib/gtp/xact.c +++ b/lib/gtp/xact.c @@ -72,8 +72,9 @@ int ogs_gtp_xact_final(void) return OGS_OK; } -ogs_gtp_xact_t *ogs_gtp_xact_local_create( - ogs_gtp_node_t *gnode, ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf) +ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode, + ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf, + void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data) { int rv; char buf[OGS_ADDRSTRLEN]; @@ -89,6 +90,8 @@ ogs_gtp_xact_t *ogs_gtp_xact_local_create( xact->org = OGS_GTP_LOCAL_ORIGINATOR; xact->xid = OGS_NEXT_ID(g_xact_id, GTP_MIN_XACT_ID, GTP_MAX_XACT_ID); xact->gnode = gnode; + xact->cb = cb; + xact->data = data; xact->tm_response = ogs_timer_add(g_timer_mgr, response_timeout, xact); ogs_assert(xact->tm_response); @@ -513,6 +516,10 @@ static void response_timeout(void *data) xact->step, xact->seq[xact->step-1].type, OGS_ADDR(&xact->gnode->remote_addr, buf), OGS_PORT(&xact->gnode->remote_addr)); + + if (xact->cb) + xact->cb(xact, xact->data); + ogs_gtp_xact_delete(xact); } diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 7b49ca28c..bf3fcb543 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -43,6 +43,9 @@ typedef struct ogs_gtp_xact_s { uint32_t xid; /**< Transaction ID */ ogs_gtp_node_t *gnode; /**< Relevant GTP node context */ + void (*cb)(ogs_gtp_xact_t *, void *); /**< Local timer expiration handler */ + void *data; /**< Transaction Data */ + int step; /**< Current step in the sequence. 1 : Initial 2 : Triggered @@ -58,23 +61,14 @@ typedef struct ogs_gtp_xact_s { uint8_t holding_rcount; struct ogs_gtp_xact_s *assoc_xact; /**< Associated transaction */ - -#define OGS_GTP_XACT_STORE_SESSION(xact, session) \ - do { \ - ogs_assert((xact)); \ - ogs_assert((session)); \ - ((xact)->sess) = (session); \ - } while(0) - -#define OGS_GTP_XACT_RETRIEVE_SESSION(xact) ((xact) ? ((xact)->sess) : NULL) - void *sess; /**< Session Store */ } ogs_gtp_xact_t; int ogs_gtp_xact_init(ogs_timer_mgr_t *timer_mgr, int size); int ogs_gtp_xact_final(void); -ogs_gtp_xact_t *ogs_gtp_xact_local_create( - ogs_gtp_node_t *gnode, ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf); +ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode, + ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf, + void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data); ogs_gtp_xact_t *ogs_gtp_xact_remote_create( ogs_gtp_node_t *gnode, uint32_t sqn); void ogs_gtp_xact_delete_all(ogs_gtp_node_t *gnode); diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 08dc6c3dc..06a545c97 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -246,8 +246,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { rv = sgsap_send_detach_indication(mme_ue); } else { - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); + mme_send_delete_session_or_detach(mme_ue); } OGS_FSM_TRAN(s, &emm_state_de_registered); @@ -347,8 +346,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(s, &emm_state_initial_context_setup); } else { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); + mme_gtp_send_delete_all_sessions(mme_ue); } else { mme_s6a_send_air(mme_ue, NULL); } @@ -384,9 +382,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) S1AP_ProcedureCode_id_downlinkNASTransport); ogs_assert(rv == OGS_OK); - rv = mme_send_release_access_bearer_or_ue_context_release( - mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); + mme_send_release_access_bearer_or_ue_context_release(enb_ue); } } else if (procedureCode == S1AP_ProcedureCode_id_uplinkNASTransport) { ogs_debug(" Uplink NAS Transport"); @@ -620,9 +616,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e) return; } - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - + mme_send_delete_session_or_detach(mme_ue); OGS_FSM_TRAN(s, &emm_state_de_registered); break; default: @@ -784,9 +778,7 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) break; } - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - + mme_send_delete_session_or_detach(mme_ue); OGS_FSM_TRAN(s, &emm_state_de_registered); break; default: @@ -877,8 +869,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) return; } - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); + mme_gtp_send_delete_all_sessions(mme_ue); OGS_FSM_TRAN(s, &emm_state_authentication); break; case OGS_NAS_EMM_STATUS: @@ -898,9 +889,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) return; } - rv = mme_send_delete_session_or_detach(mme_ue); - ogs_assert(rv == OGS_OK); - + mme_send_delete_session_or_detach(mme_ue); OGS_FSM_TRAN(s, &emm_state_de_registered); break; default: diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 3a8543e2c..d3ec1c261 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2801,6 +2801,8 @@ mme_bearer_t *mme_bearer_find_by_sess_ebi(mme_sess_t *sess, uint8_t ebi) { mme_bearer_t *bearer = NULL; + ogs_assert(sess); + bearer = mme_bearer_first(sess); while (bearer) { if (ebi == bearer->ebi) @@ -2817,6 +2819,8 @@ mme_bearer_t *mme_bearer_find_by_ue_ebi(mme_ue_t *mme_ue, uint8_t ebi) mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + ogs_assert(mme_ue); + sess = mme_sess_first(mme_ue); while (sess) { bearer = mme_bearer_find_by_sess_ebi(sess, ebi); @@ -2904,6 +2908,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message( mme_bearer_t *mme_default_bearer_in_sess(mme_sess_t *sess) { + ogs_assert(sess); return mme_bearer_first(sess); } @@ -2927,6 +2932,7 @@ mme_bearer_t *mme_bearer_first(mme_sess_t *sess) mme_bearer_t *mme_bearer_next(mme_bearer_t *bearer) { + ogs_assert(bearer); return ogs_list_next(bearer); } @@ -2954,8 +2960,8 @@ int mme_bearer_is_inactive(mme_ue_t *mme_ue) int mme_bearer_set_inactive(mme_ue_t *mme_ue) { mme_sess_t *sess = NULL; - ogs_assert(mme_ue); + ogs_assert(mme_ue); sess = mme_sess_first(mme_ue); while (sess) { mme_bearer_t *bearer = mme_bearer_first(sess); @@ -2988,6 +2994,8 @@ ogs_pdn_t *mme_pdn_find_by_apn(mme_ue_t *mme_ue, char *apn) int i = 0; ogs_assert(mme_ue); + ogs_assert(apn); + subscription_data = &mme_ue->subscription_data; ogs_assert(subscription_data); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 4bcec4257..b4a1a923f 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -264,8 +264,8 @@ struct enb_ue_s { /* Store by UE Context Release Command * Retrieve by UE Context Release Complete */ #define S1AP_UE_CTX_REL_INVALID_ACTION 0 -#define S1AP_UE_CTX_REL_NO_ACTION 1 -#define S1AP_UE_CTX_REL_S1_NORMAL_RELEASE 2 +#define S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE 1 +#define S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK 2 #define S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE 3 #define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 4 uint8_t ue_ctx_rel_action; @@ -461,6 +461,12 @@ struct mme_ue_s { OCTET_STRING_t container; /* GTP Request/Response Counter */ +#define GTP_COUNTER_CLEAR(__mME, __tYPE) \ + do { \ + ogs_assert((__mME)); \ + ((__mME)->gtp_counter[__tYPE].request) = 0; \ + ((__mME)->gtp_counter[__tYPE].response) = 0; \ + } while(0); #define GTP_COUNTER_INCREMENT(__mME, __tYPE) \ do { \ ogs_assert((__mME)); \ @@ -475,8 +481,7 @@ struct mme_ue_s { if (((__mME)->gtp_counter[__tYPE].request) == \ ((__mME)->gtp_counter[__tYPE].response)) \ { \ - ((__mME)->gtp_counter[__tYPE].request) = 0; \ - ((__mME)->gtp_counter[__tYPE].response) = 0; \ + GTP_COUNTER_CLEAR(__mME, __tYPE) \ __eXPR \ } \ } while(0); diff --git a/src/mme/mme-event.h b/src/mme/mme-event.h index 39702e52c..0b983c018 100644 --- a/src/mme/mme-event.h +++ b/src/mme/mme-event.h @@ -63,6 +63,7 @@ typedef struct enb_ue_s enb_ue_t; typedef struct mme_ue_s mme_ue_t; typedef struct mme_sess_s mme_sess_t; typedef struct mme_bearer_s mme_bearer_t; +typedef struct ogs_gtp_node_s ogs_gtp_node_t; typedef struct mme_event_s { int id; @@ -78,6 +79,8 @@ typedef struct mme_event_s { S1AP_ProcedureCode_t s1ap_code; s1ap_message_t *s1ap_message; + ogs_gtp_node_t *gnode; + uint8_t nas_type; ogs_nas_message_t *nas_message; diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index f6ea2ba6f..ec09911f1 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -21,16 +21,21 @@ #include "mme-event.h" #include "mme-gtp-path.h" +#include "mme-path.h" +#include "s1ap-path.h" #include "mme-s11-build.h" #include "mme-sm.h" static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) { int rv; + char buf[OGS_ADDRSTRLEN]; + ssize_t size; mme_event_t *e = NULL; ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; + mme_sgw_t *sgw = NULL; ogs_assert(fd != INVALID_SOCKET); @@ -47,25 +52,65 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_trim(pkbuf, size); + sgw = mme_sgw_find_by_addr(&from); + if (!sgw) { + ogs_error("Unknown SGW : %s", OGS_ADDR(&from, buf)); + ogs_pkbuf_free(e->pkbuf); + return; + } + ogs_assert(sgw->gnode); + e = mme_event_new(MME_EVT_S11_MESSAGE); ogs_assert(e); + e->gnode = sgw->gnode; e->pkbuf = pkbuf; - e->sock = data; - ogs_assert(e->sock); - e->addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(e->addr); - memcpy(e->addr, &from, sizeof(ogs_sockaddr_t)); - rv = ogs_queue_push(mme_self()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); - ogs_free(e->addr); mme_event_free(e); } } +static void timeout(ogs_gtp_xact_t *xact, void *data) +{ + mme_ue_t *mme_ue = NULL; + enb_ue_t *enb_ue = NULL; + mme_sess_t *sess = NULL; + uint8_t type = 0; + + ogs_assert(xact); + type = xact->seq[0].type; + + switch (type) { + case OGS_GTP_DELETE_SESSION_REQUEST_TYPE: + sess = data; + ogs_assert(sess); + mme_ue = sess->mme_ue; + ogs_assert(mme_ue); + + enb_ue = mme_ue->enb_ue; + if (enb_ue) { + CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); + s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); + } else { + ogs_warn("No S1 Context"); + } + break; + default: + mme_ue = data; + ogs_assert(mme_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + break; + } + + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + mme_ue->imsi_bcd, type); +} + int mme_gtp_open(void) { int rv; @@ -134,7 +179,7 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess) rv = mme_s11_build_create_session_request(&pkbuf, h.type, sess); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); @@ -167,7 +212,7 @@ int mme_gtp_send_modify_bearer_request( &pkbuf, h.type, bearer, uli_presence); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); @@ -195,18 +240,16 @@ int mme_gtp_send_delete_session_request(mme_sess_t *sess) rv = mme_s11_build_delete_session_request(&s11buf, h.type, sess); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf, timeout, sess); ogs_assert(xact); - OGS_GTP_XACT_STORE_SESSION(xact, sess); - rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); return OGS_OK; } -int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) +void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) { int rv; mme_sess_t *sess = NULL, *next_sess = NULL; @@ -216,7 +259,7 @@ int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) if (SESSION_CONTEXT_WILL_DELETED(mme_ue)) { ogs_warn("The MME has already sent a Delete-Session-Request to the SGW" " for all sessions."); - return OGS_OK; + return; } mme_ue->session_context_will_deleted = 1; @@ -242,8 +285,6 @@ int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) sess = next_sess; } - - return OGS_OK; } int mme_gtp_send_create_bearer_response(mme_bearer_t *bearer) @@ -342,7 +383,7 @@ int mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer) return OGS_OK; } -int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue) +void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue) { int rv; ogs_gtp_header_t h; @@ -358,13 +399,11 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue) rv = mme_s11_build_release_access_bearers_request(&pkbuf, h.type); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); - - return OGS_OK; } int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( @@ -385,7 +424,7 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( &pkbuf, h.type, mme_ue); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); @@ -411,7 +450,7 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( pkbuf = ogs_pkbuf_alloc(NULL, OGS_TLV_MAX_HEADROOM); ogs_pkbuf_reserve(pkbuf, OGS_TLV_MAX_HEADROOM); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); diff --git a/src/mme/mme-gtp-path.h b/src/mme/mme-gtp-path.h index e1603c8ef..61c701c4b 100644 --- a/src/mme/mme-gtp-path.h +++ b/src/mme/mme-gtp-path.h @@ -33,11 +33,11 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess); int mme_gtp_send_modify_bearer_request( mme_bearer_t *bearer, int uli_presence); int mme_gtp_send_delete_session_request(mme_sess_t *sess); -int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue); +void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue); int mme_gtp_send_create_bearer_response(mme_bearer_t *bearer); int mme_gtp_send_update_bearer_response(mme_bearer_t *bearer); int mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer); -int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue); +void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue); int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( mme_ue_t *mme_ue); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 0aeaba6c6..54394aa64 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -22,61 +22,71 @@ #include "mme-gtp-path.h" #include "mme-path.h" -int mme_send_delete_session_or_detach(mme_ue_t *mme_ue) +void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) { - int rv; - ogs_assert(mme_ue); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); + mme_gtp_send_delete_all_sessions(mme_ue); } else { - rv = nas_send_detach_accept(mme_ue); - ogs_assert(rv == OGS_OK); + nas_send_detach_accept(mme_ue); } - - return rv; } -int mme_send_delete_session_or_ue_context_release( - mme_ue_t *mme_ue, enb_ue_t *enb_ue) +void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue) { - int rv; - - ogs_assert(enb_ue); + ogs_assert(mme_ue); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - rv = mme_gtp_send_delete_all_sessions(mme_ue); - ogs_assert(rv == OGS_OK); + mme_gtp_send_delete_all_sessions(mme_ue); } else { - CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); - ogs_assert(rv == OGS_OK); + enb_ue_t *enb_ue = mme_ue->enb_ue; + if (enb_ue) { + CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); + s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); + } else { + ogs_warn("No S1 Context"); + } } - - return rv; } -int mme_send_release_access_bearer_or_ue_context_release( - mme_ue_t *mme_ue, enb_ue_t *enb_ue) +void mme_send_delete_session_or_enb_ue_context_release(enb_ue_t *enb_ue) { - int rv; - + mme_ue_t *mme_ue = NULL; ogs_assert(enb_ue); - if (BEARER_CONTEXT_IS_ACTIVE(mme_ue)) { - rv = mme_gtp_send_release_access_bearers_request(mme_ue); - ogs_assert(rv == OGS_OK); + mme_ue = enb_ue->mme_ue; + if (mme_ue && SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + mme_gtp_send_delete_all_sessions(mme_ue); } else { CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0); - ogs_assert(rv == OGS_OK); + S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0); + } +} + +void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue) +{ + mme_ue_t *mme_ue = NULL; + ogs_assert(enb_ue); + + mme_ue = enb_ue->mme_ue; + if (mme_ue) { + if (BEARER_CONTEXT_IS_ACTIVE(mme_ue)) { + ogs_debug(" EMM-Registered"); + mme_gtp_send_release_access_bearers_request(mme_ue); + } else { + ogs_warn("No EMM-Registered"); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + } + } else { + ogs_debug("No UE Context"); + CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); + s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0); } - - return rv; } diff --git a/src/mme/mme-path.h b/src/mme/mme-path.h index d2ac19e68..e9f205e9e 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -26,11 +26,10 @@ extern "C" { #endif -int mme_send_delete_session_or_detach(mme_ue_t *mme_ue); -int mme_send_delete_session_or_ue_context_release( - mme_ue_t *mme_ue, enb_ue_t *enb_ue); -int mme_send_release_access_bearer_or_ue_context_release( - mme_ue_t *mme_ue, enb_ue_t *enb_ue); +void mme_send_delete_session_or_detach(mme_ue_t *mme_ue); +void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue); +void mme_send_delete_session_or_enb_ue_context_release(enb_ue_t *enb_ue); +void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue); #ifdef __cplusplus } diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 2c8fc0656..b8b3f34dd 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -26,6 +26,7 @@ #include "nas-path.h" #include "mme-fd-path.h" #include "sgsap-path.h" +#include "mme-path.h" #include "mme-s11-build.h" #include "mme-s11-handler.h" @@ -35,6 +36,7 @@ void mme_s11_handle_create_session_response( ogs_gtp_create_session_response_t *rsp) { int rv; + uint8_t cause_value = 0; ogs_gtp_f_teid_t *sgw_s11_teid = NULL; ogs_gtp_f_teid_t *sgw_s1u_teid = NULL; @@ -47,31 +49,65 @@ void mme_s11_handle_create_session_response( ogs_debug("[MME] Create Session Response"); + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts_created.cause.presence) { + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("Cause[%d] : No Accepted", cause_value); + if (rsp->sender_f_teid_for_control_plane.presence == 0) { ogs_error("No S11 TEID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->pdn_address_allocation.presence == 0) { ogs_error("No PDN Address Allocation"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) { ogs_error("No S1U TEID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->bearer_contexts_created.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (rsp->bearer_contexts_created. eps_bearer_id.presence == 0) { + if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } - ogs_assert(mme_ue); bearer = mme_bearer_find_by_ue_ebi(mme_ue, rsp->bearer_contexts_created.eps_bearer_id.u8); ogs_assert(bearer); @@ -127,7 +163,7 @@ void mme_s11_handle_modify_bearer_response( ogs_gtp_modify_bearer_response_t *rsp) { int rv; - ogs_gtp_cause_t *cause = NULL; + uint8_t cause_value = 0; enb_ue_t *source_ue = NULL, *target_ue = NULL; ogs_assert(xact); @@ -135,28 +171,32 @@ void mme_s11_handle_modify_bearer_response( ogs_debug("[MME] Modify Bearer Response"); + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - return; - } + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); - if (!mme_ue) { - ogs_warn("No Context"); - return; + cause_value = cause->value; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH, rv = s1ap_send_path_switch_ack(mme_ue); ogs_assert(rv == OGS_OK); @@ -169,12 +209,11 @@ void mme_s11_handle_modify_bearer_response( ogs_assert(source_ue); CLEAR_ENB_UE_TIMER(source_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(source_ue, + s1ap_send_ue_context_release_command(source_ue, S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_successful_handover, S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL, ogs_time_from_msec(300)); - ogs_assert(rv == OGS_OK); ); } @@ -183,7 +222,7 @@ void mme_s11_handle_delete_session_response( ogs_gtp_delete_session_response_t *rsp) { int rv; - ogs_gtp_cause_t *cause = NULL; + uint8_t cause_value = 0; mme_sess_t *sess = NULL; ogs_assert(xact); @@ -191,24 +230,21 @@ void mme_s11_handle_delete_session_response( ogs_debug("[MME] Delete Session Response"); - rv = ogs_gtp_xact_commit(xact); - ogs_assert(rv == OGS_OK); - - sess = OGS_GTP_XACT_RETRIEVE_SESSION(xact); + sess = xact->data; ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - goto cleanup; - } + rv = ogs_gtp_xact_commit(xact); + ogs_assert(rv == OGS_OK); - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - goto cleanup; + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("GTP Failed [CAUSE:%d] - Ignored", cause_value); } ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -220,8 +256,7 @@ void mme_s11_handle_delete_session_response( } } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { - rv = nas_send_detach_accept(mme_ue); - ogs_assert(rv == OGS_OK); + nas_send_detach_accept(mme_ue); } } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { mme_bearer_t *bearer = mme_default_bearer_in_sess(sess); @@ -256,10 +291,9 @@ void mme_s11_handle_delete_session_response( enb_ue = mme_ue->enb_ue; if (enb_ue) { CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); - ogs_assert(rv == OGS_OK); } else ogs_warn("ENB-S1 Context has already been removed"); } @@ -274,17 +308,15 @@ void mme_s11_handle_delete_session_response( enb_ue = mme_ue->enb_ue; if (enb_ue) { CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); - ogs_assert(rv == OGS_OK); } else ogs_warn("ENB-S1 Context has already been removed"); } } else ogs_assert_if_reached(); -cleanup: if (mme_sess_count(mme_ue) == 1) /* Last Session */ CLEAR_SESSION_CONTEXT(mme_ue); @@ -296,6 +328,7 @@ void mme_s11_handle_create_bearer_request( ogs_gtp_create_bearer_request_t *req) { int rv; + uint8_t cause_value = 0; mme_bearer_t *bearer = NULL, *default_bearer = NULL; mme_sess_t *sess = NULL; @@ -307,41 +340,56 @@ void mme_s11_handle_create_bearer_request( ogs_debug("[MME] Create Bearer Response"); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No Linked EBI"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } + + if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); + ogs_assert(sess); + + bearer = mme_bearer_add(sess); + ogs_assert(bearer); + } + + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { ogs_error("No GTP TEID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.bearer_level_qos.presence == 0) { ogs_error("No QoS"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.tft.presence == 0) { ogs_error("No TFT"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_assert(mme_ue); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); - ogs_assert(sess); - - bearer = mme_bearer_add(sess); - ogs_assert(bearer); - /* Data Plane(UL) : SGW-S1U */ sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data; bearer->sgw_s1u_teid = ntohl(sgw_s1u_teid->teid); @@ -388,6 +436,7 @@ void mme_s11_handle_update_bearer_request( ogs_gtp_update_bearer_request_t *req) { int rv; + uint8_t cause_value = 0; mme_bearer_t *bearer = NULL; ogs_gtp_bearer_qos_t bearer_qos; @@ -396,23 +445,37 @@ void mme_s11_handle_update_bearer_request( ogs_debug("[MME] Update Bearer Request"); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = mme_bearer_find_by_ue_ebi(mme_ue, + req->bearer_contexts.eps_bearer_id.u8); + ogs_assert(bearer); + } + + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_assert(mme_ue); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - bearer = mme_bearer_find_by_ue_ebi(mme_ue, - req->bearer_contexts.eps_bearer_id.u8); - ogs_assert(bearer); - /* Save Transaction. will be handled after EMM-attached */ bearer->xact = xact; @@ -479,20 +542,25 @@ void mme_s11_handle_delete_bearer_request( ogs_debug("[MME] Delete Bearer Request"); - if (req->linked_eps_bearer_id.presence == 1) { + if (mme_ue && req->linked_eps_bearer_id.presence == 1) { bearer = mme_bearer_find_by_ue_ebi( mme_ue, req->linked_eps_bearer_id.u8); ogs_assert(bearer); - } else if (req->eps_bearer_ids.presence == 1) { + } else if (mme_ue && req->eps_bearer_ids.presence == 1) { bearer = mme_bearer_find_by_ue_ebi( mme_ue, req->eps_bearer_ids.u8); ogs_assert(bearer); } else { ogs_error("No Linked EBI or EPS Bearer ID"); + ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, + OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); return; } ogs_assert(mme_ue); + ogs_assert(bearer); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -522,7 +590,7 @@ void mme_s11_handle_release_access_bearers_response( ogs_gtp_release_access_bearers_response_t *rsp) { int rv; - ogs_gtp_cause_t *cause = NULL; + uint8_t cause_value = 0; enb_ue_t *enb_ue = NULL; ogs_assert(xact); @@ -530,38 +598,41 @@ void mme_s11_handle_release_access_bearers_response( ogs_debug("[MME] Release Access Bearers Response"); + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - return; - } + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); - if (!mme_ue) { - ogs_warn("No Context"); - return; + cause_value = cause->value; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + rv = CLEAR_BEARER_CONTEXT(mme_ue); ogs_assert(rv == OGS_OK); enb_ue = mme_ue->enb_ue; if (enb_ue) { CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0); - ogs_assert(rv == OGS_OK); + S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); } else { ogs_warn("ENB-S1 Context has already been removed"); } @@ -572,6 +643,7 @@ void mme_s11_handle_downlink_data_notification( ogs_gtp_downlink_data_notification_t *noti) { int rv; + ogs_gtp_cause_t cause; ogs_gtp_header_t h; ogs_pkbuf_t *s11buf = NULL; @@ -580,7 +652,21 @@ void mme_s11_handle_downlink_data_notification( ogs_debug("[MME] Downlink Data Notification"); - ogs_assert(mme_ue); + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + if (!mme_ue) { + ogs_warn("No Context"); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE, + cause.value); + return; + } + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); @@ -604,7 +690,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( ogs_gtp_create_indirect_data_forwarding_tunnel_response_t *rsp) { int rv; - ogs_gtp_cause_t *cause = NULL; + uint8_t cause_value = 0; mme_bearer_t *bearer = NULL; enb_ue_t *source_ue = NULL; int i; @@ -617,28 +703,32 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( ogs_debug("[MME] Create Indirect Data Forwarding Tunnel Response"); + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - return; - } + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); - if (!mme_ue) { - ogs_warn("No Context"); - return; + cause_value = cause->value; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + ogs_gtp_bearers_in_create_indirect_tunnel_response(&bearers, rsp); for (i = 0; bearers[i]->presence; i++) { @@ -681,29 +771,33 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( ogs_gtp_delete_indirect_data_forwarding_tunnel_response_t *rsp) { int rv; - ogs_gtp_cause_t *cause = NULL; + uint8_t cause_value = 0; ogs_assert(xact); ogs_assert(rsp); ogs_debug("[MME] Delete Indirect Data Forwarding Tunnel Response"); + if (!mme_ue) { + ogs_warn("No Context in TEID"); + mme_ue = xact->data; + ogs_assert(mme_ue); + } + rv = ogs_gtp_xact_commit(xact); ogs_assert(rv == OGS_OK); - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - return; + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } - if (!mme_ue) { - ogs_warn("No Context"); + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 5e61f398f..64bdbffc0 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -58,7 +58,6 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_sockaddr_t *addr = NULL; mme_enb_t *enb = NULL; uint16_t max_num_of_ostreams = 0; - mme_sgw_t *sgw = NULL; s1ap_message_t s1ap_message; ogs_pkbuf_t *pkbuf = NULL; @@ -271,7 +270,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_fsm_dispatch(&mme_ue->sm, e); if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_exception)) { - mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); } ogs_pkbuf_free(pkbuf); @@ -328,8 +327,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) * [Enhancement] - Probably Invalid APN * At this point, we'll forcely release UE context */ - mme_send_delete_session_or_ue_context_release( - mme_ue, mme_ue->enb_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); } ogs_pkbuf_free(pkbuf); @@ -364,10 +362,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_assert(enb_ue); CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); - ogs_assert(rv == OGS_OK); ogs_pkbuf_free(s6abuf); break; @@ -459,15 +456,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_assert(gnode); } else { - ogs_assert(e->addr); - - sgw = mme_sgw_find_by_addr(e->addr); - ogs_assert(sgw); - - gnode = sgw->gnode; + gnode = e->gnode; ogs_assert(gnode); } - ogs_free(e->addr); rv = ogs_gtp_xact_receive(gnode, >p_message.h, &xact); if (rv != OGS_OK) { diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index f4830baaf..011d0efae 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -253,9 +253,8 @@ int nas_send_authentication_reject(mme_ue_t *mme_ue) return OGS_OK; } -int nas_send_detach_accept(mme_ue_t *mme_ue) +void nas_send_detach_accept(mme_ue_t *mme_ue) { - int rv; enb_ue_t *enb_ue = NULL; ogs_pkbuf_t *emmbuf = NULL; @@ -265,6 +264,7 @@ int nas_send_detach_accept(mme_ue_t *mme_ue) /* reply with detach accept */ if (mme_ue->nas_eps.detach.switch_off == 0) { + int rv; rv = emm_build_detach_accept(&emmbuf, mme_ue); ogs_assert(rv == OGS_OK && emmbuf); @@ -273,12 +273,9 @@ int nas_send_detach_accept(mme_ue_t *mme_ue) } CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, + s1ap_send_ue_context_release_command(enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_detach, - S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0); - ogs_assert(rv == OGS_OK); - - return OGS_OK; + S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); } diff --git a/src/mme/nas-path.h b/src/mme/nas-path.h index 3433e3ffd..e88c300cb 100644 --- a/src/mme/nas-path.h +++ b/src/mme/nas-path.h @@ -43,7 +43,7 @@ int nas_send_authentication_reject(mme_ue_t *mme_ue); int nas_send_security_mode_command(mme_ue_t *mme_ue); -int nas_send_detach_accept(mme_ue_t *mme_ue); +void nas_send_detach_accept(mme_ue_t *mme_ue); int nas_send_pdn_connectivity_reject( mme_sess_t *sess, ogs_nas_esm_cause_t esm_cause); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index f2d9975ff..82be2190d 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -520,7 +520,6 @@ void s1ap_handle_initial_context_setup_response( void s1ap_handle_initial_context_setup_failure( mme_enb_t *enb, ogs_s1ap_message_t *message) { - int rv; char buf[OGS_ADDRSTRLEN]; int i; @@ -578,32 +577,20 @@ void s1ap_handle_initial_context_setup_failure( ogs_debug(" Cause[Group:%d Cause:%d]", Cause->present, (int)Cause->choice.radioNetwork); - mme_ue = enb_ue->mme_ue; - - if (!mme_ue) { - ogs_debug(" S1 Context Release"); - CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_NO_ACTION, 0); - ogs_assert(rv == OGS_OK); - } else { - ogs_debug(" UE Context Release [IMSI:%s]", mme_ue->imsi_bcd); - /* - * 19.2.2.3 in Spec 36.300 - * - * In case of failure, eNB and MME behaviours are not mandated. - * - * Both implicit release (local release at each node) and - * explicit release (MME-initiated UE Context Release procedure) - * may in principle be adopted. The eNB should ensure - * that no hanging resources remain at the eNB. - */ - rv = mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); - + if (mme_ue) CLEAR_SERVICE_INDICATOR(mme_ue); - } + + /* + * 19.2.2.3 in Spec 36.300 + * + * In case of failure, eNB and MME behaviours are not mandated. + * + * Both implicit release (local release at each node) and + * explicit release (MME-initiated UE Context Release procedure) + * may in principle be adopted. The eNB should ensure + * that no hanging resources remain at the eNB. + */ + mme_send_delete_session_or_enb_ue_context_release(enb_ue); } void s1ap_handle_ue_context_modification_response( @@ -841,7 +828,6 @@ void s1ap_handle_ue_context_release_request( S1AP_Cause_t *Cause = NULL; enb_ue_t *enb_ue = NULL; - mme_ue_t *mme_ue = NULL; ogs_assert(enb); ogs_assert(enb->sock); @@ -909,26 +895,7 @@ void s1ap_handle_ue_context_release_request( break; } - mme_ue = enb_ue->mme_ue; - if (mme_ue) { - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { - ogs_debug(" EMM-Registered"); - rv = mme_send_release_access_bearer_or_ue_context_release( - mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); - } else { - ogs_debug(" NOT EMM-Registered"); - rv = mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); - ogs_assert(rv == OGS_OK); - } - } else { - ogs_debug(" S1 Context Not Associated"); - CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_NO_ACTION, 0); - ogs_assert(rv == OGS_OK); - } + mme_send_release_access_bearer_or_ue_context_release(enb_ue); } void s1ap_handle_ue_context_release_complete( @@ -992,11 +959,11 @@ void s1ap_handle_ue_context_release_complete( enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); switch (enb_ue->ue_ctx_rel_action) { - case S1AP_UE_CTX_REL_NO_ACTION: + case S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE: ogs_debug(" No Action"); enb_ue_remove(enb_ue); break; - case S1AP_UE_CTX_REL_S1_NORMAL_RELEASE: + case S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK: ogs_debug(" Action: S1 normal release"); enb_ue_remove(enb_ue); mme_ue_deassociate(mme_ue); @@ -1629,11 +1596,10 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, ogs_s1ap_message_t *message) ogs_assert(rv == OGS_OK); CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command( + s1ap_send_ue_context_release_command( target_ue, S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system, S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL, 0); - ogs_assert(rv == OGS_OK); } void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message) @@ -1702,12 +1668,11 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message) ogs_assert(rv == OGS_OK); CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release); - rv = s1ap_send_ue_context_release_command( + s1ap_send_ue_context_release_command( target_ue, S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_handover_cancelled, S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL, ogs_time_from_msec(300)); - ogs_assert(rv == OGS_OK); ogs_debug("[MME] Handover Cancel : " "UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]", diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 39b126e9a..0b7fa6e09 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -272,7 +272,7 @@ int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue) return OGS_OK; } -int s1ap_send_ue_context_release_command( +void s1ap_send_ue_context_release_command( enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause, uint8_t action, uint32_t delay) { @@ -320,8 +320,6 @@ int s1ap_send_ue_context_release_command( rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, 0); ogs_assert(rv == OGS_OK); } - - return OGS_OK; } void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) diff --git a/src/mme/s1ap-path.h b/src/mme/s1ap-path.h index bbadb67d0..f2a705baf 100644 --- a/src/mme/s1ap-path.h +++ b/src/mme/s1ap-path.h @@ -50,7 +50,7 @@ int s1ap_send_to_esm(mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf); int s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue); int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue); -int s1ap_send_ue_context_release_command( +void s1ap_send_ue_context_release_command( enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause, uint8_t action, uint32_t delay); diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 4fdbac0a3..f634e6da1 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -32,7 +32,6 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) { ogs_tlv_t *root = NULL, *iter = NULL; mme_ue_t *mme_ue = NULL; - enb_ue_t *enb_ue = NULL; char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; @@ -108,20 +107,16 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) return; error: - enb_ue = mme_ue->enb_ue; - ogs_assert(enb_ue); - nas_send_attach_reject(mme_ue, EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); } void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) { ogs_tlv_t *root = NULL, *iter = NULL; mme_ue_t *mme_ue = NULL; - enb_ue_t *enb_ue = NULL; char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; @@ -180,12 +175,9 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_plmn_id_hexdump(&lai->nas_plmn_id), lai->lac); } - enb_ue = mme_ue->enb_ue; - ogs_assert(enb_ue); - nas_send_attach_reject(mme_ue, emm_cause, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); } void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) diff --git a/src/pgw/pgw-event.h b/src/pgw/pgw-event.h index 82cfc7984..0953dfb6b 100644 --- a/src/pgw/pgw-event.h +++ b/src/pgw/pgw-event.h @@ -26,8 +26,9 @@ extern "C" { #endif -typedef struct pgw_sess_s pgw_sess_t; +typedef struct ogs_gtp_node_s ogs_gtp_node_t; typedef struct ogs_gtp_xact_s ogs_gtp_xact_t; +typedef struct pgw_sess_s pgw_sess_t; typedef enum { PGW_EVT_BASE = OGS_FSM_USER_SIG, @@ -44,11 +45,10 @@ typedef struct pgw_event_s { ogs_pkbuf_t *gtpbuf; ogs_pkbuf_t *gxbuf; - ogs_sock_t *sock; - ogs_sockaddr_t *addr; + ogs_gtp_node_t *gnode; + ogs_gtp_xact_t *xact; pgw_sess_t *sess; - ogs_gtp_xact_t *xact; } pgw_event_t; void pgw_event_init(void); diff --git a/src/pgw/pgw-gtp-path.c b/src/pgw/pgw-gtp-path.c index 63526420c..8aefa30bb 100644 --- a/src/pgw/pgw-gtp-path.c +++ b/src/pgw/pgw-gtp-path.c @@ -91,6 +91,7 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) ssize_t size; ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; + ogs_gtp_node_t *gnode = NULL; ogs_assert(fd != INVALID_SOCKET); @@ -108,20 +109,20 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_trim(pkbuf, size); e = pgw_event_new(PGW_EVT_S5C_MESSAGE); + gnode = ogs_gtp_node_find_by_addr(&pgw_self()->sgw_s5c_list, &from); + if (!gnode) { + gnode = ogs_gtp_node_add_by_addr(&pgw_self()->sgw_s5c_list, &from); + ogs_assert(gnode); + gnode->sock = data; + } ogs_assert(e); + e->gnode = gnode; e->gtpbuf = pkbuf; - e->sock = data; - ogs_assert(e->sock); - e->addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(e->addr); - memcpy(e->addr, &from, sizeof(ogs_sockaddr_t)); - rv = ogs_queue_push(pgw_self()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->gtpbuf); - ogs_free(e->addr); pgw_event_free(e); } } diff --git a/src/pgw/pgw-gx-handler.c b/src/pgw/pgw-gx-handler.c index e5783e78e..4f538f7d7 100644 --- a/src/pgw/pgw-gx-handler.c +++ b/src/pgw/pgw-gx-handler.c @@ -25,6 +25,19 @@ static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message); +static void timeout(ogs_gtp_xact_t *xact, void *data) +{ + pgw_sess_t *sess = data; + uint8_t type = 0; + + ogs_assert(sess); + + type = xact->seq[0].type; + + ogs_debug("GTP Timeout : SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x] " + "Message-Type[%d]", sess->sgw_s5c_teid, sess->pgw_s5c_teid, type); +} + void pgw_gx_handle_cca_initial_request( pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message, ogs_gtp_xact_t *xact, ogs_gtp_create_session_request_t *req) @@ -215,7 +228,8 @@ static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) ogs_assert(rv == OGS_OK); } - xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create( + sess->gnode, &h, pkbuf, timeout, sess); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); @@ -231,7 +245,8 @@ static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) rv = pgw_s5c_build_delete_bearer_request(&pkbuf, h.type, bearer); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf); + xact = ogs_gtp_xact_local_create( + sess->gnode, &h, pkbuf, timeout, sess); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); diff --git a/src/pgw/pgw-s5c-handler.c b/src/pgw/pgw-s5c-handler.c index 3c3bdd396..98bbc6a3d 100644 --- a/src/pgw/pgw-s5c-handler.c +++ b/src/pgw/pgw-s5c-handler.c @@ -23,15 +23,12 @@ #include "pgw-fd-path.h" #include "pgw-s5c-handler.h" -#define SEND_ERROR_MESSAGE(XACT, SESS, TYPE, CAUSE) \ - ogs_gtp_send_error_message( \ - (XACT), ((SESS) ? ((SESS)->sgw_s5c_teid) : 0), (TYPE), (CAUSE)) - void pgw_s5c_handle_create_session_request( pgw_sess_t *sess, ogs_gtp_xact_t *xact, ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req) { int rv; + uint8_t cause_value = 0; ogs_gtp_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid; ogs_gtp_node_t *sgw = NULL; pgw_bearer_t *bearer = NULL; @@ -45,54 +42,7 @@ void pgw_s5c_handle_create_session_request( ogs_debug("[PGW] Create Session Reqeust"); - if (req->imsi.presence == 0) { - ogs_error("No IMSI"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } - if (req->sender_f_teid_for_control_plane.presence == 0) { - ogs_error("No TEID"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } - if (req->bearer_contexts_to_be_created.presence == 0) { - ogs_error("No Bearer"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } - if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) { - ogs_error("No EPS Bearer QoS"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } - if (req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence == 0) { - ogs_error("No TEID"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } - if (req->user_location_information.presence == 0) { - ogs_error("No User Location Inforamtion"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - ogs_pkbuf_free(gtpbuf); - return; - } + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; if (sess) { bearer = pgw_default_bearer_in_sess(sess); @@ -100,9 +50,39 @@ void pgw_s5c_handle_create_session_request( } if (!bearer) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(xact, sess, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->imsi.presence == 0) { + ogs_error("No IMSI"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->sender_f_teid_for_control_plane.presence == 0) { + ogs_error("No TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts_to_be_created.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) { + ogs_error("No EPS Bearer QoS"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence == 0) { + ogs_error("No TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->user_location_information.presence == 0) { + ogs_error("No User Location Inforamtion"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, + OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); + ogs_pkbuf_free(gtpbuf); + return; } /* Set IMSI */ @@ -182,7 +162,7 @@ void pgw_s5c_handle_delete_session_request( if (!sess) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(xact, sess, + ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); ogs_pkbuf_free(gtpbuf); diff --git a/src/pgw/pgw-sm.c b/src/pgw/pgw-sm.c index e85ff29cb..5d6dde580 100644 --- a/src/pgw/pgw-sm.c +++ b/src/pgw/pgw-sm.c @@ -119,20 +119,10 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e) if (sess) { gnode = sess->gnode; ogs_assert(gnode); - } else { - ogs_assert(e->addr); - - gnode = ogs_gtp_node_find_by_addr( - &pgw_self()->sgw_s5c_list, e->addr); - if (!gnode) { - gnode = ogs_gtp_node_add_by_addr( - &pgw_self()->sgw_s5c_list, e->addr); - ogs_assert(gnode); - gnode->sock = e->sock; - } + gnode = e->gnode; + ogs_assert(gnode); } - ogs_free(e->addr); rv = ogs_gtp_xact_receive(gnode, &message->h, &xact); if (rv != OGS_OK) { @@ -146,8 +136,8 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e) if (message->h.teid == 0) { ogs_assert(!sess); sess = pgw_sess_add_by_message(message); - ogs_assert(sess); - OGS_SETUP_GTP_NODE(sess, gnode); + if (sess) + OGS_SETUP_GTP_NODE(sess, gnode); } pgw_s5c_handle_create_session_request( sess, xact, copybuf, &message->create_session_request); diff --git a/src/sgw/sgw-context.c b/src/sgw/sgw-context.c index 5bb2e59a5..b28b5bebf 100644 --- a/src/sgw/sgw-context.c +++ b/src/sgw/sgw-context.c @@ -401,6 +401,9 @@ sgw_ue_t *sgw_ue_add_by_message(ogs_gtp_message_t *message) sgw_ue_t *sgw_ue = NULL; ogs_gtp_create_session_request_t *req = &message->create_session_request; + ogs_assert(message); + + req = &message->create_session_request; if (req->imsi.presence == 0) { ogs_error("No IMSI"); return NULL; @@ -563,6 +566,7 @@ void sgw_sess_remove_all(sgw_ue_t *sgw_ue) { sgw_sess_t *sess = NULL, *next_sess = NULL; + ogs_assert(sgw_ue); ogs_list_for_each_safe(&sgw_ue->sess_list, next_sess, sess) sgw_sess_remove(sess); } @@ -575,8 +579,8 @@ sgw_sess_t* sgw_sess_find_by_teid(uint32_t teid) sgw_sess_t* sgw_sess_find_by_apn(sgw_ue_t *sgw_ue, char *apn) { sgw_sess_t *sess = NULL; + ogs_assert(sgw_ue); - sess = sgw_sess_first(sgw_ue); while (sess) { if (strcmp(sess->pdn.apn, apn) == 0) @@ -680,6 +684,7 @@ sgw_bearer_t *sgw_bearer_find_by_sess_ebi(sgw_sess_t *sess, uint8_t ebi) { sgw_bearer_t *bearer = NULL; + ogs_assert(sess); bearer = sgw_bearer_first(sess); while (bearer) { if (ebi == bearer->ebi) @@ -696,6 +701,7 @@ sgw_bearer_t *sgw_bearer_find_by_ue_ebi(sgw_ue_t *sgw_ue, uint8_t ebi) sgw_sess_t *sess = NULL; sgw_bearer_t *bearer = NULL; + ogs_assert(sgw_ue); sess = sgw_sess_first(sgw_ue); while (sess) { bearer = sgw_bearer_find_by_sess_ebi(sess, ebi); @@ -722,6 +728,7 @@ sgw_bearer_t *sgw_bearer_first(sgw_sess_t *sess) sgw_bearer_t *sgw_bearer_next(sgw_bearer_t *bearer) { + ogs_assert(bearer); return ogs_list_next(bearer); } @@ -812,5 +819,6 @@ sgw_tunnel_t *sgw_tunnel_first(sgw_bearer_t *bearer) sgw_tunnel_t *sgw_tunnel_next(sgw_tunnel_t *tunnel) { + ogs_assert(tunnel); return ogs_list_next(tunnel); } diff --git a/src/sgw/sgw-gtp-path.c b/src/sgw/sgw-gtp-path.c index bade66d88..e0a3b48ba 100644 --- a/src/sgw/sgw-gtp-path.c +++ b/src/sgw/sgw-gtp-path.c @@ -28,10 +28,6 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) sgw_event_t *e = NULL; int rv; ssize_t size; - ogs_gtp_header_t *gtp_h = NULL; -#if 0 - uint32_t teid = 0; -#endif ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; ogs_gtp_node_t *gnode = NULL; @@ -51,13 +47,6 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_trim(pkbuf, size); - gtp_h = (ogs_gtp_header_t *)pkbuf->data; - ogs_assert(gtp_h); - ogs_assert(gtp_h->teid_presence); -#if 0 - teid = ntohl(gtp_h->teid); -#endif - /* * 5.5.2 in spec 29.274 * @@ -90,6 +79,7 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) gnode = ogs_gtp_node_find_by_addr(&sgw_self()->pgw_s5c_list, &from); if (gnode) { e = sgw_event_new(SGW_EVT_S5C_MESSAGE); + ogs_assert(e); e->gnode = gnode; } else { e = sgw_event_new(SGW_EVT_S11_MESSAGE); @@ -100,10 +90,10 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data) ogs_assert(gnode); gnode->sock = data; } + ogs_assert(e); e->gnode = gnode; } - ogs_assert(e); e->pkbuf = pkbuf; rv = ogs_queue_push(sgw_self()->queue, e); diff --git a/src/sgw/sgw-s11-handler.c b/src/sgw/sgw-s11-handler.c index d0c2dd178..90005c6ed 100644 --- a/src/sgw/sgw-s11-handler.c +++ b/src/sgw/sgw-s11-handler.c @@ -22,14 +22,28 @@ #include "sgw-gtp-path.h" #include "sgw-s11-handler.h" -#define SEND_ERROR_MESSAGE(XACT, SGW_UE, TYPE, CAUSE) \ - ogs_gtp_send_error_message( \ - (XACT), ((SGW_UE) ? ((SGW_UE)->mme_s11_teid) : 0), (TYPE), (CAUSE)) +static void timeout(ogs_gtp_xact_t *xact, void *data) +{ + sgw_sess_t *sess = data; + sgw_ue_t *sgw_ue = NULL; + uint8_t type = 0; + + ogs_assert(xact); + ogs_assert(sess); + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + + type = xact->seq[0].type; + + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgw_ue->imsi_bcd, type); +} void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value = 0; uint16_t decoded; ogs_gtp_create_session_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; @@ -52,62 +66,46 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact, ogs_debug("[SGW] Create Session Request"); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; req = &message->create_session_request; - if (req->imsi.presence == 0) { - ogs_error("No IMSI"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->bearer_contexts_to_be_created.presence == 0) { - ogs_error("No Bearer"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->access_point_name.presence == 0) { - ogs_error("No APN"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->sender_f_teid_for_control_plane.presence == 0) { - ogs_error("No Sender F-TEID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->pgw_s5_s8_address_for_control_plane_or_pmip.presence == 0) { - ogs_error("No PGW IP"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->user_location_information.presence == 0) { - ogs_error("No User Location Inforamtion"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } if (!sgw_ue) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->imsi.presence == 0) { + ogs_error("No IMSI"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts_to_be_created.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->access_point_name.presence == 0) { + ogs_error("No APN"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->sender_f_teid_for_control_plane.presence == 0) { + ogs_error("No Sender F-TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->pgw_s5_s8_address_for_control_plane_or_pmip.presence == 0) { + ogs_error("No PGW IP"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->user_location_information.presence == 0) { + ogs_error("No User Location Inforamtion"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); return; } @@ -198,7 +196,8 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact, rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - s5c_xact = ogs_gtp_xact_local_create(sess->gnode, &message->h, pkbuf); + s5c_xact = ogs_gtp_xact_local_create( + sess->gnode, &message->h, pkbuf, timeout, sess); ogs_assert(s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -230,44 +229,47 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact, ogs_debug("[SGW] Modify Bearer Reqeust"); + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + if (req->bearer_contexts_to_be_modified.presence == 0) { ogs_error("No Bearer"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; + cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts_to_be_modified.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) { - ogs_error("No eNB TEID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; + cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (sgw_ue) { + if (sgw_ue && cause.value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { bearer = sgw_bearer_find_by_ue_ebi(sgw_ue, req->bearer_contexts_to_be_modified.eps_bearer_id.u8); ogs_assert(bearer); } + if (!bearer) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) { + ogs_error("No eNB TEID"); + cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, cause.value); return; } rsp = &message.modify_bearer_response; memset(&message, 0, sizeof(ogs_gtp_message_t)); + rsp->cause.presence = 1; + rsp->cause.data = &cause; + rsp->cause.len = sizeof(cause); + s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer); ogs_assert(s1u_tunnel); @@ -358,12 +360,6 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact, /* Reset UE state */ SGW_RESET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - rsp->cause.presence = 1; - rsp->cause.data = &cause; - rsp->cause.len = sizeof(cause); - message.h.type = OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE; message.h.teid = sgw_ue->mme_s11_teid; @@ -381,6 +377,7 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value = 0; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *s5c_xact = NULL; sgw_sess_t *sess = NULL; @@ -391,24 +388,25 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact, ogs_debug("[SGW] Delete Session Reqeust"); + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; req = &message->delete_session_request; - if (req->linked_eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } if (!sgw_ue) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->linked_eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value); return; } - ogs_assert(sgw_ue); sess = sgw_sess_find_by_ebi(sgw_ue, req->linked_eps_bearer_id.u8); ogs_assert(sess); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -422,7 +420,8 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact, rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - s5c_xact = ogs_gtp_xact_local_create(sess->gnode, &message->h, pkbuf); + s5c_xact = ogs_gtp_xact_local_create( + sess->gnode, &message->h, pkbuf, timeout, sess); ogs_assert(s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -435,6 +434,7 @@ void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value; uint16_t decoded; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_node_t *enb = NULL; @@ -450,32 +450,72 @@ void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact, ogs_gtp_uli_t uli; ogs_assert(s11_xact); - ogs_assert(sgw_ue); - ogs_assert(message); s5c_xact = s11_xact->assoc_xact; ogs_assert(s5c_xact); + ogs_assert(message); ogs_debug("[SGW] Cerate Bearer Reqeust"); + if (!sgw_ue) { + sgw_sess_t *sess = NULL; + + ogs_warn("No Context in TEID"); + sess = s11_xact->data; + ogs_assert(sess); + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + } + + rv = ogs_gtp_xact_commit(s11_xact); + ogs_assert(rv == OGS_OK); + req = &message->create_bearer_response; + + if (req->cause.presence) { + ogs_gtp_cause_t *cause = req->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (req->bearer_contexts.cause.presence) { + cause = req->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { ogs_error("No eNB TEID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) { ogs_error("No SGW TEID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->user_location_information.presence == 0) { ogs_error("No User Location Inforamtion"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); return; } @@ -575,6 +615,7 @@ void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *s5c_xact = NULL; sgw_sess_t *sess = NULL; @@ -582,25 +623,72 @@ void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact, ogs_gtp_update_bearer_response_t *req = NULL; ogs_assert(s11_xact); - ogs_assert(sgw_ue); - ogs_assert(message); s5c_xact = s11_xact->assoc_xact; ogs_assert(s5c_xact); + ogs_assert(message); ogs_debug("[SGW] Update Bearer Reqeust"); + if (!sgw_ue) { + sgw_sess_t *sess = NULL; + + ogs_warn("No Context in TEID"); + sess = s11_xact->data; + ogs_assert(sess); + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + } + + rv = ogs_gtp_xact_commit(s11_xact); + ogs_assert(rv == OGS_OK); req = &message->update_bearer_response; + + if (req->cause.presence) { + ogs_gtp_cause_t *cause = req->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (req->bearer_contexts.cause.presence) { + cause = req->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (sgw_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgw_bearer_find_by_ue_ebi( + sgw_ue, req->bearer_contexts.eps_bearer_id.u8); + } + + if (!bearer) { + ogs_error("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value); return; } - bearer = sgw_bearer_find_by_ue_ebi( - sgw_ue, req->bearer_contexts.eps_bearer_id.u8); ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); @@ -627,6 +715,7 @@ void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *s5c_xact = NULL; sgw_sess_t *sess = NULL; @@ -634,26 +723,74 @@ void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact, ogs_gtp_delete_bearer_response_t *req = NULL; ogs_assert(s11_xact); - ogs_assert(sgw_ue); - ogs_assert(message); s5c_xact = s11_xact->assoc_xact; ogs_assert(s5c_xact); + ogs_assert(message); ogs_debug("[SGW] Delete Bearer Response"); + if (!sgw_ue) { + sgw_sess_t *sess = NULL; + + ogs_warn("No Context in TEID"); + sess = s11_xact->data; + ogs_assert(sess); + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + } + + rv = ogs_gtp_xact_commit(s11_xact); + ogs_assert(rv == OGS_OK); + req = &message->delete_bearer_response; + + if (req->cause.presence) { + ogs_gtp_cause_t *cause = req->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (req->bearer_contexts.cause.presence) { + cause = req->bearer_contexts.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (sgw_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + bearer = sgw_bearer_find_by_ue_ebi( + sgw_ue, req->bearer_contexts.eps_bearer_id.u8); + ogs_assert(bearer); + } + + if (!bearer) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value); return; } - bearer = sgw_bearer_find_by_ue_ebi( - sgw_ue, req->bearer_contexts.eps_bearer_id.u8); - ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); @@ -695,17 +832,27 @@ void sgw_s11_handle_release_access_bearers_request(ogs_gtp_xact_t *s11_xact, ogs_debug("[SGW] Release Access Bearers Request"); + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + if (!sgw_ue) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause.value); return; } rsp = &message.release_access_bearers_response; memset(&message, 0, sizeof(ogs_gtp_message_t)); + rsp->cause.presence = 1; + rsp->cause.data = &cause; + rsp->cause.len = sizeof(cause); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); /* Set UE state to S1UE_INACTIVE */ @@ -731,12 +878,6 @@ void sgw_s11_handle_release_access_bearers_request(ogs_gtp_xact_t *s11_xact, sess = sgw_sess_next(sess); } - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - rsp->cause.presence = 1; - rsp->cause.data = &cause; - rsp->cause.len = sizeof(cause); - message.h.type = OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE; message.h.teid = sgw_ue->mme_s11_teid; @@ -788,7 +929,8 @@ void sgw_s11_handle_lo_dldata_notification(sgw_bearer_t *bearer) rv = ogs_gtp_build_msg(&pkbuf, &message); ogs_assert(rv == OGS_OK); - xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &message.h, pkbuf); + xact = ogs_gtp_xact_local_create( + sgw_ue->gnode, &message.h, pkbuf, timeout, sgw_ue); ogs_assert(xact); rv = ogs_gtp_xact_commit(xact); @@ -804,10 +946,16 @@ void sgw_s11_handle_downlink_data_notification_ack( ogs_debug("[SGW] Downlink Data Notification Acknowledge"); + if (!sgw_ue) { + ogs_warn("No context"); + + sgw_ue = s11_xact->data; + ogs_assert(sgw_ue); + } + rv = ogs_gtp_xact_commit(s11_xact); ogs_assert(rv == OGS_OK); - ogs_assert(sgw_ue); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); @@ -840,10 +988,28 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( ogs_debug("[SGW] Create Indirect Data Forwarding Tunnel Request"); + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + if (!sgw_ue) { + ogs_warn("No Context"); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE, + cause.value); + return; + } + rsp = &message.create_indirect_data_forwarding_tunnel_response; memset(&message, 0, sizeof(ogs_gtp_message_t)); - ogs_assert(sgw_ue); + rsp->cause.presence = 1; + rsp->cause.data = &cause; + rsp->cause.len = sizeof(cause); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); @@ -944,15 +1110,13 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( rsp_bearers[i]->presence = 1; rsp_bearers[i]->eps_bearer_id.presence = 1; rsp_bearers[i]->eps_bearer_id.u8 = bearer->ebi; + + rsp_bearers[i]->cause.presence = 1; + rsp_bearers[i]->cause.data = &cause; + rsp_bearers[i]->cause.len = sizeof(cause); } } - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - rsp->cause.presence = 1; - rsp->cause.data = &cause; - rsp->cause.len = sizeof(cause); - message.h.type = OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE; message.h.teid = sgw_ue->mme_s11_teid; @@ -985,10 +1149,28 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request( ogs_debug("[SGW] Delete Indirect Data Forwarding Tunnel Request"); + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + + if (!sgw_ue) { + ogs_warn("No Context"); + cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE, + cause.value); + return; + } + rsp = &message.delete_indirect_data_forwarding_tunnel_response; memset(&message, 0, sizeof(ogs_gtp_message_t)); - ogs_assert(sgw_ue); + rsp->cause.presence = 1; + rsp->cause.data = &cause; + rsp->cause.len = sizeof(cause); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); @@ -1017,12 +1199,6 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request( sess = sgw_sess_next(sess); } - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; - rsp->cause.presence = 1; - rsp->cause.data = &cause; - rsp->cause.len = sizeof(cause); - message.h.type = OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE; message.h.teid = sgw_ue->mme_s11_teid; diff --git a/src/sgw/sgw-s5c-handler.c b/src/sgw/sgw-s5c-handler.c index e1832e930..019f95581 100644 --- a/src/sgw/sgw-s5c-handler.c +++ b/src/sgw/sgw-s5c-handler.c @@ -22,20 +22,28 @@ #include "sgw-gtp-path.h" #include "sgw-s5c-handler.h" -#define SEND_ERROR_MESSAGE(XACT, SGW_UE, TYPE, CAUSE) \ - ogs_gtp_send_error_message( \ - (XACT), ((SGW_UE) ? ((SGW_UE)->mme_s11_teid) : 0), (TYPE), (CAUSE)) +static void timeout(ogs_gtp_xact_t *xact, void *data) +{ + sgw_ue_t *sgw_ue = data; + uint8_t type = 0; + + ogs_assert(xact); + ogs_assert(sgw_ue); + + ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]", + sgw_ue->imsi_bcd, type); +} void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact, - sgw_sess_t *sess, ogs_gtp_message_t *gtp_message) + sgw_sess_t *sess, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value; ogs_gtp_node_t *pgw = NULL; ogs_gtp_xact_t *s11_xact = NULL; sgw_bearer_t *bearer = NULL; sgw_tunnel_t *s1u_tunnel = NULL, *s5u_tunnel = NULL; ogs_gtp_create_session_response_t *rsp = NULL; - ogs_gtp_cause_t *cause = NULL; ogs_pkbuf_t *pkbuf = NULL; sgw_ue_t *sgw_ue = NULL; @@ -48,66 +56,59 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact, ogs_assert(s5c_xact); s11_xact = s5c_xact->assoc_xact; ogs_assert(s11_xact); - ogs_assert(gtp_message); + ogs_assert(message); ogs_debug("[SGW] Create Session Response"); - rsp = >p_message->create_session_response; - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - cause->value); - return; + if (!sess) { + ogs_warn("No Context in TEID"); + sess = s5c_xact->data; + ogs_assert(sess); } - if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. - presence == 0) { - ogs_error("No GTP TEID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_assert(rv == OGS_OK); + + rsp = &message->create_session_response; + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts_created.cause.presence) { + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + } + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) + ogs_warn("Cause[%d] : No Accepted", cause_value); + + if (rsp->bearer_contexts_created.cause.presence == 0) { + ogs_error("No EPS Bearer Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->bearer_contexts_created.presence == 0) { ogs_error("No Bearer"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (rsp->bearer_contexts_created.cause.presence == 0) { - ogs_error("No EPS Bearer Cause"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) { - ogs_error("No GTP TEID"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } - if (sess) { + if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) { bearer = sgw_bearer_find_by_sess_ebi(sess, rsp->bearer_contexts_created.eps_bearer_id.u8); ogs_assert(bearer); @@ -121,9 +122,22 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact, } if (!bearer) { ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. + presence == 0) { + ogs_error("No GTP TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) { + ogs_error("No GTP TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); return; } @@ -185,16 +199,13 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact, rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = len; - rv = ogs_gtp_xact_commit(s5c_xact); + message->h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE; + message->h.teid = sgw_ue->mme_s11_teid; + + rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - gtp_message->h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE; - gtp_message->h.teid = sgw_ue->mme_s11_teid; - - rv = ogs_gtp_build_msg(&pkbuf, gtp_message); - ogs_assert(rv == OGS_OK); - - rv = ogs_gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); + rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf); ogs_assert(rv == OGS_OK); rv = ogs_gtp_xact_commit(s11_xact); @@ -202,45 +213,46 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact, } void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact, - sgw_sess_t *sess, ogs_gtp_message_t *gtp_message) + sgw_sess_t *sess, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value; ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp_delete_session_response_t *rsp = NULL; ogs_pkbuf_t *pkbuf = NULL; - ogs_gtp_cause_t *cause = NULL; sgw_ue_t *sgw_ue = NULL; ogs_assert(s5c_xact); s11_xact = s5c_xact->assoc_xact; ogs_assert(s11_xact); - ogs_assert(gtp_message); + ogs_assert(message); ogs_debug("[SGW] Delete Session Response"); - rsp = >p_message->delete_session_response; - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_MANDATORY_IE_MISSING); - return; - } - cause = rsp->cause.data; - ogs_assert(cause); - if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("No Accept [%d]", cause->value); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - cause->value); - return; + if (!sess) { + ogs_warn("No Context in TEID"); + sess = s5c_xact->data; + ogs_assert(sess); } - if (!sess) { - ogs_warn("No Context"); - SEND_ERROR_MESSAGE(s11_xact, sgw_ue, - OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, - OGS_GTP_CAUSE_CONTEXT_NOT_FOUND); + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_assert(rv == OGS_OK); + + rsp = &message->delete_session_response; + + if (rsp->cause.presence) { + ogs_gtp_cause_t *cause = rsp->cause.data; + ogs_assert(cause); + + cause_value = cause->value; + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0, + OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value); return; } @@ -255,16 +267,13 @@ void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact, sgw_sess_remove(sess); - rv = ogs_gtp_xact_commit(s5c_xact); + message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE; + message->h.teid = sgw_ue->mme_s11_teid; + + rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - gtp_message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE; - gtp_message->h.teid = sgw_ue->mme_s11_teid; - - rv = ogs_gtp_build_msg(&pkbuf, gtp_message); - ogs_assert(rv == OGS_OK); - - rv = ogs_gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); + rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf); ogs_assert(rv == OGS_OK); rv = ogs_gtp_xact_commit(s11_xact); @@ -272,9 +281,10 @@ void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact, } void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact, - sgw_sess_t *sess, ogs_gtp_message_t *gtp_message) + sgw_sess_t *sess, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value = 0; ogs_gtp_node_t *pgw = NULL; ogs_gtp_xact_t *s11_xact = NULL; sgw_bearer_t *bearer = NULL; @@ -287,36 +297,45 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact, ogs_gtp_f_teid_t sgw_s1u_teid; int len; - ogs_assert(sess); - sgw_ue = sess->sgw_ue; - ogs_assert(sgw_ue); ogs_assert(s5c_xact); - ogs_assert(gtp_message); - - req = >p_message->create_bearer_request; + ogs_assert(message); ogs_debug("[SGW] Create Bearer Request"); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); - ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", - sess->sgw_s5c_teid, sess->pgw_s5c_teid); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + req = &message->create_bearer_request; + + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No Linked EBI"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - return; + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; } if (req->bearer_contexts.s5_s8_u_sgw_f_teid.presence == 0) { ogs_error("No GTP TEID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value); return; } + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + bearer = sgw_bearer_add(sess); ogs_assert(bearer); s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer); @@ -324,6 +343,11 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact, s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer); ogs_assert(s5u_tunnel); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); + ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", + sess->sgw_s5c_teid, sess->pgw_s5c_teid); + /* Receive Data Plane(UL) : PGW-S5U */ pgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data; ogs_assert(pgw_s5u_teid); @@ -358,13 +382,14 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact, req->bearer_contexts.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; req->bearer_contexts.s1_u_enodeb_f_teid.len = len; - gtp_message->h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE; - gtp_message->h.teid = sgw_ue->mme_s11_teid; + message->h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE; + message->h.teid = sgw_ue->mme_s11_teid; - rv = ogs_gtp_build_msg(&pkbuf, gtp_message); + rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, >p_message->h, pkbuf); + s11_xact = ogs_gtp_xact_local_create( + sgw_ue->gnode, &message->h, pkbuf, timeout, sess); ogs_assert(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); @@ -374,44 +399,59 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact, } void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact, - sgw_sess_t *sess, ogs_gtp_message_t *gtp_message) + sgw_sess_t *sess, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value = 0; ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp_update_bearer_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; sgw_ue_t *sgw_ue = NULL; - ogs_assert(sess); - sgw_ue = sess->sgw_ue; - ogs_assert(sgw_ue); ogs_assert(s5c_xact); - ogs_assert(gtp_message); + ogs_assert(message); ogs_debug("[SGW] Update Bearer Request"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + req = &message->update_bearer_request; + + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->pgw_s5c_teid); - req = >p_message->update_bearer_request; + message->h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; + message->h.teid = sgw_ue->mme_s11_teid; - if (req->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - return; - } - if (req->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - return; - } - - gtp_message->h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; - gtp_message->h.teid = sgw_ue->mme_s11_teid; - - rv = ogs_gtp_build_msg(&pkbuf, gtp_message); + rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, >p_message->h, pkbuf); + s11_xact = ogs_gtp_xact_local_create( + sgw_ue->gnode, &message->h, pkbuf, timeout, sess); ogs_assert(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); @@ -423,40 +463,56 @@ void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact, } void sgw_s5c_handle_delete_bearer_request(ogs_gtp_xact_t *s5c_xact, - sgw_sess_t *sess, ogs_gtp_message_t *gtp_message) + sgw_sess_t *sess, ogs_gtp_message_t *message) { int rv; + uint8_t cause_value = 0; ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp_delete_bearer_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; sgw_ue_t *sgw_ue = NULL; - ogs_assert(sess); - sgw_ue = sess->sgw_ue; - ogs_assert(sgw_ue); ogs_assert(s5c_xact); - ogs_assert(gtp_message); - - req = >p_message->delete_bearer_request; + ogs_assert(message); ogs_debug("[SGW] Delete Bearer Request"); + + cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED; + req = &message->delete_bearer_request; + + if (!sess) { + ogs_warn("No Context"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (req->linked_eps_bearer_id.presence == 0 && + req->eps_bearer_ids.presence == 0) { + ogs_error("No Linked EBI or EPS Bearer ID"); + cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + sgw_ue = sess->sgw_ue; + ogs_assert(sgw_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->pgw_s5c_teid); - if (req->linked_eps_bearer_id.presence == 0 && - req->eps_bearer_ids.presence == 0) { - ogs_error("No Linked EBI or EPS Bearer ID"); - return; - } - gtp_message->h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE; - gtp_message->h.teid = sgw_ue->mme_s11_teid; + message->h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE; + message->h.teid = sgw_ue->mme_s11_teid; - rv = ogs_gtp_build_msg(&pkbuf, gtp_message); + rv = ogs_gtp_build_msg(&pkbuf, message); ogs_assert(rv == OGS_OK); - s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, >p_message->h, pkbuf); + s11_xact = ogs_gtp_xact_local_create( + sgw_ue->gnode, &message->h, pkbuf, timeout, sess); ogs_assert(s11_xact); ogs_gtp_xact_associate(s5c_xact, s11_xact); diff --git a/src/sgw/sgw-sm.c b/src/sgw/sgw-sm.c index 1e657f717..16c9abf24 100644 --- a/src/sgw/sgw-sm.c +++ b/src/sgw/sgw-sm.c @@ -134,8 +134,7 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e) case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: sgw_s11_handle_create_indirect_data_forwarding_tunnel_request( xact, sgw_ue, - &message. - create_indirect_data_forwarding_tunnel_request); + &message.create_indirect_data_forwarding_tunnel_request); break; case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request( diff --git a/tests/simple/attach-test.c b/tests/simple/attach-test.c index 17ccec45f..23ddae7d8 100644 --- a/tests/simple/attach-test.c +++ b/tests/simple/attach-test.c @@ -301,7 +301,6 @@ static void attach_test1(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); -#if 1 /* IMPLICIT_S1_RELEASE */ /* Send UE Context Release Request */ rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -313,25 +312,6 @@ static void attach_test1(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); ogs_pkbuf_free(recvbuf); -#else /* S1_HOLDING_TIMER */ - /* Send UE Context Release Request */ - rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - rv = testenb_s1ap_send(s1ap, sendbuf); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - - /* Receive UE Context Release Command */ - recvbuf = testenb_s1ap_read(s1ap); - ABTS_PTR_NOTNULL(tc, recvbuf); - ogs_pkbuf_free(recvbuf); - - /* Send UE Context Release Complete */ - rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex+3); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - rv = testenb_s1ap_send(s1ap, sendbuf); - ABTS_INT_EQUAL(tc, OGS_OK, rv); -#endif - /* Send ESM Information Response */ rv = tests1ap_build_esm_information_response(&sendbuf, msgindex+1); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -425,25 +405,6 @@ static void attach_test1(abts_case *tc, void *data) /* eNB disonncect from SGW */ testenb_gtpu_close(gtpu); - return; - -#if IT_WILL_BE_REMOVED -out: - /********** Remove Subscriber in Database */ - doc = BCON_NEW("imsi", BCON_UTF8("001010123456819")); - ABTS_PTR_NOTNULL(tc, doc); - ABTS_TRUE(tc, mongoc_collection_remove(collection, - MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) - bson_destroy(doc); - - mongoc_collection_destroy(collection); - - /* eNB disonncect from MME */ - testenb_s1ap_close(s1ap); - - /* eNB disonncect from SGW */ - testenb_gtpu_close(gtpu); -#endif } /**************************************************************