diff --git a/lib/gtp/gtp_xact.h b/lib/gtp/gtp_xact.h index 1ad759462d..47ad6184a4 100644 --- a/lib/gtp/gtp_xact.h +++ b/lib/gtp/gtp_xact.h @@ -46,6 +46,16 @@ typedef struct _gtp_xact_t { c_uint8_t duplicated_rcount; struct _gtp_xact_t *assoc_xact; /**< Associated transaction */ + +#define GTP_XACT_STORE_SESSION(xact, session) \ + do { \ + d_assert((xact), break, "Null param"); \ + d_assert((session), break, "Null param"); \ + ((xact)->sess) = (session); \ + } while(0) + +#define GTP_XACT_RETRIEVE_SESSION(xact) ((xact) ? ((xact)->sess) : NULL) + void *sess; /**< Session Store */ } gtp_xact_t; CORE_DECLARE(status_t) gtp_xact_init(tm_service_t *tm_service, diff --git a/src/mme/emm_handler.c b/src/mme/emm_handler.c index 4db1eaa130..9f0556608c 100644 --- a/src/mme/emm_handler.c +++ b/src/mme/emm_handler.c @@ -30,7 +30,6 @@ static void event_emm_to_esm( nas_esm_header_t *h = NULL; c_uint8_t pti = NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; c_uint8_t ebi = NAS_EPS_BEARER_IDENTITY_UNASSIGNED; - mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; d_assert(mme_ue, return, "Null param"); @@ -53,8 +52,6 @@ static void event_emm_to_esm( if (!sess) sess = mme_sess_add(mme_ue, pti); d_assert(sess, return, "Null param"); - bearer = mme_default_bearer_in_sess(sess); - d_assert(bearer, return, "No Bearer Context"); /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. * When calculating AES_CMAC, we need to use the headroom of the packet. */ diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index d23b110011..2226ac7b10 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -1127,6 +1127,9 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue) list_init(&mme_ue->sess_list); + mme_ue->mme_s11_teid = mme_ue->index; + mme_ue->mme_s11_addr = mme_self()->s11_addr; + /* Create t3413 timer */ mme_ue->t3413 = event_timer(&self.tm_service, MME_EVT_EMM_T3413, self.t3413_value * 1000, mme_ue->index); @@ -1233,6 +1236,11 @@ mme_ue_t* mme_ue_find_by_guti(guti_t *guti) return (mme_ue_t *)hash_get(self.guti_ue_hash, guti, sizeof(guti_t)); } +mme_ue_t* mme_ue_find_by_teid(c_uint32_t teid) +{ + return mme_ue_find(teid); +} + hash_index_t *mme_ue_first() { d_assert(self.imsi_ue_hash, return NULL, "Null param"); @@ -1464,9 +1472,6 @@ mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti) sess->pti = pti; sess->ebi = NEXT_ID(mme_ue->ebi, MIN_EPS_BEARER_ID, MAX_EPS_BEARER_ID); - sess->mme_s11_teid = sess->index; - sess->mme_s11_addr = mme_self()->s11_addr; - list_init(&sess->bearer_list); list_append(&mme_ue->sess_list, sess); @@ -1522,11 +1527,6 @@ mme_sess_t* mme_sess_find(index_t index) return index_find(&mme_sess_pool, index); } -mme_sess_t* mme_sess_find_by_teid(c_uint32_t teid) -{ - return mme_sess_find(teid); -} - mme_sess_t* mme_sess_find_by_pti(mme_ue_t *mme_ue, c_uint8_t pti) { mme_sess_t *sess = NULL; diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index d3de4e4967..ff7aa356c1 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -155,6 +155,14 @@ struct _mme_ue_t { c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1]; guti_t guti; + /* IMPORTANT! + * MME-S11-TEID is same with an index */ + c_uint32_t mme_s11_teid; + c_uint32_t mme_s11_addr; + + c_uint32_t sgw_s11_teid; + c_uint32_t sgw_s11_addr; + /* UE Info */ tai_t tai; e_cgi_t e_cgi; @@ -246,29 +254,17 @@ struct _mme_ue_t { nas_detach_type_t detach_type; }; +#define MME_UE_IN_ATTACH_STATE(mme) \ + ((mme) && mme_sess_first(mme) && \ + (mme_sess_next(mme_sess_first(mme)) == NULL)) typedef struct _mme_sess_t { lnode_t node; /* A node of list_t */ index_t index; /* An index of this node */ fsm_t sm; /* State Machine */ c_uint8_t pti; /* Procedure Trasaction Identity */ - -#define MME_SESSION_IN_ATTACH_STATE(sess) \ - ((sess) && ((sess)->ebi == MIN_EPS_BEARER_ID)) c_uint8_t ebi; /* EPS Bearer ID */ - /* IMPORTANT! - * MME-S11-TEID is same with an index */ - c_uint32_t mme_s11_teid; - c_uint32_t mme_s11_addr; - -#define MME_UE_HAVE_SESSION(mme) \ - ((mme) && (mme_sess_first(mme)) && \ - (((mme_sess_first(mme))->sgw_s11_teid) && \ - ((mme_sess_first(mme))->sgw_s11_addr))) - c_uint32_t sgw_s11_teid; - c_uint32_t sgw_s11_addr; - /* mme_bearer_first(sess) : Default Bearer Context */ list_t bearer_list; @@ -295,6 +291,12 @@ typedef struct _mme_bearer_t { lnode_t node; /* A node of list_t */ index_t index; /* An index of this node */ +#define MME_UE_HAVE_SESSION(mme) \ + ((mme) && (mme_sess_first(mme)) && \ + (mme_default_bearer_in_sess(mme_sess_first(mme))) && \ + ((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_teid) && \ + ((mme_default_bearer_in_sess(mme_sess_first(mme)))->sgw_s1u_addr)) + #define MME_UE_HAVE_DEFAULT_BEARER(mme) \ ((mme) && (mme_sess_first(mme)) && \ (mme_default_bearer_in_sess(mme_sess_first(mme))) && \ @@ -343,6 +345,7 @@ CORE_DECLARE(mme_ue_t*) mme_ue_find(index_t index); CORE_DECLARE(mme_ue_t*) mme_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len); CORE_DECLARE(mme_ue_t*) mme_ue_find_by_imsi_bcd(c_int8_t *imsi_bcd); CORE_DECLARE(mme_ue_t*) mme_ue_find_by_guti(guti_t *guti); +CORE_DECLARE(mme_ue_t*) mme_ue_find_by_teid(c_uint32_t teid); CORE_DECLARE(mme_ue_t*) mme_ue_find_by_message(nas_message_t *message); CORE_DECLARE(status_t) mme_ue_set_imsi( @@ -358,7 +361,6 @@ CORE_DECLARE(mme_sess_t*) mme_sess_add(mme_ue_t *mme_ue, c_uint8_t pti); CORE_DECLARE(status_t ) mme_sess_remove(mme_sess_t *sess); CORE_DECLARE(status_t ) mme_sess_remove_all(mme_ue_t *mme_ue); CORE_DECLARE(mme_sess_t*) mme_sess_find(index_t index); -CORE_DECLARE(mme_sess_t*) mme_sess_find_by_teid(c_uint32_t teid); CORE_DECLARE(mme_sess_t*) mme_sess_find_by_pti( mme_ue_t *mme_ue, c_uint8_t pti); CORE_DECLARE(mme_sess_t*) mme_sess_find_by_ebi( diff --git a/src/mme/mme_s11_build.c b/src/mme/mme_s11_build.c index 743ee31a72..5b43fd9d6b 100644 --- a/src/mme/mme_s11_build.c +++ b/src/mme/mme_s11_build.c @@ -69,8 +69,8 @@ status_t mme_s11_build_create_session_request( memset(&mme_s11_teid, 0, sizeof(gtp_f_teid_t)); mme_s11_teid.ipv4 = 1; mme_s11_teid.interface_type = GTP_F_TEID_S11_MME_GTP_C; - mme_s11_teid.teid = htonl(sess->mme_s11_teid); - mme_s11_teid.ipv4_addr = sess->mme_s11_addr; + mme_s11_teid.teid = htonl(mme_ue->mme_s11_teid); + mme_s11_teid.ipv4_addr = mme_ue->mme_s11_addr; req->sender_f_teid_for_control_plane.presence = 1; req->sender_f_teid_for_control_plane.data = &mme_s11_teid; req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; @@ -260,18 +260,15 @@ status_t mme_s11_build_release_access_bearers_request( } status_t mme_s11_build_downlink_data_notification_ack( - pkbuf_t **pkbuf, c_uint8_t type, mme_sess_t *sess) + pkbuf_t **pkbuf, c_uint8_t type, mme_ue_t *mme_ue) { status_t rv; - mme_ue_t *mme_ue = NULL; gtp_message_t gtp_message; gtp_downlink_data_notification_acknowledge_t *ack = >p_message.downlink_data_notification_acknowledge; gtp_cause_t cause; - d_assert(sess, return CORE_ERROR, "Null param"); - mme_ue = sess->mme_ue; d_assert(mme_ue, return CORE_ERROR, "Null param"); memset(>p_message, 0, sizeof(gtp_message_t)); diff --git a/src/mme/mme_s11_build.h b/src/mme/mme_s11_build.h index c16da054f3..636006f83a 100644 --- a/src/mme/mme_s11_build.h +++ b/src/mme/mme_s11_build.h @@ -16,7 +16,7 @@ CORE_DECLARE(status_t) mme_s11_build_delete_session_request( CORE_DECLARE(status_t) mme_s11_build_release_access_bearers_request( pkbuf_t **pkbuf, c_uint8_t type); CORE_DECLARE(status_t) mme_s11_build_downlink_data_notification_ack( - pkbuf_t **pkbuf, c_uint8_t type, mme_sess_t *sess); + pkbuf_t **pkbuf, c_uint8_t type, mme_ue_t *mme_ue); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/mme/mme_s11_handler.c b/src/mme/mme_s11_handler.c index 80dcf7ebfa..bb05470f67 100644 --- a/src/mme/mme_s11_handler.c +++ b/src/mme/mme_s11_handler.c @@ -19,16 +19,19 @@ void mme_s11_handle_create_session_request(mme_sess_t *sess) gtp_header_t h; pkbuf_t *pkbuf = NULL; gtp_xact_t *xact = NULL; + mme_ue_t *mme_ue = NULL; /* Use round-robin for selecting SGW */ d_assert(sess, return, "Null param"); sess->sgw = mme_sgw_next(sess->sgw); if (!sess->sgw) sess->sgw = mme_sgw_first(); d_assert(sess->sgw, return, "Null param"); + mme_ue = sess->mme_ue; + d_assert(mme_ue, return, "Null param"); memset(&h, 0, sizeof(gtp_header_t)); h.type = GTP_CREATE_SESSION_REQUEST_TYPE; - h.teid = sess->sgw_s11_teid; + h.teid = mme_ue->sgw_s11_teid; rv = mme_s11_build_create_session_request(&pkbuf, h.type, sess); d_assert(rv == CORE_OK, return, @@ -38,22 +41,27 @@ void mme_s11_handle_create_session_request(mme_sess_t *sess) &h, pkbuf); d_assert(xact, return, "Null param"); + GTP_XACT_STORE_SESSION(xact, sess); + rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); } void mme_s11_handle_create_session_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_create_session_response_t *rsp) + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp) { status_t rv; gtp_f_teid_t *sgw_s11_teid = NULL; gtp_f_teid_t *sgw_s1u_teid = NULL; + mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; pdn_t *pdn = NULL; + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); d_assert(rsp, return, "Null param"); + sess = GTP_XACT_RETRIEVE_SESSION(xact); d_assert(sess, return, "Null param"); bearer = mme_default_bearer_in_sess(sess); d_assert(bearer, return, "Null param"); @@ -88,8 +96,8 @@ void mme_s11_handle_create_session_response( /* Receive Control Plane(UL) : SGW-S11 */ sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; - sess->sgw_s11_teid = ntohl(sgw_s11_teid->teid); - sess->sgw_s11_addr = sgw_s11_teid->ipv4_addr; + mme_ue->sgw_s11_teid = ntohl(sgw_s11_teid->teid); + mme_ue->sgw_s11_addr = sgw_s11_teid->ipv4_addr; memcpy(&pdn->paa, rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len); @@ -107,7 +115,7 @@ void mme_s11_handle_create_session_response( bearer->sgw_s1u_addr = sgw_s1u_teid->ipv4_addr; d_trace(3, "[GTP] Create Session Response : " - "MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); @@ -128,7 +136,7 @@ void mme_s11_handle_delete_all_sessions_request_in_ue(mme_ue_t *mme_ue) memset(&h, 0, sizeof(gtp_header_t)); h.type = GTP_DELETE_SESSION_REQUEST_TYPE; - h.teid = sess->sgw_s11_teid; + h.teid = mme_ue->sgw_s11_teid; rv = mme_s11_build_delete_session_request(&s11buf, h.type, sess); d_assert(rv == CORE_OK, return, "S11 build error"); @@ -137,6 +145,8 @@ void mme_s11_handle_delete_all_sessions_request_in_ue(mme_ue_t *mme_ue) mme_self()->s11_sock, (gtp_node_t *)sess->sgw, &h, s11buf); d_assert(xact, return, "Null param"); + GTP_XACT_STORE_SESSION(xact, sess); + rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); @@ -145,10 +155,16 @@ void mme_s11_handle_delete_all_sessions_request_in_ue(mme_ue_t *mme_ue) } void mme_s11_handle_delete_session_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_delete_session_response_t *rsp) + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_session_response_t *rsp) { status_t rv; + mme_sess_t *sess = NULL; + + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); + d_assert(rsp, return, "Null param"); + sess = GTP_XACT_RETRIEVE_SESSION(xact); + d_assert(sess, return, "Null param"); if (rsp->cause.presence == 0) { @@ -157,7 +173,7 @@ void mme_s11_handle_delete_session_response( } d_trace(3, "[GTP] Delete Session Response : " - "MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); mme_sess_remove(sess); @@ -166,25 +182,30 @@ void mme_s11_handle_delete_session_response( } void mme_s11_handle_modify_bearer_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_modify_bearer_response_t *rsp) + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp) { status_t rv; + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); + d_assert(rsp, return, "Null param"); + d_trace(3, "[GTP] Modify Bearer Response : " - "MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); } void mme_s11_handle_release_access_bearers_response( - gtp_xact_t *xact, mme_sess_t *sess, + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_release_access_bearers_response_t *rsp) { status_t rv; + + d_assert(xact, return, "Null param"); + d_assert(mme_ue, return, "Null param"); d_assert(rsp, return, "Null param"); - d_assert(sess, return, "Null param"); if (rsp->cause.presence == 0) { @@ -193,14 +214,14 @@ void mme_s11_handle_release_access_bearers_response( } d_trace(3, "[GTP] Release Access Bearers Response : " - "MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); rv = gtp_xact_commit(xact); d_assert(rv == CORE_OK, return, "xact_commit error"); } void mme_s11_handle_downlink_data_notification( - gtp_xact_t *xact, mme_sess_t *sess, + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_downlink_data_notification_t *noti) { status_t rv; @@ -208,18 +229,18 @@ void mme_s11_handle_downlink_data_notification( pkbuf_t *s11buf = NULL; d_assert(xact, return, "Null param"); - d_assert(sess, return, "Null param"); + d_assert(mme_ue, return, "Null param"); d_assert(noti, return, "Null param"); d_trace(3, "[GTP] Downlink Data Notification : " - "MME[%d] <-- SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] <-- SGW[%d]\n", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); /* Build Downlink data notification ack */ memset(&h, 0, sizeof(gtp_header_t)); h.type = GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE; - h.teid = sess->sgw_s11_teid; + h.teid = mme_ue->sgw_s11_teid; - rv = mme_s11_build_downlink_data_notification_ack(&s11buf, h.type, sess); + rv = mme_s11_build_downlink_data_notification_ack(&s11buf, h.type, mme_ue); d_assert(rv == CORE_OK, return, "S11 build error"); rv = gtp_xact_update_tx(xact, &h, s11buf); diff --git a/src/mme/mme_s11_handler.h b/src/mme/mme_s11_handler.h index c53f077d5d..f66782f139 100644 --- a/src/mme/mme_s11_handler.h +++ b/src/mme/mme_s11_handler.h @@ -11,22 +11,19 @@ extern "C" { CORE_DECLARE(void) mme_s11_handle_create_session_request(mme_sess_t *sess); CORE_DECLARE(void) mme_s11_handle_create_session_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_create_session_response_t *rsp); + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_create_session_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_delete_all_sessions_request_in_ue( mme_ue_t *mme_ue); CORE_DECLARE(void) mme_s11_handle_delete_session_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_delete_session_response_t *rsp); + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_delete_session_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_modify_bearer_response( - gtp_xact_t *xact, mme_sess_t *sess, - gtp_modify_bearer_response_t *rsp); + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_modify_bearer_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_release_access_bearers_response( - gtp_xact_t *xact, mme_sess_t *sess, + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_release_access_bearers_response_t *rsp); CORE_DECLARE(void) mme_s11_handle_downlink_data_notification( - gtp_xact_t *xact, mme_sess_t *sess, + gtp_xact_t *xact, mme_ue_t *mme_ue, gtp_downlink_data_notification_t *noti); #ifdef __cplusplus diff --git a/src/mme/mme_sm.c b/src/mme/mme_sm.c index e823458e26..f10b351446 100644 --- a/src/mme/mme_sm.c +++ b/src/mme/mme_sm.c @@ -267,7 +267,6 @@ void mme_state_operational(fsm_t *s, event_t *e) pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e); gtp_xact_t *xact = NULL; gtp_message_t message; - mme_sess_t *sess = NULL; mme_ue_t *mme_ue = NULL; enb_ue_t *enb_ue = NULL; @@ -279,21 +278,19 @@ void mme_state_operational(fsm_t *s, event_t *e) if (rv != CORE_OK) break; - sess = mme_sess_find_by_teid(message.h.teid); - d_assert(sess, pkbuf_free(pkbuf); break, - "No Session Context(TEID:%d)", message.h.teid); - mme_ue = sess->mme_ue; - d_assert(mme_ue, pkbuf_free(pkbuf);break, "Null param"); + mme_ue = mme_ue_find_by_teid(message.h.teid); + d_assert(mme_ue, pkbuf_free(pkbuf); break, + "No UE Context(TEID:%d)", message.h.teid); enb_ue = mme_ue->enb_ue; - d_assert(enb_ue, break, "Null param"); + d_assert(enb_ue, pkbuf_free(pkbuf);break, "Null param"); switch(message.h.type) { case GTP_CREATE_SESSION_RESPONSE_TYPE: { mme_s11_handle_create_session_response( - xact, sess, &message.create_session_response); - if (MME_SESSION_IN_ATTACH_STATE(sess)) + xact, mme_ue, &message.create_session_response); + if (MME_UE_IN_ATTACH_STATE(mme_ue)) { emm_handle_attach_accept(mme_ue); } @@ -305,12 +302,12 @@ void mme_state_operational(fsm_t *s, event_t *e) } case GTP_MODIFY_BEARER_RESPONSE_TYPE: mme_s11_handle_modify_bearer_response( - xact, sess, &message.modify_bearer_response); + xact, mme_ue, &message.modify_bearer_response); break; case GTP_DELETE_SESSION_RESPONSE_TYPE: { mme_s11_handle_delete_session_response( - xact, sess, &message.delete_session_response); + xact, mme_ue, &message.delete_session_response); if (MME_UE_DETACH_INITIATED(mme_ue)) { @@ -353,7 +350,7 @@ void mme_state_operational(fsm_t *s, event_t *e) case GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: { mme_s11_handle_release_access_bearers_response( - xact, sess, &message.release_access_bearers_response); + xact, mme_ue, &message.release_access_bearers_response); s1ap_handle_release_access_bearers_response(enb_ue); break; @@ -362,7 +359,7 @@ void mme_state_operational(fsm_t *s, event_t *e) case GTP_DOWNLINK_DATA_NOTIFICATION_TYPE: { mme_s11_handle_downlink_data_notification( - xact, sess, &message.downlink_data_notification); + xact, mme_ue, &message.downlink_data_notification); s1ap_handle_paging(mme_ue); /* Start T3413 */ @@ -407,6 +404,7 @@ void mme_state_operational(fsm_t *s, event_t *e) S1ap_CauseNas_authentication_failure, EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + break; } @@ -423,6 +421,7 @@ void mme_state_operational(fsm_t *s, event_t *e) S1ap_CauseNas_unspecified, EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + break; } diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index 4dee6952b5..9422746361 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -419,7 +419,7 @@ void s1ap_handle_initial_context_setup_response( memset(&h, 0, sizeof(gtp_header_t)); h.type = GTP_MODIFY_BEARER_REQUEST_TYPE; - h.teid = sess->sgw_s11_teid; + h.teid = mme_ue->sgw_s11_teid; rv = mme_s11_build_modify_bearer_request(&pkbuf, h.type, bearer); d_assert(rv == CORE_OK, return, "S11 build error"); @@ -474,7 +474,7 @@ void s1ap_handle_ue_context_release_request( memset(&h, 0, sizeof(gtp_header_t)); h.type = GTP_RELEASE_ACCESS_BEARERS_REQUEST_TYPE; - h.teid = sess->sgw_s11_teid; + h.teid = mme_ue->sgw_s11_teid; rv = mme_s11_build_release_access_bearers_request( &pkbuf, h.type); diff --git a/src/sgw/Makefile.am b/src/sgw/Makefile.am index b3266ea0ce..3577645ac9 100644 --- a/src/sgw/Makefile.am +++ b/src/sgw/Makefile.am @@ -4,9 +4,9 @@ noinst_LTLIBRARIES = libsgw.la libsgw_la_SOURCES = \ sgw_event.h sgw_context.h \ - sgw_gtp_path.h sgw_sm.h sgw_handler.h \ + sgw_gtp_path.h sgw_sm.h sgw_s11_handler.h sgw_s5c_handler.h \ sgw_init.c sgw_event.c sgw_context.c \ - sgw_gtp_path.c sgw_sm.c sgw_handler.c + sgw_gtp_path.c sgw_sm.c sgw_s11_handler.c sgw_s5c_handler.c libsgw_la_DEPENDENCIES = \ $(top_srcdir)/lib/core/src/libcore.la \ diff --git a/src/sgw/sgw_context.c b/src/sgw/sgw_context.c index 35fd7344d0..88209587d6 100644 --- a/src/sgw/sgw_context.c +++ b/src/sgw/sgw_context.c @@ -14,6 +14,7 @@ static sgw_context_t self; +index_declare(sgw_ue_pool, sgw_ue_t, MAX_POOL_OF_UE); index_declare(sgw_sess_pool, sgw_sess_t, MAX_POOL_OF_SESS); index_declare(sgw_bearer_pool, sgw_bearer_t, MAX_POOL_OF_BEARER); @@ -26,6 +27,7 @@ status_t sgw_context_init() memset(&self, 0, sizeof(sgw_context_t)); + index_init(&sgw_ue_pool, MAX_POOL_OF_UE); index_init(&sgw_sess_pool, MAX_POOL_OF_SESS); index_init(&sgw_bearer_pool, MAX_POOL_OF_BEARER); @@ -35,7 +37,7 @@ status_t sgw_context_init() list_init(&self.s5c_node.local_list); list_init(&self.s5c_node.remote_list); - self.sess_hash = hash_make(); + self.imsi_ue_hash = hash_make(); context_initialized = 1; @@ -50,20 +52,14 @@ status_t sgw_context_final() gtp_xact_delete_all(&self.s11_node); gtp_xact_delete_all(&self.s5c_node); - sgw_sess_remove_all(); + sgw_ue_remove_all(); - d_assert(self.sess_hash, , "Null param"); - hash_destroy(self.sess_hash); + d_assert(self.imsi_ue_hash, , "Null param"); + hash_destroy(self.imsi_ue_hash); - if (index_size(&sgw_sess_pool) != pool_avail(&sgw_sess_pool)) - d_warn("%d not freed in sgw_sess_pool[%d] in SGW-Context", - index_size(&sgw_sess_pool) - pool_avail(&sgw_sess_pool), - index_size(&sgw_sess_pool)); - d_trace(3, "%d not freed in sgw_sess_pool[%d] in SGW-Context\n", - index_size(&sgw_sess_pool) - pool_avail(&sgw_sess_pool), - index_size(&sgw_sess_pool)); index_final(&sgw_bearer_pool); index_final(&sgw_sess_pool); + index_final(&sgw_ue_pool); context_initialized = 0; @@ -407,8 +403,10 @@ status_t sgw_context_setup_trace_module() { extern int _sgw_sm; d_trace_level(&_sgw_sm, gtp); - extern int _sgw_handler; - d_trace_level(&_sgw_handler, gtp); + extern int _sgw_s11_handler; + d_trace_level(&_sgw_s11_handler, gtp); + extern int _sgw_s11_handler; + d_trace_level(&_sgw_s11_handler, gtp); extern int _gtp_path; d_trace_level(&_gtp_path, gtp); extern int _sgw_path; @@ -435,78 +433,197 @@ status_t sgw_context_setup_trace_module() return CORE_OK; } -static void *sess_hash_keygen(c_uint8_t *out, int *out_len, - c_uint8_t *imsi, int imsi_len, c_int8_t *apn) +sgw_ue_t* sgw_ue_add( + c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi) { - memcpy(out, imsi, imsi_len); - core_cpystrn((char*)(out+imsi_len), apn, MAX_APN_LEN+1); - *out_len = imsi_len+strlen((char*)(out+imsi_len)); + sgw_ue_t *sgw_ue = NULL; + sgw_sess_t *sess = NULL; - return out; + index_alloc(&sgw_ue_pool, &sgw_ue); + d_assert(sgw_ue, return NULL, "Null param"); + + sgw_ue->sgw_s11_teid = sgw_ue->index; + sgw_ue->sgw_s11_addr = sgw_self()->s11_addr; + + /* Set IMSI */ + sgw_ue->imsi_len = imsi_len; + memcpy(sgw_ue->imsi, imsi, sgw_ue->imsi_len); +#if 0 + core_buffer_to_bcd(sgw_ue->imsi, sgw_ue->imsi_len, sgw_ue->imsi_bcd); +#endif + + list_init(&sgw_ue->sess_list); + + sess = sgw_sess_add(sgw_ue, apn, ebi); + d_assert(sess, index_free(&sgw_ue_pool, sgw_ue); return NULL, "Null param"); + + hash_set(self.imsi_ue_hash, sgw_ue->imsi, sgw_ue->imsi_len, sgw_ue); + + return sgw_ue; +} + +status_t sgw_ue_remove(sgw_ue_t *sgw_ue) +{ + d_assert(sgw_ue, return CORE_ERROR, "Null param"); + + /* Clear hash table */ + if (sgw_ue->imsi_len != 0) + hash_set(self.imsi_ue_hash, sgw_ue->imsi, sgw_ue->imsi_len, NULL); + + sgw_sess_remove_all(sgw_ue); + + index_free(&sgw_ue_pool, sgw_ue); + + return CORE_OK; +} + +status_t sgw_ue_remove_all() +{ + hash_index_t *hi = NULL; + sgw_ue_t *sgw_ue = NULL; + + for (hi = sgw_ue_first(); hi; hi = sgw_ue_next(hi)) + { + sgw_ue = sgw_ue_this(hi); + sgw_ue_remove(sgw_ue); + } + + return CORE_OK; +} + +sgw_ue_t* sgw_ue_find(index_t index) +{ + d_assert(index, return NULL, "Invalid index = 0x%x", index); + return index_find(&sgw_ue_pool, index); +} + +sgw_ue_t* sgw_ue_find_by_imsi_bcd(c_int8_t *imsi_bcd) +{ + c_uint8_t imsi[MAX_IMSI_LEN]; + int imsi_len = 0; + + d_assert(imsi_bcd, return NULL,"Invalid param"); + + core_bcd_to_buffer(imsi_bcd, imsi, &imsi_len); + + return sgw_ue_find_by_imsi(imsi, imsi_len); +} + +sgw_ue_t* sgw_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len) +{ + d_assert(imsi && imsi_len, return NULL,"Invalid param"); + + return (sgw_ue_t *)hash_get(self.imsi_ue_hash, imsi, imsi_len); +} + +sgw_ue_t* sgw_ue_find_by_teid(c_uint32_t teid) +{ + return sgw_ue_find(teid); +} + +sgw_ue_t *sgw_ue_find_or_add_by_message(gtp_message_t *gtp_message) +{ + sgw_ue_t *sgw_ue = NULL; + + gtp_create_session_request_t *req = >p_message->create_session_request; + + if (req->sender_f_teid_for_control_plane.presence == 0) + { + d_error("No IMSI"); + return NULL; + } + + if (req->access_point_name.presence == 0) + { + d_error("No APN"); + return NULL; + } + + sgw_ue = sgw_ue_find_by_imsi(req->imsi.data, req->imsi.len); + if (!sgw_ue) + { + c_int8_t apn[MAX_APN_LEN]; + apn_parse(apn, req->access_point_name.data, req->access_point_name.len); + sgw_ue = sgw_ue_add(req->imsi.data, req->imsi.len, apn, + req->bearer_contexts_to_be_created.eps_bearer_id.u8); + d_assert(sgw_ue, return NULL, "No UE Context"); + } + + return sgw_ue; +} + +hash_index_t *sgw_ue_first() +{ + d_assert(self.imsi_ue_hash, return NULL, "Null param"); + return hash_first(self.imsi_ue_hash); +} + +hash_index_t *sgw_ue_next(hash_index_t *hi) +{ + return hash_next(hi); +} + +sgw_ue_t *sgw_ue_this(hash_index_t *hi) +{ + d_assert(hi, return NULL, "Null param"); + return hash_this_val(hi); } sgw_sess_t *sgw_sess_add( - c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t id) + sgw_ue_t *sgw_ue, c_int8_t *apn, c_uint8_t ebi) { sgw_sess_t *sess = NULL; sgw_bearer_t *bearer = NULL; - d_assert(self.sess_hash, return NULL, "Null param"); + d_assert(sgw_ue, return NULL, "Null param"); + d_assert(ebi, return NULL, "Invalid EBI(%d)", ebi); index_alloc(&sgw_sess_pool, &sess); d_assert(sess, return NULL, "Null param"); - sess->sgw_s11_teid = sess->index; /* derived from an index */ - sess->sgw_s11_addr = sgw_self()->s11_addr; - - sess->sgw_s5c_teid = sess->index; /* derived from an index */ + sess->sgw_s5c_teid = sess->index; sess->sgw_s5c_addr = sgw_self()->s5c_addr; - /* Set IMSI */ - sess->imsi_len = imsi_len; - memcpy(sess->imsi, imsi, sess->imsi_len); - core_buffer_to_bcd(sess->imsi, sess->imsi_len, sess->imsi_bcd); - /* Set APN */ core_cpystrn(sess->pdn.apn, apn, MAX_APN_LEN+1); list_init(&sess->bearer_list); + list_append(&sgw_ue->sess_list, sess); - bearer = sgw_bearer_add(sess, id); + sess->sgw_ue = sgw_ue; + + bearer = sgw_bearer_add(sess, ebi); d_assert(bearer, sgw_sess_remove(sess); return NULL, "Can't add default bearer context"); - /* Generate Hash Key : IMSI + APN */ - sess_hash_keygen(sess->hash_keybuf, &sess->hash_keylen, - imsi, imsi_len, apn); - hash_set(self.sess_hash, sess->hash_keybuf, sess->hash_keylen, sess); - return sess; } status_t sgw_sess_remove(sgw_sess_t *sess) { - d_assert(self.sess_hash, return CORE_ERROR, "Null param"); d_assert(sess, return CORE_ERROR, "Null param"); - - hash_set(self.sess_hash, sess->hash_keybuf, sess->hash_keylen, NULL); + d_assert(sess->sgw_ue, return CORE_ERROR, "Null param"); sgw_bearer_remove_all(sess); + list_remove(&sess->sgw_ue->sess_list, sess); index_free(&sgw_sess_pool, sess); return CORE_OK; } -status_t sgw_sess_remove_all() +status_t sgw_sess_remove_all(sgw_ue_t *sgw_ue) { - hash_index_t *hi = NULL; - sgw_sess_t *sess = NULL; - - for (hi = sgw_sess_first(); hi; hi = sgw_sess_next(hi)) + sgw_sess_t *sess = NULL, *next_sess = NULL; + + sess = sgw_sess_first(sgw_ue); + while (sess) { - sess = sgw_sess_this(hi); + next_sess = sgw_sess_next(sess); + sgw_sess_remove(sess); + + sess = next_sess; } return CORE_OK; @@ -523,68 +640,44 @@ sgw_sess_t* sgw_sess_find_by_teid(c_uint32_t teid) return sgw_sess_find(teid); } -sgw_sess_t* sgw_sess_find_by_imsi_apn( - c_uint8_t *imsi, int imsi_len, c_int8_t *apn) -{ - c_uint8_t keybuf[MAX_IMSI_LEN+MAX_APN_LEN+1]; - int keylen = 0; - - d_assert(self.sess_hash, return NULL, "Null param"); - - sess_hash_keygen(keybuf, &keylen, imsi, imsi_len, apn); - return (sgw_sess_t *)hash_get(self.sess_hash, keybuf, keylen); -} - -sgw_sess_t *sgw_sess_find_or_add_by_message(gtp_message_t *gtp_message) +sgw_sess_t* sgw_sess_find_by_apn(sgw_ue_t *sgw_ue, c_int8_t *apn) { sgw_sess_t *sess = NULL; - - gtp_create_session_request_t *req = >p_message->create_session_request; - c_int8_t apn[MAX_APN_LEN]; - - if (req->sender_f_teid_for_control_plane.presence == 0) + + sess = sgw_sess_first(sgw_ue); + while (sess) { - d_error("No IMSI"); - return NULL; + if (strcmp(sess->pdn.apn, apn) == 0) + return sess; + + sess = sgw_sess_next(sess); } - if (req->access_point_name.presence == 0) - { - d_error("No APN"); - return NULL; - } - - apn_parse(apn, req->access_point_name.data, req->access_point_name.len); - sess = sgw_sess_find_by_imsi_apn(req->imsi.data, req->imsi.len, apn); - if (!sess) - { - sess = sgw_sess_add(req->imsi.data, req->imsi.len, apn, - req->bearer_contexts_to_be_created.eps_bearer_id.u8); - d_assert(sess, return NULL, "No Session Context"); - } - - return sess; + return NULL; } -hash_index_t* sgw_sess_first() +sgw_sess_t* sgw_sess_find_by_ebi(sgw_ue_t *sgw_ue, c_uint8_t ebi) { - d_assert(self.sess_hash, return NULL, "Null param"); - return hash_first(self.sess_hash); + sgw_bearer_t *bearer = NULL; + + bearer = sgw_bearer_find_by_ue_ebi(sgw_ue, ebi); + if (bearer) + return bearer->sess; + + return NULL; } -hash_index_t* sgw_sess_next(hash_index_t *hi) +sgw_sess_t* sgw_sess_first(sgw_ue_t *sgw_ue) { - return hash_next(hi); + return list_first(&sgw_ue->sess_list); } -sgw_sess_t *sgw_sess_this(hash_index_t *hi) +sgw_sess_t* sgw_sess_next(sgw_sess_t *sess) { - d_assert(hi, return NULL, "Null param"); - return hash_this_val(hi); + return list_next(sess); } - -sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess, c_uint8_t id) +sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess, c_uint8_t ebi) { sgw_bearer_t *bearer = NULL; @@ -593,7 +686,7 @@ sgw_bearer_t* sgw_bearer_add(sgw_sess_t *sess, c_uint8_t id) index_alloc(&sgw_bearer_pool, &bearer); d_assert(bearer, return NULL, "Bearer context allocation failed"); - bearer->id = id; + bearer->ebi = ebi; bearer->sgw_s1u_teid = bearer->index; bearer->sgw_s1u_addr = sgw_self()->s1u_addr; bearer->sgw_s5u_teid = bearer->index; @@ -659,22 +752,40 @@ sgw_bearer_t* sgw_bearer_find_by_sgw_s1u_teid(c_uint32_t sgw_s1u_teid) return sgw_bearer_find(sgw_s1u_teid); } -sgw_bearer_t* sgw_bearer_find_by_id(sgw_sess_t *sess, c_uint8_t id) +sgw_bearer_t* sgw_bearer_find_by_sess_ebi(sgw_sess_t *sess, c_uint8_t ebi) { sgw_bearer_t *bearer = NULL; - - d_assert(sess, return NULL, "Null param"); - bearer = list_first(&sess->bearer_list); - while (bearer) + bearer = sgw_bearer_first(sess); + while(bearer) { - if (bearer->id == id) - break; + if (ebi == bearer->ebi) + return bearer; - bearer = list_next(bearer); + bearer = sgw_bearer_next(bearer); } - return bearer; + return NULL; +} + +sgw_bearer_t* sgw_bearer_find_by_ue_ebi(sgw_ue_t *sgw_ue, c_uint8_t ebi) +{ + sgw_sess_t *sess = NULL; + sgw_bearer_t *bearer = NULL; + + sess = sgw_sess_first(sgw_ue); + while (sess) + { + bearer = sgw_bearer_find_by_sess_ebi(sess, ebi); + if (bearer) + { + return bearer; + } + + sess = sgw_sess_next(sess); + } + + return NULL; } sgw_bearer_t* sgw_default_bearer_in_sess(sgw_sess_t *sess) diff --git a/src/sgw/sgw_context.h b/src/sgw/sgw_context.h index de5e1d9f9c..6c6373e15f 100644 --- a/src/sgw/sgw_context.h +++ b/src/sgw/sgw_context.h @@ -40,12 +40,17 @@ typedef struct _sgw_context_t { msgq_id queue_id; /* Queue for processing SGW control plane */ tm_service_t tm_service; /* Timer Service */ - hash_t *sess_hash; /* hash table (IMSI+APN) */ + hash_t *imsi_ue_hash; /* hash table (IMSI : SGW_UE) */ } sgw_context_t; -typedef struct _sgw_sess_t { - lnode_t node; /* A node of list_t */ - index_t index; /* An index of this node */ +typedef struct _sgw_ue_t { + lnode_t node; /* A node of list_t */ + index_t index; /* An index of this node */ + + /* UE identity */ + c_uint8_t imsi[MAX_IMSI_LEN]; + int imsi_len; + c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1]; /* IMPORTANT! * SGW-S11-F-TEID is same with an index */ @@ -54,6 +59,13 @@ typedef struct _sgw_sess_t { c_uint32_t mme_s11_teid; /* MME-S11-F-TEID */ c_uint32_t mme_s11_addr; /* MME-S11-F-TEID IPv4 Address */ + list_t sess_list; +} sgw_ue_t; + +typedef struct _sgw_sess_t { + lnode_t node; /* A node of list_t */ + index_t index; /* An index of this node */ + /* IMPORTANT! * SGW-S5C-F-TEID is same with an index */ c_uint32_t sgw_s5c_teid; @@ -61,26 +73,20 @@ typedef struct _sgw_sess_t { c_uint32_t pgw_s5c_teid; /* PGW-S5C-F-TEID */ c_uint32_t pgw_s5c_addr; /* PGW-S5C-F-TEID IPv4 Address */ - /* IMSI */ - c_uint8_t imsi[MAX_IMSI_LEN]; - int imsi_len; - c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1]; - /* APN Configuration */ pdn_t pdn; - /* Hash Key : IMSI+APN */ - c_uint8_t hash_keybuf[MAX_IMSI_LEN+MAX_APN_LEN+1]; - int hash_keylen; - list_t bearer_list; + + /* Related Context */ + sgw_ue_t *sgw_ue; } sgw_sess_t; typedef struct _sgw_bearer_t { lnode_t node; /**< A node of list_t */ index_t index; - c_uint8_t id; + c_uint8_t ebi; /* IMPORTANT! * SGW-S1U-TEID is same with an index */ @@ -125,6 +131,7 @@ CORE_DECLARE(sgw_context_t*) sgw_self(void); CORE_DECLARE(status_t) sgw_context_parse_config(void); CORE_DECLARE(status_t) sgw_context_setup_trace_module(void); +#if 0 CORE_DECLARE(sgw_sess_t*) sgw_sess_add( c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t id); CORE_DECLARE(status_t) sgw_sess_remove(sgw_sess_t *sess); @@ -138,16 +145,48 @@ CORE_DECLARE(sgw_sess_t *) sgw_sess_find_or_add_by_message( CORE_DECLARE(hash_index_t *) sgw_sess_first(); CORE_DECLARE(hash_index_t *) sgw_sess_next(hash_index_t *hi); CORE_DECLARE(sgw_sess_t *) sgw_sess_this(hash_index_t *hi); +#endif -CORE_DECLARE(sgw_bearer_t*) sgw_bearer_add(sgw_sess_t *sess, c_uint8_t id); +CORE_DECLARE(sgw_ue_t*) sgw_ue_add(c_uint8_t *imsi, int imsi_len, + c_int8_t *apn, c_uint8_t id); +CORE_DECLARE(status_t) sgw_ue_remove(sgw_ue_t *sgw_ue); +CORE_DECLARE(status_t) sgw_ue_remove_all(); + +CORE_DECLARE(sgw_ue_t*) sgw_ue_find(index_t index); +CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len); +CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_imsi_bcd(c_int8_t *imsi_bcd); +CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_teid(c_uint32_t teid); +CORE_DECLARE(sgw_ue_t *) sgw_ue_find_or_add_by_message( + gtp_message_t *gtp_message); + +CORE_DECLARE(hash_index_t *) sgw_ue_first(); +CORE_DECLARE(hash_index_t *) sgw_ue_next(hash_index_t *hi); +CORE_DECLARE(sgw_ue_t *) sgw_ue_this(hash_index_t *hi); + +CORE_DECLARE(sgw_sess_t*) sgw_sess_add(sgw_ue_t *sgw_ue, + c_int8_t *apn, c_uint8_t ebi); +CORE_DECLARE(status_t ) sgw_sess_remove(sgw_sess_t *sess); +CORE_DECLARE(status_t ) sgw_sess_remove_all(sgw_ue_t *sgw_ue); +CORE_DECLARE(sgw_sess_t*) sgw_sess_find(index_t index); +CORE_DECLARE(sgw_sess_t*) sgw_sess_find_by_apn( + sgw_ue_t *sgw_ue, c_int8_t *apn); +CORE_DECLARE(sgw_sess_t*) sgw_sess_find_by_ebi( + sgw_ue_t *sgw_ue, c_uint8_t ebi); +CORE_DECLARE(sgw_sess_t*) sgw_sess_find_by_teid(c_uint32_t teid); +CORE_DECLARE(sgw_sess_t*) sgw_sess_first(sgw_ue_t *sgw_ue); +CORE_DECLARE(sgw_sess_t*) sgw_sess_next(sgw_sess_t *sess); + +CORE_DECLARE(sgw_bearer_t*) sgw_bearer_add(sgw_sess_t *sess, c_uint8_t ebi); CORE_DECLARE(status_t) sgw_bearer_remove(sgw_bearer_t *bearer); CORE_DECLARE(status_t) sgw_bearer_remove_all(sgw_sess_t *sess); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sgw_s5u_teid( c_uint32_t sgw_s5u_teid); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sgw_s1u_teid( c_uint32_t sgw_s1u_teid); -CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_id( - sgw_sess_t *sess, c_uint8_t id); +CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_sess_ebi( + sgw_sess_t *sess, c_uint8_t ebi); +CORE_DECLARE(sgw_bearer_t*) sgw_bearer_find_by_ue_ebi( + sgw_ue_t *sgw_ue, c_uint8_t ebi); CORE_DECLARE(sgw_bearer_t*) sgw_default_bearer_in_sess(sgw_sess_t *sess); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_first(sgw_sess_t *sess); CORE_DECLARE(sgw_bearer_t*) sgw_bearer_next(sgw_bearer_t *bearer); diff --git a/src/sgw/sgw_handler.c b/src/sgw/sgw_s11_handler.c similarity index 54% rename from src/sgw/sgw_handler.c rename to src/sgw/sgw_s11_handler.c index 81280475eb..b24024b9e6 100644 --- a/src/sgw/sgw_handler.c +++ b/src/sgw/sgw_s11_handler.c @@ -1,4 +1,4 @@ -#define TRACE_MODULE _sgw_handler +#define TRACE_MODULE _sgw_s11_handler #include "core_debug.h" #include "core_lib.h" @@ -8,10 +8,10 @@ #include "sgw_event.h" #include "sgw_context.h" #include "sgw_gtp_path.h" -#include "sgw_handler.h" +#include "sgw_s11_handler.h" void sgw_handle_create_session_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message) + sgw_ue_t *sgw_ue, gtp_message_t *gtp_message) { status_t rv; gtp_create_session_request_t *req = NULL; @@ -20,13 +20,12 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact, gtp_f_teid_t sgw_s5c_teid, sgw_s5u_teid; gtp_xact_t *s5c_xact = NULL; + sgw_sess_t *sess = NULL; sgw_bearer_t *bearer = NULL; d_assert(s11_xact, return, "Null param"); - d_assert(sess, return, "Null param"); + d_assert(sgw_ue, return, "Null param"); d_assert(gtp_message, return, "Null param"); - bearer = sgw_default_bearer_in_sess(sess); - d_assert(bearer, return, "Null param"); req = >p_message->create_session_request; @@ -45,11 +44,29 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact, d_error("No EPS Bearer ID"); return; } + if (req->access_point_name.presence == 0) + { + d_error("No APN"); + return; + } + + sess = sgw_sess_find_by_ebi(sgw_ue, + req->bearer_contexts_to_be_created.eps_bearer_id.u8); + if (!sess) + { + c_int8_t apn[MAX_APN_LEN]; + apn_parse(apn, req->access_point_name.data, req->access_point_name.len); + sess = sgw_sess_add(sgw_ue, apn, + req->bearer_contexts_to_be_created.eps_bearer_id.u8); + } + d_assert(sess, return, "Null param"); + bearer = sgw_default_bearer_in_sess(sess); + d_assert(bearer, return, "Null param"); /* Receive Control Plane(DL) : MME-S11 */ mme_s11_teid = req->sender_f_teid_for_control_plane.data; - sess->mme_s11_teid = ntohl(mme_s11_teid->teid); - sess->mme_s11_addr = mme_s11_teid->ipv4_addr; + sgw_ue->mme_s11_teid = ntohl(mme_s11_teid->teid); + sgw_ue->mme_s11_addr = mme_s11_teid->ipv4_addr; /* Send Control Plane(DL) : SGW-S5C */ memset(&sgw_s5c_teid, 0, sizeof(gtp_f_teid_t)); @@ -92,109 +109,8 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact, "SGW[%d] --> PGW\n", sess->sgw_s5c_teid); } -void sgw_handle_create_session_response(gtp_xact_t *s5c_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message) -{ - status_t rv; - gtp_xact_t *s11_xact = NULL; - sgw_bearer_t *bearer = NULL; - gtp_create_session_response_t *rsp = NULL; - pkbuf_t *pkbuf = NULL; - - gtp_f_teid_t *pgw_s5c_teid = NULL; - gtp_f_teid_t sgw_s11_teid; - gtp_f_teid_t *pgw_s5u_teid = NULL; - gtp_f_teid_t sgw_s1u_teid; - - d_assert(sess, return, "Null param"); - d_assert(s5c_xact, return, "Null param"); - s11_xact = s5c_xact->assoc_xact; - d_assert(s11_xact, return, "Null param"); - d_assert(gtp_message, return, "Null param"); - - rsp = >p_message->create_session_response; - - if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. - presence == 0) - { - d_error("No GTP TEID"); - return; - } - if (rsp->bearer_contexts_created.presence == 0) - { - d_error("No Bearer"); - return; - } - if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) - { - d_error("No EPS Bearer ID"); - return; - } - if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) - { - d_error("No GTP TEID"); - return; - } - - bearer = sgw_bearer_find_by_id(sess, - rsp->bearer_contexts_created.eps_bearer_id.u8); - d_assert(bearer, sgw_sess_remove(sess); return, "No Bearer Context"); - - /* Receive Control Plane(UL) : PGW-S5C */ - pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. - data; - sess->pgw_s5c_teid = ntohl(pgw_s5c_teid->teid); - sess->pgw_s5c_addr = pgw_s5c_teid->ipv4_addr; - rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. - presence = 0; - - /* Receive Data Plane(UL) : PGW-S5U */ - pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data; - bearer->pgw_s5u_teid = ntohl(pgw_s5u_teid->teid); - bearer->pgw_s5u_addr = pgw_s5u_teid->ipv4_addr; - rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 0; - - /* Send Control Plane(UL) : SGW-S11 */ - memset(&sgw_s11_teid, 0, sizeof(gtp_f_teid_t)); - sgw_s11_teid.ipv4 = 1; - sgw_s11_teid.interface_type = GTP_F_TEID_S11_S4_SGW_GTP_C; - sgw_s11_teid.ipv4_addr = sess->sgw_s11_addr; - sgw_s11_teid.teid = htonl(sess->sgw_s11_teid); - rsp->sender_f_teid_for_control_plane.presence = 1; - rsp->sender_f_teid_for_control_plane.data = &sgw_s11_teid; - rsp->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; - - /* Send Data Plane(UL) : SGW-S1U */ - memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t)); - sgw_s1u_teid.ipv4 = 1; - sgw_s1u_teid.interface_type = GTP_F_TEID_S1_U_SGW_GTP_U; - sgw_s1u_teid.ipv4_addr = bearer->sgw_s1u_addr; - sgw_s1u_teid.teid = htonl(bearer->sgw_s1u_teid); - rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1; - rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; - rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN; - - rv = gtp_xact_commit(s5c_xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); - - gtp_message->h.type = GTP_CREATE_SESSION_RESPONSE_TYPE; - gtp_message->h.teid = sess->mme_s11_teid; - - rv = gtp_build_msg(&pkbuf, gtp_message); - d_assert(rv == CORE_OK, return, "gtp build failed"); - - rv = gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); - d_assert(rv == CORE_OK, return, "gtp_xact_update_tx error"); - - rv = gtp_xact_commit(s11_xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); - - d_trace(3, "[GTP] Create Session Response : " - "SGW[%d] <-- PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); -} - CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_modify_bearer_request_t *req) + sgw_ue_t *sgw_ue, gtp_modify_bearer_request_t *req) { status_t rv; sgw_bearer_t *bearer = NULL; @@ -205,8 +121,9 @@ CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, gtp_cause_t cause; gtp_f_teid_t *enb_s1u_teid = NULL; - d_assert(sess, return, "Null param"); d_assert(s11_xact, return, "Null param"); + d_assert(sgw_ue, return, "Null param"); + d_assert(req, return, "Null param"); if (req->bearer_contexts_to_be_modified.presence == 0) { @@ -224,9 +141,9 @@ CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, return; } - bearer = sgw_bearer_find_by_id(sess, + bearer = sgw_bearer_find_by_ue_ebi(sgw_ue, req->bearer_contexts_to_be_modified.eps_bearer_id.u8); - d_assert(bearer, sgw_sess_remove(sess); return, "No Bearer Context"); + d_assert(bearer, return, "No Bearer Context"); /* Receive Data Plane(DL) : eNB-S1U */ enb_s1u_teid = req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data; @@ -244,7 +161,7 @@ CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, rsp->cause.len = sizeof(cause); gtp_message.h.type = GTP_MODIFY_BEARER_RESPONSE_TYPE; - gtp_message.h.teid = sess->mme_s11_teid; + gtp_message.h.teid = sgw_ue->mme_s11_teid; rv = gtp_build_msg(&pkbuf, >p_message); d_assert(rv == CORE_OK, return, "gtp build failed"); @@ -256,20 +173,34 @@ CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, d_assert(rv == CORE_OK, return, "xact_commit error"); d_trace(3, "[GTP] Modify Bearer Reqeust : " - "MME[%d] --> SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] --> SGW[%d]\n", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); } void sgw_handle_delete_session_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message) + sgw_ue_t *sgw_ue, gtp_message_t *gtp_message) { status_t rv; pkbuf_t *pkbuf = NULL; gtp_xact_t *s5c_xact = NULL; + sgw_sess_t *sess = NULL; + gtp_delete_session_request_t *req = NULL; d_assert(s11_xact, return, "Null param"); - d_assert(sess, return, "Null param"); + d_assert(sgw_ue, return, "Null param"); d_assert(gtp_message, return, "Null param"); + req = >p_message->delete_session_request; + d_assert(req, return, "Null param"); + + if (req->linked_eps_bearer_id.presence == 0) + { + d_error("No EPS Bearer ID"); + return; + } + + sess = sgw_sess_find_by_ebi(sgw_ue, req->linked_eps_bearer_id.u8); + d_assert(sess, return, "Null param"); + gtp_message->h.type = GTP_DELETE_SESSION_REQUEST_TYPE; gtp_message->h.teid = sess->pgw_s5c_teid; @@ -287,98 +218,43 @@ void sgw_handle_delete_session_request(gtp_xact_t *s11_xact, d_assert(rv == CORE_OK, return, "xact_commit error"); d_trace(3, "[GTP] Delete Session Reqeust : " - "SGW[%d] --> PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); -} - -void sgw_handle_delete_session_response(gtp_xact_t *s5c_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message) -{ - status_t rv; - gtp_xact_t *s11_xact = NULL; - gtp_delete_session_response_t *rsp = NULL; - pkbuf_t *pkbuf = NULL; - c_uint32_t mme_s11_teid; - gtp_cause_t *cause = NULL; - - d_assert(sess, return, "Null param"); - d_assert(s5c_xact, return, "Null param"); - s11_xact = s5c_xact->assoc_xact; - d_assert(s11_xact, return, "Null param"); - d_assert(gtp_message, return, "Null param"); - - rsp = >p_message->delete_session_response; - - if (rsp->cause.presence == 0) - { - d_error("No Cause"); - return; - } - - cause = rsp->cause.data; - d_assert(cause, return, "Null param"); - - /* Remove a pgw session */ - if (sess) - { - d_trace(3, "[GTP] Delete Session Response : " - "SGW[%d] --> PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); - - /* backup sgw_s5c_teid in session context */ - mme_s11_teid = sess->mme_s11_teid; - - if (sgw_sess_remove(sess) != CORE_OK) - { - d_error("Error on PGW session %d removal", sess->index); - cause->value = GTP_CAUSE_CONTEXT_NOT_FOUND; - } - } - else - { - cause->value = GTP_CAUSE_INVALID_PEER; - } - - rv = gtp_xact_commit(s5c_xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); - - gtp_message->h.type = GTP_DELETE_SESSION_RESPONSE_TYPE; - gtp_message->h.teid = mme_s11_teid; - - rv = gtp_build_msg(&pkbuf, gtp_message); - d_assert(rv == CORE_OK, return, "gtp build failed"); - - rv = gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); - d_assert(rv == CORE_OK, return, "gtp_xact_update_tx error"); - - rv = gtp_xact_commit(s11_xact); - d_assert(rv == CORE_OK, return, "xact_commit error"); + "SGW[%d] --> PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); } void sgw_handle_release_access_bearers_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_release_access_bearers_request_t *req) + sgw_ue_t *sgw_ue, gtp_release_access_bearers_request_t *req) { status_t rv; gtp_release_access_bearers_response_t *rsp = NULL; pkbuf_t *pkbuf = NULL; gtp_message_t gtp_message; sgw_bearer_t *bearer = NULL, *next_bearer = NULL; + sgw_sess_t *sess = NULL; gtp_cause_t cause; - d_assert(sess, return, "Null param"); + d_assert(sgw_ue, return, "Null param"); d_assert(s11_xact, return, "Null param"); + d_assert(req, return, "Null param"); /* Release S1U(DL) path */ - bearer = list_first(&sess->bearer_list); - while (bearer) + sess = sgw_sess_first(sgw_ue); + while (sess) { - next_bearer = list_next(bearer); + bearer = list_first(&sess->bearer_list); + while (bearer) + { + next_bearer = list_next(bearer); - bearer->enb_s1u_teid = 0; - bearer->enb_s1u_addr = 0; + bearer->enb_s1u_teid = 0; + bearer->enb_s1u_addr = 0; - RESET_DL_NOTI_SENT(bearer); + RESET_DL_NOTI_SENT(bearer); - bearer = next_bearer; + bearer = next_bearer; + } + + sess = sgw_sess_next(sess); } rsp = >p_message.release_access_bearers_response; @@ -392,7 +268,7 @@ void sgw_handle_release_access_bearers_request(gtp_xact_t *s11_xact, rsp->cause.len = sizeof(cause); gtp_message.h.type = GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE; - gtp_message.h.teid = sess->mme_s11_teid; + gtp_message.h.teid = sgw_ue->mme_s11_teid; rv = gtp_build_msg(&pkbuf, >p_message); d_assert(rv == CORE_OK, return, "gtp build failed"); @@ -404,7 +280,7 @@ void sgw_handle_release_access_bearers_request(gtp_xact_t *s11_xact, d_assert(rv == CORE_OK, return, "xact_commit error"); d_trace(3, "[GTP] Release Access Bearers Reqeust : " - "MME[%d] --> SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] --> SGW[%d]\n", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); } void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer) @@ -413,6 +289,7 @@ void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer) gtp_downlink_data_notification_t *noti = NULL; pkbuf_t *pkbuf = NULL; gtp_message_t gtp_message; + sgw_ue_t *sgw_ue = NULL; sgw_sess_t *sess = NULL; gtp_xact_t *xact = NULL; /* FIXME : ARP should be retrieved from ? */ @@ -422,13 +299,15 @@ void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer) sess = bearer->sess; d_assert(sess, return, "Null param"); + sgw_ue = sess->sgw_ue; + d_assert(sgw_ue, return, "Null param"); /* Build downlink notification message */ noti = >p_message.downlink_data_notification; memset(>p_message, 0, sizeof(gtp_message_t)); noti->eps_bearer_id.presence = 1; - noti->eps_bearer_id.u8 = bearer->id; + noti->eps_bearer_id.u8 = bearer->ebi; /* FIXME : ARP should be retrieved from ? */ noti->allocation_retention_priority.presence = 1; @@ -436,7 +315,7 @@ void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer) noti->allocation_retention_priority.len = sizeof(arp); gtp_message.h.type = GTP_DOWNLINK_DATA_NOTIFICATION_TYPE; - gtp_message.h.teid = sess->mme_s11_teid; + gtp_message.h.teid = sgw_ue->mme_s11_teid; rv = gtp_build_msg(&pkbuf, >p_message); d_assert(rv == CORE_OK, return, "gtp build failed"); @@ -449,12 +328,12 @@ void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer) d_assert(rv == CORE_OK, return, "xact_commit error"); d_trace(3, "[GTP] Downlink Data Notification : " - "SGW[%d] --> MME[%d]\n", sess->sgw_s11_teid, sess->mme_s11_teid); + "SGW[%d] --> MME[%d]\n", sgw_ue->sgw_s11_teid, sgw_ue->mme_s11_teid); } -void sgw_handle_downlink_data_notification_ack(sgw_sess_t *sess, +void sgw_handle_downlink_data_notification_ack(sgw_ue_t *sgw_ue, gtp_downlink_data_notification_acknowledge_t *ack) { d_trace(3, "[GTP] Downlink Data Notification Ack: " - "MME[%d] --> SGW[%d]\n", sess->mme_s11_teid, sess->sgw_s11_teid); + "MME[%d] --> SGW[%d]\n", sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); } diff --git a/src/sgw/sgw_handler.h b/src/sgw/sgw_s11_handler.h similarity index 54% rename from src/sgw/sgw_handler.h rename to src/sgw/sgw_s11_handler.h index ccfbf0ad3b..3e94c4d8d2 100644 --- a/src/sgw/sgw_handler.h +++ b/src/sgw/sgw_s11_handler.h @@ -1,5 +1,5 @@ -#ifndef __SGW_HANDLER_H__ -#define __SGW_HANDLER_H__ +#ifndef __SGW_S11_HANDLER_H__ +#define __SGW_S11_HANDLER_H__ #include "gtp_message.h" @@ -10,29 +10,24 @@ extern "C" { #endif /* __cplusplus */ CORE_DECLARE(void) sgw_handle_create_session_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message); - -CORE_DECLARE(void) sgw_handle_create_session_response(gtp_xact_t *s5c_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message); + sgw_ue_t *sgw_ue, gtp_message_t *gtp_message); CORE_DECLARE(void) sgw_handle_modify_bearer_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_modify_bearer_request_t *req); + sgw_ue_t *sgw_ue, gtp_modify_bearer_request_t *req); CORE_DECLARE(void) sgw_handle_delete_session_request(gtp_xact_t *s11_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message); -CORE_DECLARE(void) sgw_handle_delete_session_response(gtp_xact_t *s5c_xact, - sgw_sess_t *sess, gtp_message_t *gtp_message); + sgw_ue_t *sgw_ue, gtp_message_t *gtp_message); CORE_DECLARE(void) sgw_handle_release_access_bearers_request( - gtp_xact_t *s11_xact, sgw_sess_t *sess, + gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue, gtp_release_access_bearers_request_t *req); CORE_DECLARE(void) sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer); -CORE_DECLARE(void) sgw_handle_downlink_data_notification_ack(sgw_sess_t *sess, +CORE_DECLARE(void) sgw_handle_downlink_data_notification_ack(sgw_ue_t *sgw_ue, gtp_downlink_data_notification_acknowledge_t *ack); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* __SGW_HANDLER_H__ */ +#endif /* __SGW_S11_HANDLER_H__ */ diff --git a/src/sgw/sgw_s5c_handler.c b/src/sgw/sgw_s5c_handler.c new file mode 100644 index 0000000000..e920ac4b0c --- /dev/null +++ b/src/sgw/sgw_s5c_handler.c @@ -0,0 +1,180 @@ +#define TRACE_MODULE _sgw_s5c_handler + +#include "core_debug.h" +#include "core_lib.h" + +#include "gtp_types.h" + +#include "sgw_event.h" +#include "sgw_context.h" +#include "sgw_gtp_path.h" +#include "sgw_s5c_handler.h" + +void sgw_handle_create_session_response(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message) +{ + status_t rv; + gtp_xact_t *s11_xact = NULL; + sgw_bearer_t *bearer = NULL; + gtp_create_session_response_t *rsp = NULL; + pkbuf_t *pkbuf = NULL; + sgw_ue_t *sgw_ue = NULL; + + gtp_f_teid_t *pgw_s5c_teid = NULL; + gtp_f_teid_t sgw_s11_teid; + gtp_f_teid_t *pgw_s5u_teid = NULL; + gtp_f_teid_t sgw_s1u_teid; + + d_assert(sess, return, "Null param"); + sgw_ue = sess->sgw_ue; + d_assert(sgw_ue, return, "Null param"); + d_assert(s5c_xact, return, "Null param"); + s11_xact = s5c_xact->assoc_xact; + d_assert(s11_xact, return, "Null param"); + d_assert(gtp_message, return, "Null param"); + + rsp = >p_message->create_session_response; + + if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. + presence == 0) + { + d_error("No GTP TEID"); + return; + } + if (rsp->bearer_contexts_created.presence == 0) + { + d_error("No Bearer"); + return; + } + if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) + { + d_error("No EPS Bearer ID"); + return; + } + if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) + { + d_error("No GTP TEID"); + return; + } + + bearer = sgw_bearer_find_by_sess_ebi(sess, + rsp->bearer_contexts_created.eps_bearer_id.u8); + d_assert(bearer, return, "No Bearer Context"); + + /* Receive Control Plane(UL) : PGW-S5C */ + pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. + data; + sess->pgw_s5c_teid = ntohl(pgw_s5c_teid->teid); + sess->pgw_s5c_addr = pgw_s5c_teid->ipv4_addr; + rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. + presence = 0; + + /* Receive Data Plane(UL) : PGW-S5U */ + pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data; + bearer->pgw_s5u_teid = ntohl(pgw_s5u_teid->teid); + bearer->pgw_s5u_addr = pgw_s5u_teid->ipv4_addr; + rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 0; + + /* Send Control Plane(UL) : SGW-S11 */ + memset(&sgw_s11_teid, 0, sizeof(gtp_f_teid_t)); + sgw_s11_teid.ipv4 = 1; + sgw_s11_teid.interface_type = GTP_F_TEID_S11_S4_SGW_GTP_C; + sgw_s11_teid.ipv4_addr = sgw_ue->sgw_s11_addr; + sgw_s11_teid.teid = htonl(sgw_ue->sgw_s11_teid); + rsp->sender_f_teid_for_control_plane.presence = 1; + rsp->sender_f_teid_for_control_plane.data = &sgw_s11_teid; + rsp->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; + + /* Send Data Plane(UL) : SGW-S1U */ + memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t)); + sgw_s1u_teid.ipv4 = 1; + sgw_s1u_teid.interface_type = GTP_F_TEID_S1_U_SGW_GTP_U; + sgw_s1u_teid.ipv4_addr = bearer->sgw_s1u_addr; + sgw_s1u_teid.teid = htonl(bearer->sgw_s1u_teid); + rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1; + rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid; + rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN; + + rv = gtp_xact_commit(s5c_xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + + gtp_message->h.type = GTP_CREATE_SESSION_RESPONSE_TYPE; + gtp_message->h.teid = sgw_ue->mme_s11_teid; + + rv = gtp_build_msg(&pkbuf, gtp_message); + d_assert(rv == CORE_OK, return, "gtp build failed"); + + rv = gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); + d_assert(rv == CORE_OK, return, "gtp_xact_update_tx error"); + + rv = gtp_xact_commit(s11_xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + + d_trace(3, "[GTP] Create Session Response : " + "SGW[%d] <-- PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); +} + +void sgw_handle_delete_session_response(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message) +{ + status_t rv; + gtp_xact_t *s11_xact = NULL; + gtp_delete_session_response_t *rsp = NULL; + pkbuf_t *pkbuf = NULL; + c_uint32_t mme_s11_teid; + gtp_cause_t *cause = NULL; + sgw_ue_t *sgw_ue = NULL; + + d_assert(sess, return, "Null param"); + sgw_ue = sess->sgw_ue; + d_assert(s5c_xact, return, "Null param"); + s11_xact = s5c_xact->assoc_xact; + d_assert(s11_xact, return, "Null param"); + d_assert(gtp_message, return, "Null param"); + + rsp = >p_message->delete_session_response; + + if (rsp->cause.presence == 0) + { + d_error("No Cause"); + return; + } + + cause = rsp->cause.data; + d_assert(cause, return, "Null param"); + + /* Remove a pgw session */ + if (sess) + { + d_trace(3, "[GTP] Delete Session Response : " + "SGW[%d] --> PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid); + + /* backup sgw_s5c_teid in session context */ + mme_s11_teid = sgw_ue->mme_s11_teid; + + if (sgw_sess_remove(sess) != CORE_OK) + { + d_error("Error on PGW session %d removal", sess->index); + cause->value = GTP_CAUSE_CONTEXT_NOT_FOUND; + } + } + else + { + cause->value = GTP_CAUSE_INVALID_PEER; + } + + rv = gtp_xact_commit(s5c_xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); + + gtp_message->h.type = GTP_DELETE_SESSION_RESPONSE_TYPE; + gtp_message->h.teid = mme_s11_teid; + + rv = gtp_build_msg(&pkbuf, gtp_message); + d_assert(rv == CORE_OK, return, "gtp build failed"); + + rv = gtp_xact_update_tx(s11_xact, >p_message->h, pkbuf); + d_assert(rv == CORE_OK, return, "gtp_xact_update_tx error"); + + rv = gtp_xact_commit(s11_xact); + d_assert(rv == CORE_OK, return, "xact_commit error"); +} diff --git a/src/sgw/sgw_s5c_handler.h b/src/sgw/sgw_s5c_handler.h new file mode 100644 index 0000000000..f082f87a8e --- /dev/null +++ b/src/sgw/sgw_s5c_handler.h @@ -0,0 +1,22 @@ +#ifndef __SGW_S5C_HANDLER_H__ +#define __SGW_S5C_HANDLER_H__ + +#include "gtp_message.h" + +#include "sgw_context.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +CORE_DECLARE(void) sgw_handle_create_session_response(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message); + +CORE_DECLARE(void) sgw_handle_delete_session_response(gtp_xact_t *s5c_xact, + sgw_sess_t *sess, gtp_message_t *gtp_message); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SGW_S5C_HANDLER_H__ */ diff --git a/src/sgw/sgw_sm.c b/src/sgw/sgw_sm.c index fd3370bd93..4e0b6232e2 100644 --- a/src/sgw/sgw_sm.c +++ b/src/sgw/sgw_sm.c @@ -4,7 +4,8 @@ #include "sgw_context.h" #include "sgw_event.h" #include "sgw_gtp_path.h" -#include "sgw_handler.h" +#include "sgw_s11_handler.h" +#include "sgw_s5c_handler.h" void sgw_state_initial(fsm_t *s, event_t *e) { @@ -53,6 +54,56 @@ void sgw_state_operational(fsm_t *s, event_t *e) break; } case SGW_EVT_S11_MESSAGE: + { + status_t rv; + net_sock_t *sock = (net_sock_t *)event_get_param1(e); + gtp_node_t *gnode = (gtp_node_t *)event_get_param2(e); + pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e); + gtp_xact_t *xact = NULL; + gtp_message_t message; + sgw_ue_t *sgw_ue = NULL; + + d_assert(pkbuf, break, "Null param"); + d_assert(sock, pkbuf_free(pkbuf); break, "Null param"); + d_assert(gnode, pkbuf_free(pkbuf); break, "Null param"); + + rv = gtp_xact_receive(sock, gnode, pkbuf, &xact, &message); + if (rv != CORE_OK) + break; + + if (message.h.type == GTP_CREATE_SESSION_REQUEST_TYPE) + sgw_ue = sgw_ue_find_or_add_by_message(&message); + else + sgw_ue = sgw_ue_find_by_teid(message.h.teid); + d_assert(sgw_ue, pkbuf_free(pkbuf); break, "No Session Context"); + + switch(message.h.type) + { + case GTP_CREATE_SESSION_REQUEST_TYPE: + sgw_handle_create_session_request(xact, sgw_ue, &message); + break; + case GTP_MODIFY_BEARER_REQUEST_TYPE: + sgw_handle_modify_bearer_request(xact, sgw_ue, + &message.modify_bearer_request); + break; + case GTP_DELETE_SESSION_REQUEST_TYPE: + sgw_handle_delete_session_request(xact, sgw_ue, &message); + break; + case GTP_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: + sgw_handle_release_access_bearers_request(xact, sgw_ue, + &message.release_access_bearers_request); + break; + case GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE: + sgw_handle_downlink_data_notification_ack(sgw_ue, + &message.downlink_data_notification_acknowledge); + break; + default: + d_warn("Not implmeneted(type:%d)", message.h.type); + break; + } + pkbuf_free(pkbuf); + break; + } case SGW_EVT_S5C_MESSAGE: { status_t rv; @@ -71,38 +122,17 @@ void sgw_state_operational(fsm_t *s, event_t *e) if (rv != CORE_OK) break; - if (message.h.type == GTP_CREATE_SESSION_REQUEST_TYPE) - sess = sgw_sess_find_or_add_by_message(&message); - else - sess = sgw_sess_find_by_teid(message.h.teid); + sess = sgw_sess_find_by_teid(message.h.teid); d_assert(sess, pkbuf_free(pkbuf); break, "No Session Context"); switch(message.h.type) { - case GTP_CREATE_SESSION_REQUEST_TYPE: - sgw_handle_create_session_request(xact, sess, &message); - break; case GTP_CREATE_SESSION_RESPONSE_TYPE: sgw_handle_create_session_response(xact, sess, &message); break; - case GTP_MODIFY_BEARER_REQUEST_TYPE: - sgw_handle_modify_bearer_request(xact, sess, - &message.modify_bearer_request); - break; - case GTP_DELETE_SESSION_REQUEST_TYPE: - sgw_handle_delete_session_request(xact, sess, &message); - break; case GTP_DELETE_SESSION_RESPONSE_TYPE: sgw_handle_delete_session_response(xact, sess, &message); break; - case GTP_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: - sgw_handle_release_access_bearers_request(xact, sess, - &message.release_access_bearers_request); - break; - case GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE: - sgw_handle_downlink_data_notification_ack(sess, - &message.downlink_data_notification_acknowledge); - break; default: d_warn("Not implmeneted(type:%d)", message.h.type); break;