MME-SGW GTP-C TEID is assigned per-UE
This commit is contained in:
parent
c44dc0a4c4
commit
021e3ee963
|
@ -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,
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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");
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue