[#258] All GTP message is fixed not to crash

This commit is contained in:
Sukchan Lee 2019-11-15 23:56:55 +09:00
parent ad7fc34fa2
commit c8bcfffe2e
30 changed files with 1002 additions and 717 deletions

View File

@ -242,6 +242,24 @@ void ogs_gtp_send_error_message(
case OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
tlv = &errmsg.release_access_bearers_response.cause;
break;
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE:
tlv = &errmsg.downlink_data_notification_acknowledge.cause;
break;
case OGS_GTP_CREATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.create_bearer_response.cause;
break;
case OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.update_bearer_response.cause;
break;
case OGS_GTP_DELETE_BEARER_RESPONSE_TYPE:
tlv = &errmsg.delete_bearer_response.cause;
break;
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.create_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.delete_indirect_data_forwarding_tunnel_response.cause;
break;
default:
ogs_assert_if_reached();
return;

View File

@ -72,8 +72,9 @@ int ogs_gtp_xact_final(void)
return OGS_OK;
}
ogs_gtp_xact_t *ogs_gtp_xact_local_create(
ogs_gtp_node_t *gnode, ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf)
ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode,
ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf,
void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data)
{
int rv;
char buf[OGS_ADDRSTRLEN];
@ -89,6 +90,8 @@ ogs_gtp_xact_t *ogs_gtp_xact_local_create(
xact->org = OGS_GTP_LOCAL_ORIGINATOR;
xact->xid = OGS_NEXT_ID(g_xact_id, GTP_MIN_XACT_ID, GTP_MAX_XACT_ID);
xact->gnode = gnode;
xact->cb = cb;
xact->data = data;
xact->tm_response = ogs_timer_add(g_timer_mgr, response_timeout, xact);
ogs_assert(xact->tm_response);
@ -513,6 +516,10 @@ static void response_timeout(void *data)
xact->step, xact->seq[xact->step-1].type,
OGS_ADDR(&xact->gnode->remote_addr, buf),
OGS_PORT(&xact->gnode->remote_addr));
if (xact->cb)
xact->cb(xact, xact->data);
ogs_gtp_xact_delete(xact);
}

View File

@ -43,6 +43,9 @@ typedef struct ogs_gtp_xact_s {
uint32_t xid; /**< Transaction ID */
ogs_gtp_node_t *gnode; /**< Relevant GTP node context */
void (*cb)(ogs_gtp_xact_t *, void *); /**< Local timer expiration handler */
void *data; /**< Transaction Data */
int step; /**< Current step in the sequence.
1 : Initial
2 : Triggered
@ -58,23 +61,14 @@ typedef struct ogs_gtp_xact_s {
uint8_t holding_rcount;
struct ogs_gtp_xact_s *assoc_xact; /**< Associated transaction */
#define OGS_GTP_XACT_STORE_SESSION(xact, session) \
do { \
ogs_assert((xact)); \
ogs_assert((session)); \
((xact)->sess) = (session); \
} while(0)
#define OGS_GTP_XACT_RETRIEVE_SESSION(xact) ((xact) ? ((xact)->sess) : NULL)
void *sess; /**< Session Store */
} ogs_gtp_xact_t;
int ogs_gtp_xact_init(ogs_timer_mgr_t *timer_mgr, int size);
int ogs_gtp_xact_final(void);
ogs_gtp_xact_t *ogs_gtp_xact_local_create(
ogs_gtp_node_t *gnode, ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf);
ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode,
ogs_gtp_header_t *hdesc, ogs_pkbuf_t *pkbuf,
void (*cb)(ogs_gtp_xact_t *xact, void *data), void *data);
ogs_gtp_xact_t *ogs_gtp_xact_remote_create(
ogs_gtp_node_t *gnode, uint32_t sqn);
void ogs_gtp_xact_delete_all(ogs_gtp_node_t *gnode);

View File

@ -246,8 +246,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
rv = sgsap_send_detach_indication(mme_ue);
} else {
rv = mme_send_delete_session_or_detach(mme_ue);
ogs_assert(rv == OGS_OK);
mme_send_delete_session_or_detach(mme_ue);
}
OGS_FSM_TRAN(s, &emm_state_de_registered);
@ -347,8 +346,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
OGS_FSM_TRAN(s, &emm_state_initial_context_setup);
} else {
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
rv = mme_gtp_send_delete_all_sessions(mme_ue);
ogs_assert(rv == OGS_OK);
mme_gtp_send_delete_all_sessions(mme_ue);
} else {
mme_s6a_send_air(mme_ue, NULL);
}
@ -384,9 +382,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_assert(rv == OGS_OK);
rv = mme_send_release_access_bearer_or_ue_context_release(
mme_ue, enb_ue);
ogs_assert(rv == OGS_OK);
mme_send_release_access_bearer_or_ue_context_release(enb_ue);
}
} else if (procedureCode == S1AP_ProcedureCode_id_uplinkNASTransport) {
ogs_debug(" Uplink NAS Transport");
@ -620,9 +616,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
return;
}
rv = mme_send_delete_session_or_detach(mme_ue);
ogs_assert(rv == OGS_OK);
mme_send_delete_session_or_detach(mme_ue);
OGS_FSM_TRAN(s, &emm_state_de_registered);
break;
default:
@ -784,9 +778,7 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
break;
}
rv = mme_send_delete_session_or_detach(mme_ue);
ogs_assert(rv == OGS_OK);
mme_send_delete_session_or_detach(mme_ue);
OGS_FSM_TRAN(s, &emm_state_de_registered);
break;
default:
@ -877,8 +869,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e)
return;
}
rv = mme_gtp_send_delete_all_sessions(mme_ue);
ogs_assert(rv == OGS_OK);
mme_gtp_send_delete_all_sessions(mme_ue);
OGS_FSM_TRAN(s, &emm_state_authentication);
break;
case OGS_NAS_EMM_STATUS:
@ -898,9 +889,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e)
return;
}
rv = mme_send_delete_session_or_detach(mme_ue);
ogs_assert(rv == OGS_OK);
mme_send_delete_session_or_detach(mme_ue);
OGS_FSM_TRAN(s, &emm_state_de_registered);
break;
default:

View File

