MME-SGW GTP-C TEID is assigned per-UE

This commit is contained in:
Sukchan Lee 2017-09-01 21:35:45 +09:00
parent c44dc0a4c4
commit 021e3ee963
18 changed files with 710 additions and 431 deletions

View File

@ -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,

View File

@ -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. */

View File

@ -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;

View File

@ -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(

View File

@ -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 =
&gtp_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(&gtp_message, 0, sizeof(gtp_message_t));

View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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 \

View File

@ -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 = &gtp_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 = &gtp_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)

View File

@ -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);

View File

@ -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 = &gtp_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 = &gtp_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, &gtp_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, &gtp_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 = &gtp_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 = &gtp_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, &gtp_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 = &gtp_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, &gtp_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 = &gtp_message.downlink_data_notification;
memset(&gtp_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, &gtp_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);
}

View File

@ -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__ */

180
src/sgw/sgw_s5c_handler.c Normal file
View File

@ -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 = &gtp_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, &gtp_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 = &gtp_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, &gtp_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");
}

22
src/sgw/sgw_s5c_handler.h Normal file
View File

@ -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__ */

View File

@ -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;