@ -2801,6 +2801,8 @@ mme_bearer_t *mme_bearer_find_by_sess_ebi(mme_sess_t *sess, uint8_t ebi)
{
mme_bearer_t *bearer = NULL;
ogs_assert(sess);
bearer = mme_bearer_first(sess);
while (bearer) {
if (ebi == bearer->ebi)
@ -2817,6 +2819,8 @@ mme_bearer_t *mme_bearer_find_by_ue_ebi(mme_ue_t *mme_ue, uint8_t ebi)
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
ogs_assert(mme_ue);
sess = mme_sess_first(mme_ue);
while (sess) {
bearer = mme_bearer_find_by_sess_ebi(sess, ebi);
@ -2904,6 +2908,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
mme_bearer_t *mme_default_bearer_in_sess(mme_sess_t *sess)
{
ogs_assert(sess);
return mme_bearer_first(sess);
}
@ -2927,6 +2932,7 @@ mme_bearer_t *mme_bearer_first(mme_sess_t *sess)
mme_bearer_t *mme_bearer_next(mme_bearer_t *bearer)
{
ogs_assert(bearer);
return ogs_list_next(bearer);
}
@ -2954,8 +2960,8 @@ int mme_bearer_is_inactive(mme_ue_t *mme_ue)
int mme_bearer_set_inactive(mme_ue_t *mme_ue)
{
mme_sess_t *sess = NULL;
ogs_assert(mme_ue);
ogs_assert(mme_ue);
sess = mme_sess_first(mme_ue);
while (sess) {
mme_bearer_t *bearer = mme_bearer_first(sess);
@ -2988,6 +2994,8 @@ ogs_pdn_t *mme_pdn_find_by_apn(mme_ue_t *mme_ue, char *apn)
int i = 0;
ogs_assert(mme_ue);
ogs_assert(apn);
subscription_data = &mme_ue->subscription_data;
ogs_assert(subscription_data);

View File

@ -264,8 +264,8 @@ struct enb_ue_s {
/* Store by UE Context Release Command
* Retrieve by UE Context Release Complete */
#define S1AP_UE_CTX_REL_INVALID_ACTION 0
#define S1AP_UE_CTX_REL_NO_ACTION 1
#define S1AP_UE_CTX_REL_S1_NORMAL_RELEASE 2
#define S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE 1
#define S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK 2
#define S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE 3
#define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 4
uint8_t ue_ctx_rel_action;
@ -461,6 +461,12 @@ struct mme_ue_s {
OCTET_STRING_t container;
/* GTP Request/Response Counter */
#define GTP_COUNTER_CLEAR(__mME, __tYPE) \
do { \
ogs_assert((__mME)); \
((__mME)->gtp_counter[__tYPE].request) = 0; \
((__mME)->gtp_counter[__tYPE].response) = 0; \
} while(0);
#define GTP_COUNTER_INCREMENT(__mME, __tYPE) \
do { \
ogs_assert((__mME)); \
@ -475,8 +481,7 @@ struct mme_ue_s {
if (((__mME)->gtp_counter[__tYPE].request) == \
((__mME)->gtp_counter[__tYPE].response)) \
{ \
((__mME)->gtp_counter[__tYPE].request) = 0; \
((__mME)->gtp_counter[__tYPE].response) = 0; \
GTP_COUNTER_CLEAR(__mME, __tYPE) \
__eXPR \
} \
} while(0);

View File

@ -63,6 +63,7 @@ typedef struct enb_ue_s enb_ue_t;
typedef struct mme_ue_s mme_ue_t;
typedef struct mme_sess_s mme_sess_t;
typedef struct mme_bearer_s mme_bearer_t;
typedef struct ogs_gtp_node_s ogs_gtp_node_t;
typedef struct mme_event_s {
int id;
@ -78,6 +79,8 @@ typedef struct mme_event_s {
S1AP_ProcedureCode_t s1ap_code;
s1ap_message_t *s1ap_message;
ogs_gtp_node_t *gnode;
uint8_t nas_type;
ogs_nas_message_t *nas_message;

View File

@ -21,16 +21,21 @@
#include "mme-event.h"
#include "mme-gtp-path.h"
#include "mme-path.h"
#include "s1ap-path.h"
#include "mme-s11-build.h"
#include "mme-sm.h"
static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
{
int rv;
char buf[OGS_ADDRSTRLEN];
ssize_t size;
mme_event_t *e = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_sockaddr_t from;
mme_sgw_t *sgw = NULL;
ogs_assert(fd != INVALID_SOCKET);
@ -47,25 +52,65 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_pkbuf_trim(pkbuf, size);
sgw = mme_sgw_find_by_addr(&from);
if (!sgw) {
ogs_error("Unknown SGW : %s", OGS_ADDR(&from, buf));
ogs_pkbuf_free(e->pkbuf);
return;
}
ogs_assert(sgw->gnode);
e = mme_event_new(MME_EVT_S11_MESSAGE);
ogs_assert(e);
e->gnode = sgw->gnode;
e->pkbuf = pkbuf;
e->sock = data;
ogs_assert(e->sock);
e->addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
ogs_assert(e->addr);
memcpy(e->addr, &from, sizeof(ogs_sockaddr_t));
rv = ogs_queue_push(mme_self()->queue, e);
if (rv != OGS_OK) {
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
ogs_free(e->addr);
mme_event_free(e);
}
}
static void timeout(ogs_gtp_xact_t *xact, void *data)
{
mme_ue_t *mme_ue = NULL;
enb_ue_t *enb_ue = NULL;
mme_sess_t *sess = NULL;
uint8_t type = 0;
ogs_assert(xact);
type = xact->seq[0].type;
switch (type) {
case OGS_GTP_DELETE_SESSION_REQUEST_TYPE:
sess = data;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
enb_ue = mme_ue->enb_ue;
if (enb_ue) {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
} else {
ogs_warn("No S1 Context");
}
break;
default:
mme_ue = data;
ogs_assert(mme_ue);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
break;
}
ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]",
mme_ue->imsi_bcd, type);
}
int mme_gtp_open(void)
{
int rv;
@ -134,7 +179,7 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess)
rv = mme_s11_build_create_session_request(&pkbuf, h.type, sess);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
@ -167,7 +212,7 @@ int mme_gtp_send_modify_bearer_request(
&pkbuf, h.type, bearer, uli_presence);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
@ -195,18 +240,16 @@ int mme_gtp_send_delete_session_request(mme_sess_t *sess)
rv = mme_s11_build_delete_session_request(&s11buf, h.type, sess);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf, timeout, sess);
ogs_assert(xact);
OGS_GTP_XACT_STORE_SESSION(xact, sess);
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
return OGS_OK;
}
int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue)
void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue)
{
int rv;
mme_sess_t *sess = NULL, *next_sess = NULL;
@ -216,7 +259,7 @@ int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue)
if (SESSION_CONTEXT_WILL_DELETED(mme_ue)) {
ogs_warn("The MME has already sent a Delete-Session-Request to the SGW"
" for all sessions.");
return OGS_OK;
return;
}
mme_ue->session_context_will_deleted = 1;
@ -242,8 +285,6 @@ int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue)
sess = next_sess;
}
return OGS_OK;
}
int mme_gtp_send_create_bearer_response(mme_bearer_t *bearer)
@ -342,7 +383,7 @@ int mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer)
return OGS_OK;
}
int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue)
void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue)
{
int rv;
ogs_gtp_header_t h;
@ -358,13 +399,11 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue)
rv = mme_s11_build_release_access_bearers_request(&pkbuf, h.type);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
return OGS_OK;
}
int mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
@ -385,7 +424,7 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
&pkbuf, h.type, mme_ue);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
@ -411,7 +450,7 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
pkbuf = ogs_pkbuf_alloc(NULL, OGS_TLV_MAX_HEADROOM);
ogs_pkbuf_reserve(pkbuf, OGS_TLV_MAX_HEADROOM);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);

View File

@ -33,11 +33,11 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess);
int mme_gtp_send_modify_bearer_request(
mme_bearer_t *bearer, int uli_presence);
int mme_gtp_send_delete_session_request(mme_sess_t *sess);
int mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue);
void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue);
int mme_gtp_send_create_bearer_response(mme_bearer_t *bearer);
int mme_gtp_send_update_bearer_response(mme_bearer_t *bearer);
int mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer);
int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue);
void mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue);
int mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
mme_ue_t *mme_ue);

View File

@ -22,61 +22,71 @@
#include "mme-gtp-path.h"
#include "mme-path.h"
int mme_send_delete_session_or_detach(mme_ue_t *mme_ue)
void mme_send_delete_session_or_detach(mme_ue_t *mme_ue)
{
int rv;
ogs_assert(mme_ue);
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
rv = mme_gtp_send_delete_all_sessions(mme_ue);
ogs_assert(rv == OGS_OK);
mme_gtp_send_delete_all_sessions(mme_ue);
} else {
rv = nas_send_detach_accept(mme_ue);
ogs_assert(rv == OGS_OK);
nas_send_detach_accept(mme_ue);
}
return rv;
}
int mme_send_delete_session_or_ue_context_release(
mme_ue_t *mme_ue, enb_ue_t *enb_ue)
void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue)
{
int rv;
ogs_assert(enb_ue);
ogs_assert(mme_ue);
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
rv = mme_gtp_send_delete_all_sessions(mme_ue);
ogs_assert(rv == OGS_OK);
mme_gtp_send_delete_all_sessions(mme_ue);
} else {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
ogs_assert(rv == OGS_OK);
enb_ue_t *enb_ue = mme_ue->enb_ue;
if (enb_ue) {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
} else {
ogs_warn("No S1 Context");
}
}
return rv;
}
int mme_send_release_access_bearer_or_ue_context_release(
mme_ue_t *mme_ue, enb_ue_t *enb_ue)
void mme_send_delete_session_or_enb_ue_context_release(enb_ue_t *enb_ue)
{
int rv;
mme_ue_t *mme_ue = NULL;
ogs_assert(enb_ue);
if (BEARER_CONTEXT_IS_ACTIVE(mme_ue)) {
rv = mme_gtp_send_release_access_bearers_request(mme_ue);
ogs_assert(rv == OGS_OK);
mme_ue = enb_ue->mme_ue;
if (mme_ue && SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
mme_gtp_send_delete_all_sessions(mme_ue);
} else {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
ogs_assert(rv == OGS_OK);
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0);
}
}
void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue)
{
mme_ue_t *mme_ue = NULL;
ogs_assert(enb_ue);
mme_ue = enb_ue->mme_ue;
if (mme_ue) {
if (BEARER_CONTEXT_IS_ACTIVE(mme_ue)) {
ogs_debug(" EMM-Registered");
mme_gtp_send_release_access_bearers_request(mme_ue);
} else {
ogs_warn("No EMM-Registered");
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
}
} else {
ogs_debug("No UE Context");
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0);
}
return rv;
}

View File

@ -26,11 +26,10 @@
extern "C" {
#endif
int mme_send_delete_session_or_detach(mme_ue_t *mme_ue);
int mme_send_delete_session_or_ue_context_release(
mme_ue_t *mme_ue, enb_ue_t *enb_ue);
int mme_send_release_access_bearer_or_ue_context_release(
mme_ue_t *mme_ue, enb_ue_t *enb_ue);
void mme_send_delete_session_or_detach(mme_ue_t *mme_ue);
void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue);
void mme_send_delete_session_or_enb_ue_context_release(enb_ue_t *enb_ue);
void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue);
#ifdef __cplusplus
}

View File

@ -26,6 +26,7 @@
#include "nas-path.h"
#include "mme-fd-path.h"
#include "sgsap-path.h"
#include "mme-path.h"
#include "mme-s11-build.h"
#include "mme-s11-handler.h"
@ -35,6 +36,7 @@ void mme_s11_handle_create_session_response(
ogs_gtp_create_session_response_t *rsp)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_f_teid_t *sgw_s11_teid = NULL;
ogs_gtp_f_teid_t *sgw_s1u_teid = NULL;
@ -47,31 +49,65 @@ void mme_s11_handle_create_session_response(
ogs_debug("[MME] Create Session Response");
if (!mme_ue) {
ogs_warn("No Context in TEID");
mme_ue = xact->data;
ogs_assert(mme_ue);
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (rsp->bearer_contexts_created.cause.presence) {
cause = rsp->bearer_contexts_created.cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
}
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("Cause[%d] : No Accepted", cause_value);
if (rsp->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("No S11 TEID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->pdn_address_allocation.presence == 0) {
ogs_error("No PDN Address Allocation");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No S1U TEID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created. eps_bearer_id.presence == 0) {
if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
ogs_assert(mme_ue);
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
rsp->bearer_contexts_created.eps_bearer_id.u8);
ogs_assert(bearer);
@ -127,7 +163,7 @@ void mme_s11_handle_modify_bearer_response(
ogs_gtp_modify_bearer_response_t *rsp)
{
int rv;
ogs_gtp_cause_t *cause = NULL;
uint8_t cause_value = 0;
enb_ue_t *source_ue = NULL, *target_ue = NULL;
ogs_assert(xact);
@ -135,28 +171,32 @@ void mme_s11_handle_modify_bearer_response(
ogs_debug("[MME] Modify Bearer Response");
if (!mme_ue) {
ogs_warn("No Context in TEID");
mme_ue = xact->data;
ogs_assert(mme_ue);
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
return;
}
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
if (!mme_ue) {
ogs_warn("No Context");
return;
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH,
rv = s1ap_send_path_switch_ack(mme_ue);
ogs_assert(rv == OGS_OK);
@ -169,12 +209,11 @@ void mme_s11_handle_modify_bearer_response(
ogs_assert(source_ue);
CLEAR_ENB_UE_TIMER(source_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(source_ue,
s1ap_send_ue_context_release_command(source_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_successful_handover,
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL,
ogs_time_from_msec(300));
ogs_assert(rv == OGS_OK);
);
}
@ -183,7 +222,7 @@ void mme_s11_handle_delete_session_response(
ogs_gtp_delete_session_response_t *rsp)
{
int rv;
ogs_gtp_cause_t *cause = NULL;
uint8_t cause_value = 0;
mme_sess_t *sess = NULL;
ogs_assert(xact);
@ -191,24 +230,21 @@ void mme_s11_handle_delete_session_response(
ogs_debug("[MME] Delete Session Response");
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
sess = OGS_GTP_XACT_RETRIEVE_SESSION(xact);
sess = xact->data;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
goto cleanup;
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
goto cleanup;
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d] - Ignored", cause_value);
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
@ -220,8 +256,7 @@ void mme_s11_handle_delete_session_response(
}
} else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) {
if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
rv = nas_send_detach_accept(mme_ue);
ogs_assert(rv == OGS_OK);
nas_send_detach_accept(mme_ue);
}
} else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
mme_bearer_t *bearer = mme_default_bearer_in_sess(sess);
@ -256,10 +291,9 @@ void mme_s11_handle_delete_session_response(
enb_ue = mme_ue->enb_ue;
if (enb_ue) {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
ogs_assert(rv == OGS_OK);
} else
ogs_warn("ENB-S1 Context has already been removed");
}
@ -274,17 +308,15 @@ void mme_s11_handle_delete_session_response(
enb_ue = mme_ue->enb_ue;
if (enb_ue) {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
ogs_assert(rv == OGS_OK);
} else
ogs_warn("ENB-S1 Context has already been removed");
}
} else
ogs_assert_if_reached();
cleanup:
if (mme_sess_count(mme_ue) == 1) /* Last Session */
CLEAR_SESSION_CONTEXT(mme_ue);
@ -296,6 +328,7 @@ void mme_s11_handle_create_bearer_request(
ogs_gtp_create_bearer_request_t *req)
{
int rv;
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL, *default_bearer = NULL;
mme_sess_t *sess = NULL;
@ -307,41 +340,56 @@ void mme_s11_handle_create_bearer_request(
ogs_debug("[MME] Create Bearer Response");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EBI");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8);
ogs_assert(sess);
bearer = mme_bearer_add(sess);
ogs_assert(bearer);
}
if (!bearer) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No GTP TEID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.bearer_level_qos.presence == 0) {
ogs_error("No QoS");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.tft.presence == 0) {
ogs_error("No TFT");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0,
OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
ogs_assert(mme_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8);
ogs_assert(sess);
bearer = mme_bearer_add(sess);
ogs_assert(bearer);
/* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;
bearer->sgw_s1u_teid = ntohl(sgw_s1u_teid->teid);
@ -388,6 +436,7 @@ void mme_s11_handle_update_bearer_request(
ogs_gtp_update_bearer_request_t *req)
{
int rv;
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL;
ogs_gtp_bearer_qos_t bearer_qos;
@ -396,23 +445,37 @@ void mme_s11_handle_update_bearer_request(
ogs_debug("[MME] Update Bearer Request");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (mme_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
req->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
}
if (!bearer) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0,
OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
ogs_assert(mme_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
req->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
/* Save Transaction. will be handled after EMM-attached */
bearer->xact = xact;
@ -479,20 +542,25 @@ void mme_s11_handle_delete_bearer_request(
ogs_debug("[MME] Delete Bearer Request");
if (req->linked_eps_bearer_id.presence == 1) {
if (mme_ue && req->linked_eps_bearer_id.presence == 1) {
bearer = mme_bearer_find_by_ue_ebi(
mme_ue, req->linked_eps_bearer_id.u8);
ogs_assert(bearer);
} else if (req->eps_bearer_ids.presence == 1) {
} else if (mme_ue && req->eps_bearer_ids.presence == 1) {
bearer = mme_bearer_find_by_ue_ebi(
mme_ue, req->eps_bearer_ids.u8);
ogs_assert(bearer);
} else {
ogs_error("No Linked EBI or EPS Bearer ID");
ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0,
OGS_GTP_DELETE_BEARER_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
return;
}
ogs_assert(mme_ue);
ogs_assert(bearer);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
@ -522,7 +590,7 @@ void mme_s11_handle_release_access_bearers_response(
ogs_gtp_release_access_bearers_response_t *rsp)
{
int rv;
ogs_gtp_cause_t *cause = NULL;
uint8_t cause_value = 0;
enb_ue_t *enb_ue = NULL;
ogs_assert(xact);
@ -530,38 +598,41 @@ void mme_s11_handle_release_access_bearers_response(
ogs_debug("[MME] Release Access Bearers Response");
if (!mme_ue) {
ogs_warn("No Context in TEID");
mme_ue = xact->data;
ogs_assert(mme_ue);
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
return;
}
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
if (!mme_ue) {
ogs_warn("No Context");
return;
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
rv = CLEAR_BEARER_CONTEXT(mme_ue);
ogs_assert(rv == OGS_OK);
enb_ue = mme_ue->enb_ue;
if (enb_ue) {
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
ogs_assert(rv == OGS_OK);
S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0);
} else {
ogs_warn("ENB-S1 Context has already been removed");
}
@ -572,6 +643,7 @@ void mme_s11_handle_downlink_data_notification(
ogs_gtp_downlink_data_notification_t *noti)
{
int rv;
ogs_gtp_cause_t cause;
ogs_gtp_header_t h;
ogs_pkbuf_t *s11buf = NULL;
@ -580,7 +652,21 @@ void mme_s11_handle_downlink_data_notification(
ogs_debug("[MME] Downlink Data Notification");
ogs_assert(mme_ue);
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (!mme_ue) {
ogs_warn("No Context");
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0,
OGS_GTP_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE,
cause.value);
return;
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
@ -604,7 +690,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_gtp_create_indirect_data_forwarding_tunnel_response_t *rsp)
{
int rv;
ogs_gtp_cause_t *cause = NULL;
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL;
enb_ue_t *source_ue = NULL;
int i;
@ -617,28 +703,32 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_debug("[MME] Create Indirect Data Forwarding Tunnel Response");
if (!mme_ue) {
ogs_warn("No Context in TEID");
mme_ue = xact->data;
ogs_assert(mme_ue);
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
return;
}
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
if (!mme_ue) {
ogs_warn("No Context");
return;
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
ogs_gtp_bearers_in_create_indirect_tunnel_response(&bearers, rsp);
for (i = 0; bearers[i]->presence; i++) {
@ -681,29 +771,33 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp_delete_indirect_data_forwarding_tunnel_response_t *rsp)
{
int rv;
ogs_gtp_cause_t *cause = NULL;
uint8_t cause_value = 0;
ogs_assert(xact);
ogs_assert(rsp);
ogs_debug("[MME] Delete Indirect Data Forwarding Tunnel Response");
if (!mme_ue) {
ogs_warn("No Context in TEID");
mme_ue = xact->data;
ogs_assert(mme_ue);
}
rv = ogs_gtp_xact_commit(xact);
ogs_assert(rv == OGS_OK);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
return;
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
}
if (!mme_ue) {
ogs_warn("No Context");
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}

View File

@ -58,7 +58,6 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_sockaddr_t *addr = NULL;
mme_enb_t *enb = NULL;
uint16_t max_num_of_ostreams = 0;
mme_sgw_t *sgw = NULL;
s1ap_message_t s1ap_message;
ogs_pkbuf_t *pkbuf = NULL;
@ -271,7 +270,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_fsm_dispatch(&mme_ue->sm, e);
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_exception)) {
mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
}
ogs_pkbuf_free(pkbuf);
@ -328,8 +327,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
* [Enhancement] - Probably Invalid APN
* At this point, we'll forcely release UE context
*/
mme_send_delete_session_or_ue_context_release(
mme_ue, mme_ue->enb_ue);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
}
ogs_pkbuf_free(pkbuf);
@ -364,10 +362,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_assert(enb_ue);
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
ogs_assert(rv == OGS_OK);
ogs_pkbuf_free(s6abuf);
break;
@ -459,15 +456,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_assert(gnode);
} else {
ogs_assert(e->addr);
sgw = mme_sgw_find_by_addr(e->addr);
ogs_assert(sgw);
gnode = sgw->gnode;
gnode = e->gnode;
ogs_assert(gnode);
}
ogs_free(e->addr);
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &xact);
if (rv != OGS_OK) {

View File

@ -253,9 +253,8 @@ int nas_send_authentication_reject(mme_ue_t *mme_ue)
return OGS_OK;
}
int nas_send_detach_accept(mme_ue_t *mme_ue)
void nas_send_detach_accept(mme_ue_t *mme_ue)
{
int rv;
enb_ue_t *enb_ue = NULL;
ogs_pkbuf_t *emmbuf = NULL;
@ -265,6 +264,7 @@ int nas_send_detach_accept(mme_ue_t *mme_ue)
/* reply with detach accept */
if (mme_ue->nas_eps.detach.switch_off == 0) {
int rv;
rv = emm_build_detach_accept(&emmbuf, mme_ue);
ogs_assert(rv == OGS_OK && emmbuf);
@ -273,12 +273,9 @@ int nas_send_detach_accept(mme_ue_t *mme_ue)
}
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_detach,
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
ogs_assert(rv == OGS_OK);
return OGS_OK;
S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0);
}

View File

@ -43,7 +43,7 @@ int nas_send_authentication_reject(mme_ue_t *mme_ue);
int nas_send_security_mode_command(mme_ue_t *mme_ue);
int nas_send_detach_accept(mme_ue_t *mme_ue);
void nas_send_detach_accept(mme_ue_t *mme_ue);
int nas_send_pdn_connectivity_reject(
mme_sess_t *sess, ogs_nas_esm_cause_t esm_cause);

View File

@ -520,7 +520,6 @@ void s1ap_handle_initial_context_setup_response(
void s1ap_handle_initial_context_setup_failure(
mme_enb_t *enb, ogs_s1ap_message_t *message)
{
int rv;
char buf[OGS_ADDRSTRLEN];
int i;
@ -578,32 +577,20 @@ void s1ap_handle_initial_context_setup_failure(
ogs_debug(" Cause[Group:%d Cause:%d]",
Cause->present, (int)Cause->choice.radioNetwork);
mme_ue = enb_ue->mme_ue;
if (!mme_ue) {
ogs_debug(" S1 Context Release");
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_NO_ACTION, 0);
ogs_assert(rv == OGS_OK);
} else {
ogs_debug(" UE Context Release [IMSI:%s]", mme_ue->imsi_bcd);
/*
* 19.2.2.3 in Spec 36.300
*
* In case of failure, eNB and MME behaviours are not mandated.
*
* Both implicit release (local release at each node) and
* explicit release (MME-initiated UE Context Release procedure)
* may in principle be adopted. The eNB should ensure
* that no hanging resources remain at the eNB.
*/
rv = mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue);
ogs_assert(rv == OGS_OK);
if (mme_ue)
CLEAR_SERVICE_INDICATOR(mme_ue);
}
/*
* 19.2.2.3 in Spec 36.300
*
* In case of failure, eNB and MME behaviours are not mandated.
*
* Both implicit release (local release at each node) and
* explicit release (MME-initiated UE Context Release procedure)
* may in principle be adopted. The eNB should ensure
* that no hanging resources remain at the eNB.
*/
mme_send_delete_session_or_enb_ue_context_release(enb_ue);
}
void s1ap_handle_ue_context_modification_response(
@ -841,7 +828,6 @@ void s1ap_handle_ue_context_release_request(
S1AP_Cause_t *Cause = NULL;
enb_ue_t *enb_ue = NULL;
mme_ue_t *mme_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
@ -909,26 +895,7 @@ void s1ap_handle_ue_context_release_request(
break;
}
mme_ue = enb_ue->mme_ue;
if (mme_ue) {
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
ogs_debug(" EMM-Registered");
rv = mme_send_release_access_bearer_or_ue_context_release(
mme_ue, enb_ue);
ogs_assert(rv == OGS_OK);
} else {
ogs_debug(" NOT EMM-Registered");
rv = mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue);
ogs_assert(rv == OGS_OK);
}
} else {
ogs_debug(" S1 Context Not Associated");
CLEAR_ENB_UE_TIMER(enb_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_NO_ACTION, 0);
ogs_assert(rv == OGS_OK);
}
mme_send_release_access_bearer_or_ue_context_release(enb_ue);
}
void s1ap_handle_ue_context_release_complete(
@ -992,11 +959,11 @@ void s1ap_handle_ue_context_release_complete(
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
switch (enb_ue->ue_ctx_rel_action) {
case S1AP_UE_CTX_REL_NO_ACTION:
case S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE:
ogs_debug(" No Action");
enb_ue_remove(enb_ue);
break;
case S1AP_UE_CTX_REL_S1_NORMAL_RELEASE:
case S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK:
ogs_debug(" Action: S1 normal release");
enb_ue_remove(enb_ue);
mme_ue_deassociate(mme_ue);
@ -1629,11 +1596,10 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_assert(rv == OGS_OK);
CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(
s1ap_send_ue_context_release_command(
target_ue, S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system,
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL, 0);
ogs_assert(rv == OGS_OK);
}
void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
@ -1702,12 +1668,11 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_assert(rv == OGS_OK);
CLEAR_ENB_UE_TIMER(target_ue->t_ue_context_release);
rv = s1ap_send_ue_context_release_command(
s1ap_send_ue_context_release_command(
target_ue, S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_handover_cancelled,
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL,
ogs_time_from_msec(300));
ogs_assert(rv == OGS_OK);
ogs_debug("[MME] Handover Cancel : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]",

View File

@ -272,7 +272,7 @@ int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue)
return OGS_OK;
}
int s1ap_send_ue_context_release_command(
void s1ap_send_ue_context_release_command(
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause,
uint8_t action, uint32_t delay)
{
@ -320,8 +320,6 @@ int s1ap_send_ue_context_release_command(
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, 0);
ogs_assert(rv == OGS_OK);
}
return OGS_OK;
}
void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain)

View File

@ -50,7 +50,7 @@ int s1ap_send_to_esm(mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf);
int s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue);
int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue);
int s1ap_send_ue_context_release_command(
void s1ap_send_ue_context_release_command(
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause,
uint8_t action, uint32_t delay);

View File

@ -32,7 +32,6 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
{
ogs_tlv_t *root = NULL, *iter = NULL;
mme_ue_t *mme_ue = NULL;
enb_ue_t *enb_ue = NULL;
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
@ -108,20 +107,16 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
return;
error:
enb_ue = mme_ue->enb_ue;
ogs_assert(enb_ue);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
}
void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
{
ogs_tlv_t *root = NULL, *iter = NULL;
mme_ue_t *mme_ue = NULL;
enb_ue_t *enb_ue = NULL;
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
@ -180,12 +175,9 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
ogs_plmn_id_hexdump(&lai->nas_plmn_id), lai->lac);
}
enb_ue = mme_ue->enb_ue;
ogs_assert(enb_ue);
nas_send_attach_reject(mme_ue,
emm_cause, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
}
void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)

View File

@ -26,8 +26,9 @@
extern "C" {
#endif
typedef struct pgw_sess_s pgw_sess_t;
typedef struct ogs_gtp_node_s ogs_gtp_node_t;
typedef struct ogs_gtp_xact_s ogs_gtp_xact_t;
typedef struct pgw_sess_s pgw_sess_t;
typedef enum {
PGW_EVT_BASE = OGS_FSM_USER_SIG,
@ -44,11 +45,10 @@ typedef struct pgw_event_s {
ogs_pkbuf_t *gtpbuf;
ogs_pkbuf_t *gxbuf;
ogs_sock_t *sock;
ogs_sockaddr_t *addr;
ogs_gtp_node_t *gnode;
ogs_gtp_xact_t *xact;
pgw_sess_t *sess;
ogs_gtp_xact_t *xact;
} pgw_event_t;
void pgw_event_init(void);

View File

@ -91,6 +91,7 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
ssize_t size;
ogs_pkbuf_t *pkbuf = NULL;
ogs_sockaddr_t from;
ogs_gtp_node_t *gnode = NULL;
ogs_assert(fd != INVALID_SOCKET);
@ -108,20 +109,20 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_pkbuf_trim(pkbuf, size);
e = pgw_event_new(PGW_EVT_S5C_MESSAGE);
gnode = ogs_gtp_node_find_by_addr(&pgw_self()->sgw_s5c_list, &from);
if (!gnode) {
gnode = ogs_gtp_node_add_by_addr(&pgw_self()->sgw_s5c_list, &from);
ogs_assert(gnode);
gnode->sock = data;
}
ogs_assert(e);
e->gnode = gnode;
e->gtpbuf = pkbuf;
e->sock = data;
ogs_assert(e->sock);
e->addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
ogs_assert(e->addr);
memcpy(e->addr, &from, sizeof(ogs_sockaddr_t));
rv = ogs_queue_push(pgw_self()->queue, e);
if (rv != OGS_OK) {
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->gtpbuf);
ogs_free(e->addr);
pgw_event_free(e);
}
}

View File

@ -25,6 +25,19 @@
static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message);
static void timeout(ogs_gtp_xact_t *xact, void *data)
{
pgw_sess_t *sess = data;
uint8_t type = 0;
ogs_assert(sess);
type = xact->seq[0].type;
ogs_debug("GTP Timeout : SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x] "
"Message-Type[%d]", sess->sgw_s5c_teid, sess->pgw_s5c_teid, type);
}
void pgw_gx_handle_cca_initial_request(
pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message,
ogs_gtp_xact_t *xact, ogs_gtp_create_session_request_t *req)
@ -215,7 +228,8 @@ static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message)
ogs_assert(rv == OGS_OK);
}
xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(
sess->gnode, &h, pkbuf, timeout, sess);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
@ -231,7 +245,8 @@ static int bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message)
rv = pgw_s5c_build_delete_bearer_request(&pkbuf, h.type, bearer);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf);
xact = ogs_gtp_xact_local_create(
sess->gnode, &h, pkbuf, timeout, sess);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);

View File

@ -23,15 +23,12 @@
#include "pgw-fd-path.h"
#include "pgw-s5c-handler.h"
#define SEND_ERROR_MESSAGE(XACT, SESS, TYPE, CAUSE) \
ogs_gtp_send_error_message( \
(XACT), ((SESS) ? ((SESS)->sgw_s5c_teid) : 0), (TYPE), (CAUSE))
void pgw_s5c_handle_create_session_request(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid;
ogs_gtp_node_t *sgw = NULL;
pgw_bearer_t *bearer = NULL;
@ -45,54 +42,7 @@ void pgw_s5c_handle_create_session_request(
ogs_debug("[PGW] Create Session Reqeust");
if (req->imsi.presence == 0) {
ogs_error("No IMSI");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
if (req->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("No TEID");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
if (req->bearer_contexts_to_be_created.presence == 0) {
ogs_error("No Bearer");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) {
ogs_error("No EPS Bearer QoS");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
if (req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No TEID");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
if (req->user_location_information.presence == 0) {
ogs_error("No User Location Inforamtion");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
ogs_pkbuf_free(gtpbuf);
return;
}
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (sess) {
bearer = pgw_default_bearer_in_sess(sess);
@ -100,9 +50,39 @@ void pgw_s5c_handle_create_session_request(
}
if (!bearer) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(xact, sess,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->imsi.presence == 0) {
ogs_error("No IMSI");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("No TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_created.presence == 0) {
ogs_error("No Bearer");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) {
ogs_error("No EPS Bearer QoS");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->user_location_information.presence == 0) {
ogs_error("No User Location Inforamtion");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
ogs_pkbuf_free(gtpbuf);
return;
}
/* Set IMSI */
@ -182,7 +162,7 @@ void pgw_s5c_handle_delete_session_request(
if (!sess) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(xact, sess,
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
ogs_pkbuf_free(gtpbuf);

View File

@ -119,20 +119,10 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
ogs_assert(e->addr);
gnode = ogs_gtp_node_find_by_addr(
&pgw_self()->sgw_s5c_list, e->addr);
if (!gnode) {
gnode = ogs_gtp_node_add_by_addr(
&pgw_self()->sgw_s5c_list, e->addr);
ogs_assert(gnode);
gnode->sock = e->sock;
}
gnode = e->gnode;
ogs_assert(gnode);
}
ogs_free(e->addr);
rv = ogs_gtp_xact_receive(gnode, &message->h, &xact);
if (rv != OGS_OK) {
@ -146,8 +136,8 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
if (message->h.teid == 0) {
ogs_assert(!sess);
sess = pgw_sess_add_by_message(message);
ogs_assert(sess);
OGS_SETUP_GTP_NODE(sess, gnode);
if (sess)
OGS_SETUP_GTP_NODE(sess, gnode);
}
pgw_s5c_handle_create_session_request(
sess, xact, copybuf, &message->create_session_request);

View File

@ -401,6 +401,9 @@ sgw_ue_t *sgw_ue_add_by_message(ogs_gtp_message_t *message)
sgw_ue_t *sgw_ue = NULL;
ogs_gtp_create_session_request_t *req = &message->create_session_request;
ogs_assert(message);
req = &message->create_session_request;
if (req->imsi.presence == 0) {
ogs_error("No IMSI");
return NULL;
@ -563,6 +566,7 @@ void sgw_sess_remove_all(sgw_ue_t *sgw_ue)
{
sgw_sess_t *sess = NULL, *next_sess = NULL;
ogs_assert(sgw_ue);
ogs_list_for_each_safe(&sgw_ue->sess_list, next_sess, sess)
sgw_sess_remove(sess);
}
@ -575,8 +579,8 @@ sgw_sess_t* sgw_sess_find_by_teid(uint32_t teid)
sgw_sess_t* sgw_sess_find_by_apn(sgw_ue_t *sgw_ue, char *apn)
{
sgw_sess_t *sess = NULL;
ogs_assert(sgw_ue);
sess = sgw_sess_first(sgw_ue);
while (sess) {
if (strcmp(sess->pdn.apn, apn) == 0)
@ -680,6 +684,7 @@ sgw_bearer_t *sgw_bearer_find_by_sess_ebi(sgw_sess_t *sess, uint8_t ebi)
{
sgw_bearer_t *bearer = NULL;
ogs_assert(sess);
bearer = sgw_bearer_first(sess);
while (bearer) {
if (ebi == bearer->ebi)
@ -696,6 +701,7 @@ sgw_bearer_t *sgw_bearer_find_by_ue_ebi(sgw_ue_t *sgw_ue, uint8_t ebi)
sgw_sess_t *sess = NULL;
sgw_bearer_t *bearer = NULL;
ogs_assert(sgw_ue);
sess = sgw_sess_first(sgw_ue);
while (sess) {
bearer = sgw_bearer_find_by_sess_ebi(sess, ebi);
@ -722,6 +728,7 @@ sgw_bearer_t *sgw_bearer_first(sgw_sess_t *sess)
sgw_bearer_t *sgw_bearer_next(sgw_bearer_t *bearer)
{
ogs_assert(bearer);
return ogs_list_next(bearer);
}
@ -812,5 +819,6 @@ sgw_tunnel_t *sgw_tunnel_first(sgw_bearer_t *bearer)
sgw_tunnel_t *sgw_tunnel_next(sgw_tunnel_t *tunnel)
{
ogs_assert(tunnel);
return ogs_list_next(tunnel);
}

View File

@ -28,10 +28,6 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
sgw_event_t *e = NULL;
int rv;
ssize_t size;
ogs_gtp_header_t *gtp_h = NULL;
#if 0
uint32_t teid = 0;
#endif
ogs_pkbuf_t *pkbuf = NULL;
ogs_sockaddr_t from;
ogs_gtp_node_t *gnode = NULL;
@ -51,13 +47,6 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_pkbuf_trim(pkbuf, size);
gtp_h = (ogs_gtp_header_t *)pkbuf->data;
ogs_assert(gtp_h);
ogs_assert(gtp_h->teid_presence);
#if 0
teid = ntohl(gtp_h->teid);
#endif
/*
* 5.5.2 in spec 29.274
*
@ -90,6 +79,7 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
gnode = ogs_gtp_node_find_by_addr(&sgw_self()->pgw_s5c_list, &from);
if (gnode) {
e = sgw_event_new(SGW_EVT_S5C_MESSAGE);
ogs_assert(e);
e->gnode = gnode;
} else {
e = sgw_event_new(SGW_EVT_S11_MESSAGE);
@ -100,10 +90,10 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_assert(gnode);
gnode->sock = data;
}
ogs_assert(e);
e->gnode = gnode;
}
ogs_assert(e);
e->pkbuf = pkbuf;
rv = ogs_queue_push(sgw_self()->queue, e);

View File

@ -22,14 +22,28 @@
#include "sgw-gtp-path.h"
#include "sgw-s11-handler.h"
#define SEND_ERROR_MESSAGE(XACT, SGW_UE, TYPE, CAUSE) \
ogs_gtp_send_error_message( \
(XACT), ((SGW_UE) ? ((SGW_UE)->mme_s11_teid) : 0), (TYPE), (CAUSE))
static void timeout(ogs_gtp_xact_t *xact, void *data)
{
sgw_sess_t *sess = data;
sgw_ue_t *sgw_ue = NULL;
uint8_t type = 0;
ogs_assert(xact);
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
type = xact->seq[0].type;
ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]",
sgw_ue->imsi_bcd, type);
}
void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value = 0;
uint16_t decoded;
ogs_gtp_create_session_request_t *req = NULL;
ogs_pkbuf_t *pkbuf = NULL;
@ -52,62 +66,46 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
ogs_debug("[SGW] Create Session Request");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->create_session_request;
if (req->imsi.presence == 0) {
ogs_error("No IMSI");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->bearer_contexts_to_be_created.presence == 0) {
ogs_error("No Bearer");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->access_point_name.presence == 0) {
ogs_error("No APN");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("No Sender F-TEID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->pgw_s5_s8_address_for_control_plane_or_pmip.presence == 0) {
ogs_error("No PGW IP");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->user_location_information.presence == 0) {
ogs_error("No User Location Inforamtion");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (!sgw_ue) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->imsi.presence == 0) {
ogs_error("No IMSI");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_created.presence == 0) {
ogs_error("No Bearer");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->access_point_name.presence == 0) {
ogs_error("No APN");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("No Sender F-TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->pgw_s5_s8_address_for_control_plane_or_pmip.presence == 0) {
ogs_error("No PGW IP");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->user_location_information.presence == 0) {
ogs_error("No User Location Inforamtion");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -198,7 +196,8 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
s5c_xact = ogs_gtp_xact_local_create(sess->gnode, &message->h, pkbuf);
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, timeout, sess);
ogs_assert(s5c_xact);
ogs_gtp_xact_associate(s11_xact, s5c_xact);
@ -230,44 +229,47 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
ogs_debug("[SGW] Modify Bearer Reqeust");
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (req->bearer_contexts_to_be_modified.presence == 0) {
ogs_error("No Bearer");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts_to_be_modified.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No eNB TEID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (sgw_ue) {
if (sgw_ue && cause.value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
bearer = sgw_bearer_find_by_ue_ebi(sgw_ue,
req->bearer_contexts_to_be_modified.eps_bearer_id.u8);
ogs_assert(bearer);
}
if (!bearer) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No eNB TEID");
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE, cause.value);
return;
}
rsp = &message.modify_bearer_response;
memset(&message, 0, sizeof(ogs_gtp_message_t));
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
ogs_assert(s1u_tunnel);
@ -358,12 +360,6 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
/* Reset UE state */
SGW_RESET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE);
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
message.h.type = OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE;
message.h.teid = sgw_ue->mme_s11_teid;
@ -381,6 +377,7 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value = 0;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
@ -391,24 +388,25 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
ogs_debug("[SGW] Delete Session Reqeust");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->delete_session_request;
if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (!sgw_ue) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
ogs_assert(sgw_ue);
sess = sgw_sess_find_by_ebi(sgw_ue, req->linked_eps_bearer_id.u8);
ogs_assert(sess);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
@ -422,7 +420,8 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
s5c_xact = ogs_gtp_xact_local_create(sess->gnode, &message->h, pkbuf);
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, timeout, sess);
ogs_assert(s5c_xact);
ogs_gtp_xact_associate(s11_xact, s5c_xact);
@ -435,6 +434,7 @@ void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value;
uint16_t decoded;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_node_t *enb = NULL;
@ -450,32 +450,72 @@ void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact,
ogs_gtp_uli_t uli;
ogs_assert(s11_xact);
ogs_assert(sgw_ue);
ogs_assert(message);
s5c_xact = s11_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_assert(message);
ogs_debug("[SGW] Cerate Bearer Reqeust");
if (!sgw_ue) {
sgw_sess_t *sess = NULL;
ogs_warn("No Context in TEID");
sess = s11_xact->data;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
}
rv = ogs_gtp_xact_commit(s11_xact);
ogs_assert(rv == OGS_OK);
req = &message->create_bearer_response;
if (req->cause.presence) {
ogs_gtp_cause_t *cause = req->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (req->bearer_contexts.cause.presence) {
cause = req->bearer_contexts.cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
}
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No eNB TEID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) {
ogs_error("No SGW TEID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->user_location_information.presence == 0) {
ogs_error("No User Location Inforamtion");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -575,6 +615,7 @@ void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
@ -582,25 +623,72 @@ void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact,
ogs_gtp_update_bearer_response_t *req = NULL;
ogs_assert(s11_xact);
ogs_assert(sgw_ue);
ogs_assert(message);
s5c_xact = s11_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_assert(message);
ogs_debug("[SGW] Update Bearer Reqeust");
if (!sgw_ue) {
sgw_sess_t *sess = NULL;
ogs_warn("No Context in TEID");
sess = s11_xact->data;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
}
rv = ogs_gtp_xact_commit(s11_xact);
ogs_assert(rv == OGS_OK);
req = &message->update_bearer_response;
if (req->cause.presence) {
ogs_gtp_cause_t *cause = req->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (req->bearer_contexts.cause.presence) {
cause = req->bearer_contexts.cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
}
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (sgw_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
bearer = sgw_bearer_find_by_ue_ebi(
sgw_ue, req->bearer_contexts.eps_bearer_id.u8);
}
if (!bearer) {
ogs_error("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
bearer = sgw_bearer_find_by_ue_ebi(
sgw_ue, req->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
@ -627,6 +715,7 @@ void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
@ -634,26 +723,74 @@ void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact,
ogs_gtp_delete_bearer_response_t *req = NULL;
ogs_assert(s11_xact);
ogs_assert(sgw_ue);
ogs_assert(message);
s5c_xact = s11_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_assert(message);
ogs_debug("[SGW] Delete Bearer Response");
if (!sgw_ue) {
sgw_sess_t *sess = NULL;
ogs_warn("No Context in TEID");
sess = s11_xact->data;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
}
rv = ogs_gtp_xact_commit(s11_xact);
ogs_assert(rv == OGS_OK);
req = &message->delete_bearer_response;
if (req->cause.presence) {
ogs_gtp_cause_t *cause = req->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (req->bearer_contexts.cause.presence) {
cause = req->bearer_contexts.cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
}
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (sgw_ue && cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
bearer = sgw_bearer_find_by_ue_ebi(
sgw_ue, req->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
}
if (!bearer) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
bearer = sgw_bearer_find_by_ue_ebi(
sgw_ue, req->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
@ -695,17 +832,27 @@ void sgw_s11_handle_release_access_bearers_request(ogs_gtp_xact_t *s11_xact,
ogs_debug("[SGW] Release Access Bearers Request");
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause.value);
return;
}
rsp = &message.release_access_bearers_response;
memset(&message, 0, sizeof(ogs_gtp_message_t));
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/* Set UE state to S1UE_INACTIVE */
@ -731,12 +878,6 @@ void sgw_s11_handle_release_access_bearers_request(ogs_gtp_xact_t *s11_xact,
sess = sgw_sess_next(sess);
}
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
message.h.type = OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE;
message.h.teid = sgw_ue->mme_s11_teid;
@ -788,7 +929,8 @@ void sgw_s11_handle_lo_dldata_notification(sgw_bearer_t *bearer)
rv = ogs_gtp_build_msg(&pkbuf, &message);
ogs_assert(rv == OGS_OK);
xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &message.h, pkbuf);
xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message.h, pkbuf, timeout, sgw_ue);
ogs_assert(xact);
rv = ogs_gtp_xact_commit(xact);
@ -804,10 +946,16 @@ void sgw_s11_handle_downlink_data_notification_ack(
ogs_debug("[SGW] Downlink Data Notification Acknowledge");
if (!sgw_ue) {
ogs_warn("No context");
sgw_ue = s11_xact->data;
ogs_assert(sgw_ue);
}
rv = ogs_gtp_xact_commit(s11_xact);
ogs_assert(rv == OGS_OK);
ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
@ -840,10 +988,28 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
ogs_debug("[SGW] Create Indirect Data Forwarding Tunnel Request");
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
ogs_warn("No Context");
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
cause.value);
return;
}
rsp = &message.create_indirect_data_forwarding_tunnel_response;
memset(&message, 0, sizeof(ogs_gtp_message_t));
ogs_assert(sgw_ue);
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
@ -944,15 +1110,13 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
rsp_bearers[i]->presence = 1;
rsp_bearers[i]->eps_bearer_id.presence = 1;
rsp_bearers[i]->eps_bearer_id.u8 = bearer->ebi;
rsp_bearers[i]->cause.presence = 1;
rsp_bearers[i]->cause.data = &cause;
rsp_bearers[i]->cause.len = sizeof(cause);
}
}
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
message.h.type =
OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
message.h.teid = sgw_ue->mme_s11_teid;
@ -985,10 +1149,28 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
ogs_debug("[SGW] Delete Indirect Data Forwarding Tunnel Request");
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
ogs_warn("No Context");
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
cause.value);
return;
}
rsp = &message.delete_indirect_data_forwarding_tunnel_response;
memset(&message, 0, sizeof(ogs_gtp_message_t));
ogs_assert(sgw_ue);
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
@ -1017,12 +1199,6 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
sess = sgw_sess_next(sess);
}
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
rsp->cause.presence = 1;
rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause);
message.h.type =
OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
message.h.teid = sgw_ue->mme_s11_teid;

View File

@ -22,20 +22,28 @@
#include "sgw-gtp-path.h"
#include "sgw-s5c-handler.h"
#define SEND_ERROR_MESSAGE(XACT, SGW_UE, TYPE, CAUSE) \
ogs_gtp_send_error_message( \
(XACT), ((SGW_UE) ? ((SGW_UE)->mme_s11_teid) : 0), (TYPE), (CAUSE))
static void timeout(ogs_gtp_xact_t *xact, void *data)
{
sgw_ue_t *sgw_ue = data;
uint8_t type = 0;
ogs_assert(xact);
ogs_assert(sgw_ue);
ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]",
sgw_ue->imsi_bcd, type);
}
void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value;
ogs_gtp_node_t *pgw = NULL;
ogs_gtp_xact_t *s11_xact = NULL;
sgw_bearer_t *bearer = NULL;
sgw_tunnel_t *s1u_tunnel = NULL, *s5u_tunnel = NULL;
ogs_gtp_create_session_response_t *rsp = NULL;
ogs_gtp_cause_t *cause = NULL;
ogs_pkbuf_t *pkbuf = NULL;
sgw_ue_t *sgw_ue = NULL;
@ -48,66 +56,59 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_assert(gtp_message);
ogs_assert(message);
ogs_debug("[SGW] Create Session Response");
rsp = &gtp_message->create_session_response;
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
cause->value);
return;
if (!sess) {
ogs_warn("No Context in TEID");
sess = s5c_xact->data;
ogs_assert(sess);
}
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.
presence == 0) {
ogs_error("No GTP TEID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_assert(rv == OGS_OK);
rsp = &message->create_session_response;
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (rsp->bearer_contexts_created.cause.presence) {
cause = rsp->bearer_contexts_created.cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
}
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("Cause[%d] : No Accepted", cause_value);
if (rsp->bearer_contexts_created.cause.presence == 0) {
ogs_error("No EPS Bearer Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.presence == 0) {
ogs_error("No Bearer");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (rsp->bearer_contexts_created.cause.presence == 0) {
ogs_error("No EPS Bearer Cause");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No GTP TEID");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (sess) {
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
bearer = sgw_bearer_find_by_sess_ebi(sess,
rsp->bearer_contexts_created.eps_bearer_id.u8);
ogs_assert(bearer);
@ -121,9 +122,22 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
}
if (!bearer) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.
presence == 0) {
ogs_error("No GTP TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No GTP TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -185,16 +199,13 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = len;
rv = ogs_gtp_xact_commit(s5c_xact);
message->h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE;
message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
gtp_message->h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
ogs_assert(rv == OGS_OK);
rv = ogs_gtp_xact_update_tx(s11_xact, &gtp_message->h, pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_assert(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
@ -202,45 +213,46 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
}
void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_delete_session_response_t *rsp = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_cause_t *cause = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_assert(gtp_message);
ogs_assert(message);
ogs_debug("[SGW] Delete Session Response");
rsp = &gtp_message->delete_session_response;
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
return;
}
cause = rsp->cause.data;
ogs_assert(cause);
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("No Accept [%d]", cause->value);
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
cause->value);
return;
if (!sess) {
ogs_warn("No Context in TEID");
sess = s5c_xact->data;
ogs_assert(sess);
}
if (!sess) {
ogs_warn("No Context");
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_assert(rv == OGS_OK);
rsp = &message->delete_session_response;
if (rsp->cause.presence) {
ogs_gtp_cause_t *cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -255,16 +267,13 @@ void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact,
sgw_sess_remove(sess);
rv = ogs_gtp_xact_commit(s5c_xact);
message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE;
message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
gtp_message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
ogs_assert(rv == OGS_OK);
rv = ogs_gtp_xact_update_tx(s11_xact, &gtp_message->h, pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_assert(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
@ -272,9 +281,10 @@ void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact,
}
void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_node_t *pgw = NULL;
ogs_gtp_xact_t *s11_xact = NULL;
sgw_bearer_t *bearer = NULL;
@ -287,36 +297,45 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact,
ogs_gtp_f_teid_t sgw_s1u_teid;
int len;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_assert(s5c_xact);
ogs_assert(gtp_message);
req = &gtp_message->create_bearer_request;
ogs_assert(message);
ogs_debug("[SGW] Create Bearer Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->create_bearer_request;
if (!sess) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EBI");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
return;
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No GTP TEID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
bearer = sgw_bearer_add(sess);
ogs_assert(bearer);
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
@ -324,6 +343,11 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact,
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
ogs_assert(s5u_tunnel);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
/* Receive Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
@ -358,13 +382,14 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact,
req->bearer_contexts.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
req->bearer_contexts.s1_u_enodeb_f_teid.len = len;
gtp_message->h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;
message->h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE;
message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &gtp_message->h, pkbuf);
s11_xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message->h, pkbuf, timeout, sess);
ogs_assert(s11_xact);
ogs_gtp_xact_associate(s5c_xact, s11_xact);
@ -374,44 +399,59 @@ void sgw_s5c_handle_create_bearer_request(ogs_gtp_xact_t *s5c_xact,
}
void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_update_bearer_request_t *req = NULL;
ogs_pkbuf_t *pkbuf = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_assert(s5c_xact);
ogs_assert(gtp_message);
ogs_assert(message);
ogs_debug("[SGW] Update Bearer Request");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->update_bearer_request;
if (!sess) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
req = &gtp_message->update_bearer_request;
message->h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE;
message->h.teid = sgw_ue->mme_s11_teid;
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
return;
}
if (req->bearer_contexts.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
return;
}
gtp_message->h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &gtp_message->h, pkbuf);
s11_xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message->h, pkbuf, timeout, sess);
ogs_assert(s11_xact);
ogs_gtp_xact_associate(s5c_xact, s11_xact);
@ -423,40 +463,56 @@ void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact,
}
void sgw_s5c_handle_delete_bearer_request(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_delete_bearer_request_t *req = NULL;
ogs_pkbuf_t *pkbuf = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(sess);
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_assert(s5c_xact);
ogs_assert(gtp_message);
req = &gtp_message->delete_bearer_request;
ogs_assert(message);
ogs_debug("[SGW] Delete Bearer Request");
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
req = &message->delete_bearer_request;
if (!sess) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (req->linked_eps_bearer_id.presence == 0 &&
req->eps_bearer_ids.presence == 0) {
ogs_error("No Linked EBI or EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_DELETE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
if (req->linked_eps_bearer_id.presence == 0 &&
req->eps_bearer_ids.presence == 0) {
ogs_error("No Linked EBI or EPS Bearer ID");
return;
}
gtp_message->h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;
message->h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE;
message->h.teid = sgw_ue->mme_s11_teid;
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
rv = ogs_gtp_build_msg(&pkbuf, message);
ogs_assert(rv == OGS_OK);
s11_xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &gtp_message->h, pkbuf);
s11_xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message->h, pkbuf, timeout, sess);
ogs_assert(s11_xact);
ogs_gtp_xact_associate(s5c_xact, s11_xact);

View File

@ -134,8 +134,7 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
case OGS_GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
xact, sgw_ue,
&message.
create_indirect_data_forwarding_tunnel_request);
&message.create_indirect_data_forwarding_tunnel_request);
break;
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE:
sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(

View File

@ -301,7 +301,6 @@ static void attach_test1(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
#if 1 /* IMPLICIT_S1_RELEASE */
/* Send UE Context Release Request */
rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
@ -313,25 +312,6 @@ static void attach_test1(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
#else /* S1_HOLDING_TIMER */
/* Send UE Context Release Request */
rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UE Context Release Command */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send UE Context Release Complete */
rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex+3);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#endif
/* Send ESM Information Response */
rv = tests1ap_build_esm_information_response(&sendbuf, msgindex+1);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
@ -425,25 +405,6 @@ static void attach_test1(abts_case *tc, void *data)
/* eNB disonncect from SGW */
testenb_gtpu_close(gtpu);
return;
#if IT_WILL_BE_REMOVED
out:
/********** Remove Subscriber in Database */
doc = BCON_NEW("imsi", BCON_UTF8("001010123456819"));
ABTS_PTR_NOTNULL(tc, doc);
ABTS_TRUE(tc, mongoc_collection_remove(collection,
MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error))
bson_destroy(doc);
mongoc_collection_destroy(collection);
/* eNB disonncect from MME */
testenb_s1ap_close(s1ap);
/* eNB disonncect from SGW */
testenb_gtpu_close(gtpu);
#endif
}
/**************************************************************