[#258] Test done for receiving unknown TEID
This commit is contained in:
parent
71f54a4500
commit
cdbbbc500b
|
@ -351,8 +351,7 @@ bool ogs_sockaddr_is_equal(void *p, void *q)
|
|||
&a->sin6.sin6_addr, &b->sin6.sin6_addr, sizeof(struct in6_addr)) == 0)
|
||||
return true;
|
||||
else {
|
||||
ogs_fatal("Unknown family(%d)", a->ogs_sa_family);
|
||||
ogs_abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -215,3 +215,53 @@ ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkb)
|
|||
|
||||
return pkb_resp;
|
||||
}
|
||||
|
||||
void ogs_gtp_send_error_message(
|
||||
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
|
||||
{
|
||||
int rv;
|
||||
ogs_gtp_message_t errmsg;
|
||||
ogs_gtp_cause_t cause;
|
||||
ogs_tlv_cause_t *tlv = NULL;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
|
||||
memset(&errmsg, 0, sizeof(ogs_gtp_message_t));
|
||||
errmsg.h.teid = teid;
|
||||
errmsg.h.type = type;
|
||||
|
||||
switch (type) {
|
||||
case OGS_GTP_CREATE_SESSION_RESPONSE_TYPE:
|
||||
tlv = &errmsg.create_session_response.cause;
|
||||
break;
|
||||
case OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE:
|
||||
tlv = &errmsg.modify_bearer_response.cause;
|
||||
break;
|
||||
case OGS_GTP_DELETE_SESSION_RESPONSE_TYPE:
|
||||
tlv = &errmsg.delete_session_response.cause;
|
||||
break;
|
||||
case OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
|
||||
tlv = &errmsg.release_access_bearers_response.cause;
|
||||
break;
|
||||
default:
|
||||
ogs_assert_if_reached();
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_assert(tlv);
|
||||
|
||||
memset(&cause, 0, sizeof cause);
|
||||
cause.value = cause_value;
|
||||
tlv->presence = 1;
|
||||
tlv->len = sizeof(cause);
|
||||
tlv->data = &cause;
|
||||
|
||||
rv = ogs_gtp_build_msg(&pkbuf, &errmsg);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_update_tx(xact, &errmsg.h, pkbuf);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ogs_gtp_xact_s ogs_gtp_xact_t;
|
||||
|
||||
ogs_sock_t *ogs_gtp_server(ogs_socknode_t *node);
|
||||
int ogs_gtp_connect(ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_gtp_node_t *gnode);
|
||||
|
||||
|
@ -38,6 +40,8 @@ int ogs_gtp_send(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
|
|||
int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
|
||||
|
||||
ogs_pkbuf_t *ogs_gtp_handle_echo_req(ogs_pkbuf_t *pkt);
|
||||
void ogs_gtp_send_error_message(
|
||||
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -43,11 +43,13 @@ void mme_s11_handle_create_session_response(
|
|||
ogs_pdn_t *pdn = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("[MME] Create Session Response");
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
if (rsp->sender_f_teid_for_control_plane.presence == 0) {
|
||||
ogs_error("No S11 TEID");
|
||||
return;
|
||||
|
@ -70,7 +72,6 @@ void mme_s11_handle_create_session_response(
|
|||
}
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
|
||||
rsp->bearer_contexts_created.eps_bearer_id.u8);
|
||||
ogs_assert(bearer);
|
||||
|
@ -104,9 +105,6 @@ void mme_s11_handle_create_session_response(
|
|||
rv = ogs_gtp_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_initial_context_setup)) {
|
||||
mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai);
|
||||
mme_ue->csmap = csmap;
|
||||
|
@ -129,19 +127,36 @@ void mme_s11_handle_modify_bearer_response(
|
|||
ogs_gtp_modify_bearer_response_t *rsp)
|
||||
{
|
||||
int rv;
|
||||
ogs_gtp_cause_t *cause = NULL;
|
||||
enb_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(xact);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("[MME] Modify Bearer Response");
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
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 (!mme_ue) {
|
||||
ogs_warn("No Context");
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
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);
|
||||
|
@ -167,16 +182,11 @@ void mme_s11_handle_delete_session_response(
|
|||
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
|
||||
ogs_gtp_delete_session_response_t *rsp)
|
||||
{
|
||||
ogs_gtp_cause_t cause;
|
||||
|
||||
int rv;
|
||||
ogs_gtp_cause_t *cause = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
sess = OGS_GTP_XACT_RETRIEVE_SESSION(xact);
|
||||
ogs_assert(sess);
|
||||
mme_ue = sess->mme_ue;
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("[MME] Delete Session Response");
|
||||
|
@ -184,14 +194,20 @@ void mme_s11_handle_delete_session_response(
|
|||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
sess = OGS_GTP_XACT_RETRIEVE_SESSION(xact);
|
||||
ogs_assert(sess);
|
||||
mme_ue = sess->mme_ue;
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
if (rsp->cause.presence == 0) {
|
||||
ogs_error("No Cause");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(&cause, rsp->cause.data, rsp->cause.len);
|
||||
if (cause.value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_warn("No Accept [%d]", cause.value);
|
||||
cause = rsp->cause.data;
|
||||
ogs_assert(cause);
|
||||
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_warn("No Accept [%d]", cause->value);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -287,7 +303,6 @@ void mme_s11_handle_create_bearer_request(
|
|||
ogs_gtp_bearer_qos_t bearer_qos;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[MME] Create Bearer Response");
|
||||
|
@ -317,6 +332,7 @@ void mme_s11_handle_create_bearer_request(
|
|||
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);
|
||||
|
||||
|
@ -376,10 +392,10 @@ void mme_s11_handle_update_bearer_request(
|
|||
ogs_gtp_bearer_qos_t bearer_qos;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[MME] Update Bearer Request");
|
||||
|
||||
if (req->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
return;
|
||||
|
@ -388,6 +404,8 @@ void mme_s11_handle_update_bearer_request(
|
|||
ogs_error("No EPS Bearer ID");
|
||||
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);
|
||||
|
||||
|
@ -457,10 +475,10 @@ void mme_s11_handle_delete_bearer_request(
|
|||
mme_bearer_t *bearer = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[MME] Delete Bearer Request");
|
||||
|
||||
if (req->linked_eps_bearer_id.presence == 1) {
|
||||
bearer = mme_bearer_find_by_ue_ebi(
|
||||
mme_ue, req->linked_eps_bearer_id.u8);
|
||||
|
@ -473,6 +491,8 @@ void mme_s11_handle_delete_bearer_request(
|
|||
ogs_error("No Linked EBI or EPS Bearer ID");
|
||||
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);
|
||||
|
||||
|
@ -502,17 +522,13 @@ void mme_s11_handle_release_access_bearers_response(
|
|||
ogs_gtp_release_access_bearers_response_t *rsp)
|
||||
{
|
||||
int rv;
|
||||
ogs_gtp_cause_t *cause = NULL;
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("[MME] Release Access Bearers Response");
|
||||
enb_ue = mme_ue->enb_ue;
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
@ -521,18 +537,34 @@ void mme_s11_handle_release_access_bearers_response(
|
|||
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 (!mme_ue) {
|
||||
ogs_warn("No Context");
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
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_Cause_PR_nas, S1AP_CauseNas_normal_release,
|
||||
S1AP_UE_CTX_REL_S1_NORMAL_RELEASE, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
} else
|
||||
} else {
|
||||
ogs_warn("ENB-S1 Context has already been removed");
|
||||
}
|
||||
}
|
||||
|
||||
void mme_s11_handle_downlink_data_notification(
|
||||
|
@ -544,10 +576,11 @@ void mme_s11_handle_downlink_data_notification(
|
|||
ogs_pkbuf_t *s11buf = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(noti);
|
||||
|
||||
ogs_debug("[MME] Downlink Data Notification");
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
|
@ -571,6 +604,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;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
enb_ue_t *source_ue = NULL;
|
||||
int i;
|
||||
|
@ -579,23 +613,32 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
|
|||
ogs_gtp_f_teid_t *teid = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(rsp);
|
||||
|
||||
source_ue = mme_ue->enb_ue;
|
||||
ogs_assert(source_ue);
|
||||
|
||||
ogs_debug("[MME] Create Indirect Data Forwarding Tunnel Response");
|
||||
|
||||
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 (!mme_ue) {
|
||||
ogs_warn("No Context");
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
ogs_gtp_bearers_in_create_indirect_tunnel_response(&bearers, rsp);
|
||||
|
||||
for (i = 0; bearers[i]->presence; i++) {
|
||||
|
@ -626,6 +669,9 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
|
|||
}
|
||||
}
|
||||
|
||||
source_ue = mme_ue->enb_ue;
|
||||
ogs_assert(source_ue);
|
||||
|
||||
rv = s1ap_send_handover_command(source_ue);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
@ -635,22 +681,35 @@ 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;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("[MME] Delete Indirect Data Forwarding Tunnel Response");
|
||||
if (rsp->cause.presence == 0) {
|
||||
ogs_error("No Cause");
|
||||
return;
|
||||
}
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
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 (!mme_ue) {
|
||||
ogs_warn("No Context");
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
|
||||
|
||||
rv = mme_ue_clear_indirect_tunnel(mme_ue);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
|
|
@ -20,11 +20,16 @@
|
|||
#include "pgw-event.h"
|
||||
#include "pgw-context.h"
|
||||
#include "pgw-gtp-path.h"
|
||||
#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_gtp_create_session_request_t *req)
|
||||
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req)
|
||||
{
|
||||
int rv;
|
||||
ogs_gtp_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid;
|
||||
|
@ -36,36 +41,69 @@ void pgw_s5c_handle_create_session_request(
|
|||
uint16_t decoded = 0;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(sess);
|
||||
ogs_assert(req);
|
||||
bearer = pgw_default_bearer_in_sess(sess);
|
||||
ogs_assert(bearer);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (sess) {
|
||||
bearer = pgw_default_bearer_in_sess(sess);
|
||||
ogs_assert(bearer);
|
||||
}
|
||||
if (!bearer) {
|
||||
ogs_warn("No Context");
|
||||
SEND_ERROR_MESSAGE(xact, sess,
|
||||
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Set IMSI */
|
||||
sess->imsi_len = req->imsi.len;
|
||||
|
@ -128,17 +166,34 @@ void pgw_s5c_handle_create_session_request(
|
|||
sess->tai.tac = uli.tai.tac;
|
||||
memcpy(&sess->e_cgi.plmn_id, &uli.e_cgi.plmn_id, sizeof(uli.e_cgi.plmn_id));
|
||||
sess->e_cgi.cell_id = uli.e_cgi.cell_id;
|
||||
|
||||
pgw_gx_send_ccr(sess, xact, gtpbuf,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
||||
}
|
||||
|
||||
void pgw_s5c_handle_delete_session_request(
|
||||
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp_delete_session_request_t *req)
|
||||
ogs_pkbuf_t *gtpbuf, ogs_gtp_delete_session_request_t *req)
|
||||
{
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_debug("[PGW] Delete Session Request");
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(req);
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context");
|
||||
SEND_ERROR_MESSAGE(xact, sess,
|
||||
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
|
||||
ogs_pkbuf_free(gtpbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
|
||||
|
||||
pgw_gx_send_ccr(sess, xact, gtpbuf,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
}
|
||||
|
||||
void pgw_s5c_handle_create_bearer_response(
|
||||
|
|
|
@ -28,10 +28,10 @@ extern "C" {
|
|||
|
||||
void pgw_s5c_handle_create_session_request(
|
||||
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp_create_session_request_t *req);
|
||||
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req);
|
||||
void pgw_s5c_handle_delete_session_request(
|
||||
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp_delete_session_request_t *req);
|
||||
ogs_pkbuf_t *gtpbuf, ogs_gtp_delete_session_request_t *req);
|
||||
void pgw_s5c_handle_create_bearer_response(
|
||||
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp_create_bearer_response_t *req);
|
||||
|
|
|
@ -150,15 +150,11 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
|
|||
OGS_SETUP_GTP_NODE(sess, gnode);
|
||||
}
|
||||
pgw_s5c_handle_create_session_request(
|
||||
sess, xact, &message->create_session_request);
|
||||
pgw_gx_send_ccr(sess, xact, copybuf,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
||||
sess, xact, copybuf, &message->create_session_request);
|
||||
break;
|
||||
case OGS_GTP_DELETE_SESSION_REQUEST_TYPE:
|
||||
pgw_s5c_handle_delete_session_request(
|
||||
sess, xact, &message->delete_session_request);
|
||||
pgw_gx_send_ccr(sess, xact, copybuf,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
sess, xact, copybuf, &message->delete_session_request);
|
||||
break;
|
||||
case OGS_GTP_CREATE_BEARER_RESPONSE_TYPE:
|
||||
pgw_s5c_handle_create_bearer_response(
|
||||
|
|
|
@ -430,10 +430,8 @@ sgw_ue_t *sgw_ue_add_by_message(ogs_gtp_message_t *message)
|
|||
* the message is received with a TEID not set to zero in the header.
|
||||
*/
|
||||
sgw_ue = sgw_ue_find_by_imsi(req->imsi.data, req->imsi.len);
|
||||
if (sgw_ue) {
|
||||
ogs_warn("OLD UE Context Release [IMSI:%s]", sgw_ue->imsi_bcd);
|
||||
if (sgw_ue)
|
||||
sgw_ue_remove(sgw_ue);
|
||||
}
|
||||
sgw_ue = sgw_ue_add(req->imsi.data, req->imsi.len);
|
||||
ogs_assert(sgw_ue);
|
||||
|
||||
|
@ -795,11 +793,13 @@ sgw_tunnel_t *sgw_tunnel_find_by_interface_type(
|
|||
|
||||
sgw_tunnel_t *sgw_s1u_tunnel_in_bearer(sgw_bearer_t *bearer)
|
||||
{
|
||||
ogs_assert(bearer);
|
||||
return sgw_tunnel_find_by_interface_type(
|
||||
bearer, OGS_GTP_F_TEID_S1_U_SGW_GTP_U);
|
||||
}
|
||||
sgw_tunnel_t *sgw_s5u_tunnel_in_bearer(sgw_bearer_t *bearer)
|
||||
{
|
||||
ogs_assert(bearer);
|
||||
return sgw_tunnel_find_by_interface_type(
|
||||
bearer, OGS_GTP_F_TEID_S5_S8_SGW_GTP_U);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ogs_gtp_node_s ogs_gtp_node_t;
|
||||
typedef struct sgw_bearer_s sgw_bearer_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -44,8 +45,7 @@ typedef struct sgw_event_s {
|
|||
int id;
|
||||
ogs_pkbuf_t *pkbuf;
|
||||
|
||||
ogs_sock_t *sock;
|
||||
ogs_sockaddr_t *addr;
|
||||
ogs_gtp_node_t *gnode;
|
||||
|
||||
sgw_bearer_t *bearer;
|
||||
} sgw_event_t;
|
||||
|
|
|
@ -29,9 +29,12 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
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;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
|
@ -51,26 +54,62 @@ static void _gtpv2_c_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
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
|
||||
|
||||
if (SGW_S5C_TEID(teid))
|
||||
/*
|
||||
* 5.5.2 in spec 29.274
|
||||
*
|
||||
* If a peer's TEID is not available, the TEID field still shall be
|
||||
* present in the header and its value shall be set to "0" in the
|
||||
* following messages:
|
||||
*
|
||||
* - Create Session Request message on S2a/S2b/S5/S8
|
||||
*
|
||||
* - Create Session Request message on S4/S11, if for a given UE,
|
||||
* the SGSN/MME has not yet obtained the Control TEID of the SGW.
|
||||
*
|
||||
* - If a node receives a message and the TEID-C in the GTPv2 header of
|
||||
* the received message is not known, it shall respond with
|
||||
* "Context not found" Cause in the corresponding response message
|
||||
* to the sender, the TEID used in the GTPv2-C header in the response
|
||||
* message shall be then set to zero.
|
||||
*
|
||||
* - If a node receives a request message containing protocol error,
|
||||
* e.g. Mandatory IE missing, which requires the receiver to reject
|
||||
* the message as specified in clause 7.7, it shall reject
|
||||
* the request message. For the response message, the node should
|
||||
* look up the remote peer's TEID and accordingly set the GTPv2-C
|
||||
* header TEID and the message cause code. As an implementation
|
||||
* option, the node may not look up the remote peer's TEID and
|
||||
* set the GTPv2-C header TEID to zero in the response message.
|
||||
* However in this case, the cause code shall not be set to
|
||||
* "Context not found".
|
||||
*/
|
||||
gnode = ogs_gtp_node_find_by_addr(&sgw_self()->pgw_s5c_list, &from);
|
||||
if (gnode) {
|
||||
e = sgw_event_new(SGW_EVT_S5C_MESSAGE);
|
||||
else
|
||||
e->gnode = gnode;
|
||||
} else {
|
||||
e = sgw_event_new(SGW_EVT_S11_MESSAGE);
|
||||
gnode = ogs_gtp_node_find_by_addr(&sgw_self()->mme_s11_list, &from);
|
||||
if (!gnode) {
|
||||
gnode = ogs_gtp_node_add_by_addr(
|
||||
&sgw_self()->mme_s11_list, &from);
|
||||
ogs_assert(gnode);
|
||||
gnode->sock = data;
|
||||
}
|
||||
e->gnode = gnode;
|
||||
}
|
||||
|
||||
ogs_assert(e);
|
||||
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(sgw_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);
|
||||
sgw_event_free(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#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))
|
||||
|
||||
void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
|
||||
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
|
||||
{
|
||||
ogs_gtp_cause_t cause;
|
||||
|
||||
int rv;
|
||||
uint16_t decoded;
|
||||
ogs_gtp_create_session_request_t *req = NULL;
|
||||
|
@ -48,75 +50,69 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
|
|||
ogs_assert(s11_xact);
|
||||
ogs_assert(message);
|
||||
|
||||
req = &message->create_session_request;
|
||||
|
||||
ogs_debug("[SGW] Create Session Request");
|
||||
|
||||
memset(&cause, 0, sizeof cause);
|
||||
|
||||
if (!sgw_ue) {
|
||||
ogs_warn("No Context");
|
||||
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
req = &message->create_session_request;
|
||||
if (req->imsi.presence == 0) {
|
||||
ogs_error("No IMSI");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
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");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
if (cause.value) {
|
||||
ogs_gtp_message_t errmsg;
|
||||
ogs_gtp_create_session_response_t *rsp = NULL;
|
||||
|
||||
ogs_debug("[SGW] Create Session Response");
|
||||
|
||||
rsp = &errmsg.create_session_response;
|
||||
memset(&errmsg, 0, sizeof(ogs_gtp_message_t));
|
||||
|
||||
/* Set Cause */
|
||||
rsp->cause.presence = 1;
|
||||
rsp->cause.len = sizeof(cause);
|
||||
rsp->cause.data = &cause;
|
||||
|
||||
errmsg.h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE;
|
||||
if (sgw_ue)
|
||||
errmsg.h.teid = sgw_ue->mme_s11_teid;
|
||||
rv = ogs_gtp_build_msg(&pkbuf, &errmsg);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_update_tx(s11_xact, &errmsg.h, pkbuf);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_commit(s11_xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
ogs_fqdn_parse(apn,
|
||||
req->access_point_name.data, req->access_point_name.len);
|
||||
sess = sgw_sess_find_by_ebi(sgw_ue,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
if (sess) {
|
||||
|
@ -124,9 +120,6 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
|
|||
sgw_ue->imsi_bcd, sess->pdn.apn);
|
||||
sgw_sess_remove(sess);
|
||||
}
|
||||
|
||||
ogs_fqdn_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);
|
||||
ogs_assert(sess);
|
||||
|
@ -217,8 +210,6 @@ void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
|
|||
void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
|
||||
sgw_ue_t *sgw_ue, ogs_gtp_modify_bearer_request_t *req)
|
||||
{
|
||||
ogs_gtp_cause_t cause;
|
||||
|
||||
int rv;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
|
@ -230,6 +221,7 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
|
|||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_gtp_message_t message;
|
||||
|
||||
ogs_gtp_cause_t cause;
|
||||
ogs_gtp_f_teid_t *enb_s1u_teid = NULL;
|
||||
ogs_gtp_uli_t uli;
|
||||
|
||||
|
@ -238,132 +230,142 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
|
|||
|
||||
ogs_debug("[SGW] Modify Bearer Reqeust");
|
||||
|
||||
rsp = &message.modify_bearer_response;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (sgw_ue) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
rsp = &message.modify_bearer_response;
|
||||
memset(&message, 0, sizeof(ogs_gtp_message_t));
|
||||
message.h.type = OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE;
|
||||
if (sgw_ue)
|
||||
message.h.teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
|
||||
/* Data Plane(DL) : eNB-S1U */
|
||||
enb_s1u_teid =
|
||||
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
|
||||
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
|
||||
ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]",
|
||||
s1u_tunnel->remote_teid, s1u_tunnel->local_teid);
|
||||
|
||||
enb = ogs_gtp_node_find_by_f_teid(
|
||||
&sgw_self()->enb_s1u_list, enb_s1u_teid);
|
||||
if (!enb) {
|
||||
enb = ogs_gtp_node_add(&sgw_self()->enb_s1u_list, enb_s1u_teid,
|
||||
sgw_self()->gtpu_port,
|
||||
ogs_config()->parameter.no_ipv4,
|
||||
ogs_config()->parameter.no_ipv6,
|
||||
ogs_config()->parameter.prefer_ipv4);
|
||||
ogs_assert(enb);
|
||||
|
||||
rv = ogs_gtp_connect(sgw_self()->gtpu_sock, sgw_self()->gtpu_sock6, enb);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
||||
/* Copy Bearer-Contexts-Modified from Modify-Bearer-Request
|
||||
*
|
||||
* TS 29.274 Table 7.2.7-2
|
||||
* NOTE 1: The SGW shall not change its F-TEID for a given interface
|
||||
* during the Handover, Service Request, E-UTRAN Initial Attach,
|
||||
* UE Requested PDN connectivity and PDP Context Activation procedures.
|
||||
* The SGW F-TEID shall be same for S1-U, S4-U and S12. During Handover
|
||||
* and Service Request the target eNodeB/RNC/SGSN may use a different
|
||||
* IP type than the one used by the source eNodeB/RNC/SGSN.
|
||||
* In order to support such a scenario, the SGW F-TEID should contain
|
||||
* both an IPv4 address and an IPv6 address
|
||||
* (see also subclause 8.22 "F-TEID").
|
||||
*/
|
||||
rsp->bearer_contexts_modified.presence = 1;
|
||||
rsp->bearer_contexts_modified.eps_bearer_id.presence = 1;
|
||||
rsp->bearer_contexts_modified.eps_bearer_id.u8 =
|
||||
req->bearer_contexts_to_be_modified.eps_bearer_id.u8;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.presence = 1;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.data =
|
||||
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.len =
|
||||
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.len;
|
||||
|
||||
rsp->bearer_contexts_modified.cause.presence = 1;
|
||||
rsp->bearer_contexts_modified.cause.len = sizeof(cause);
|
||||
rsp->bearer_contexts_modified.cause.data = &cause;
|
||||
|
||||
/* if GTP Node changes, End Marker is sent out or not */
|
||||
if (req->user_location_information.presence == 1) {
|
||||
/* Set User Location Information */
|
||||
decoded = ogs_gtp_parse_uli(&uli, &req->user_location_information);
|
||||
ogs_assert(req->user_location_information.len == decoded);
|
||||
memcpy(&bearer->tai.plmn_id, &uli.tai.plmn_id,
|
||||
sizeof(uli.tai.plmn_id));
|
||||
bearer->tai.tac = uli.tai.tac;
|
||||
memcpy(&bearer->e_cgi.plmn_id, &uli.e_cgi.plmn_id,
|
||||
sizeof(uli.e_cgi.plmn_id));
|
||||
bearer->e_cgi.cell_id = uli.e_cgi.cell_id;
|
||||
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
|
||||
ogs_plmn_id_hexdump(&bearer->tai.plmn_id),
|
||||
bearer->tai.tac);
|
||||
ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]",
|
||||
ogs_plmn_id_hexdump(&bearer->e_cgi.plmn_id),
|
||||
bearer->e_cgi.cell_id);
|
||||
}
|
||||
|
||||
if (s1u_tunnel->gnode && s1u_tunnel->gnode != enb) {
|
||||
ogs_assert(s1u_tunnel->gnode->sock);
|
||||
|
||||
ogs_debug("[SGW] SEND End Marker to ENB[%s]: TEID[0x%x]",
|
||||
OGS_ADDR(&s1u_tunnel->gnode->remote_addr, buf),
|
||||
s1u_tunnel->remote_teid);
|
||||
rv = sgw_gtp_send_end_marker(s1u_tunnel);
|
||||
if (rv != OGS_OK)
|
||||
ogs_error("gtp send end marker failed");
|
||||
}
|
||||
|
||||
/* Setup GTP Node */
|
||||
OGS_SETUP_GTP_NODE(s1u_tunnel, enb);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (req->bearer_contexts_to_be_modified.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
} else {
|
||||
if (sgw_ue) {
|
||||
bearer = sgw_bearer_find_by_ue_ebi(sgw_ue,
|
||||
req->bearer_contexts_to_be_modified.eps_bearer_id.u8);
|
||||
}
|
||||
if (!bearer) {
|
||||
ogs_warn("No Context");
|
||||
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
if (req->bearer_contexts_to_be_modified.eps_bearer_id.presence == 0) {
|
||||
ogs_error("No EPS Bearer ID");
|
||||
cause.value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
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 (bearer) {
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
|
||||
/* Data Plane(DL) : eNB-S1U */
|
||||
enb_s1u_teid = req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
|
||||
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
|
||||
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
|
||||
ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]",
|
||||
s1u_tunnel->remote_teid, s1u_tunnel->local_teid);
|
||||
|
||||
enb = ogs_gtp_node_find_by_f_teid(
|
||||
&sgw_self()->enb_s1u_list, enb_s1u_teid);
|
||||
if (!enb) {
|
||||
enb = ogs_gtp_node_add(&sgw_self()->enb_s1u_list, enb_s1u_teid,
|
||||
sgw_self()->gtpu_port,
|
||||
ogs_config()->parameter.no_ipv4,
|
||||
ogs_config()->parameter.no_ipv6,
|
||||
ogs_config()->parameter.prefer_ipv4);
|
||||
ogs_assert(enb);
|
||||
|
||||
rv = ogs_gtp_connect(sgw_self()->gtpu_sock, sgw_self()->gtpu_sock6, enb);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
}
|
||||
|
||||
/* Copy Bearer-Contexts-Modified from Modify-Bearer-Request
|
||||
*
|
||||
* TS 29.274 Table 7.2.7-2
|
||||
* NOTE 1: The SGW shall not change its F-TEID for a given interface
|
||||
* during the Handover, Service Request, E-UTRAN Initial Attach,
|
||||
* UE Requested PDN connectivity and PDP Context Activation procedures.
|
||||
* The SGW F-TEID shall be same for S1-U, S4-U and S12. During Handover
|
||||
* and Service Request the target eNodeB/RNC/SGSN may use a different
|
||||
* IP type than the one used by the source eNodeB/RNC/SGSN.
|
||||
* In order to support such a scenario, the SGW F-TEID should contain
|
||||
* both an IPv4 address and an IPv6 address
|
||||
* (see also subclause 8.22 "F-TEID").
|
||||
*/
|
||||
rsp->bearer_contexts_modified.presence = 1;
|
||||
rsp->bearer_contexts_modified.eps_bearer_id.presence = 1;
|
||||
rsp->bearer_contexts_modified.eps_bearer_id.u8 =
|
||||
req->bearer_contexts_to_be_modified.eps_bearer_id.u8;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.presence = 1;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.data =
|
||||
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
|
||||
rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.len =
|
||||
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.len;
|
||||
|
||||
rsp->bearer_contexts_modified.cause.presence = 1;
|
||||
rsp->bearer_contexts_modified.cause.len = sizeof(cause);
|
||||
rsp->bearer_contexts_modified.cause.data = &cause;
|
||||
|
||||
/* if GTP Node changes, End Marker is sent out or not */
|
||||
if (req->user_location_information.presence == 1) {
|
||||
/* Set User Location Information */
|
||||
decoded = ogs_gtp_parse_uli(&uli, &req->user_location_information);
|
||||
ogs_assert(req->user_location_information.len == decoded);
|
||||
memcpy(&bearer->tai.plmn_id, &uli.tai.plmn_id,
|
||||
sizeof(uli.tai.plmn_id));
|
||||
bearer->tai.tac = uli.tai.tac;
|
||||
memcpy(&bearer->e_cgi.plmn_id, &uli.e_cgi.plmn_id,
|
||||
sizeof(uli.e_cgi.plmn_id));
|
||||
bearer->e_cgi.cell_id = uli.e_cgi.cell_id;
|
||||
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
|
||||
ogs_plmn_id_hexdump(&bearer->tai.plmn_id),
|
||||
bearer->tai.tac);
|
||||
ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]",
|
||||
ogs_plmn_id_hexdump(&bearer->e_cgi.plmn_id),
|
||||
bearer->e_cgi.cell_id);
|
||||
}
|
||||
|
||||
if (s1u_tunnel->gnode && s1u_tunnel->gnode != enb) {
|
||||
ogs_assert(s1u_tunnel->gnode->sock);
|
||||
|
||||
ogs_debug("[SGW] SEND End Marker to ENB[%s]: TEID[0x%x]",
|
||||
OGS_ADDR(&s1u_tunnel->gnode->remote_addr, buf),
|
||||
s1u_tunnel->remote_teid);
|
||||
rv = sgw_gtp_send_end_marker(s1u_tunnel);
|
||||
if (rv != OGS_OK)
|
||||
ogs_error("gtp send end marker failed");
|
||||
}
|
||||
|
||||
/* Setup GTP Node */
|
||||
OGS_SETUP_GTP_NODE(s1u_tunnel, enb);
|
||||
|
||||
/* Reset UE state */
|
||||
SGW_RESET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE);
|
||||
|
||||
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
message.h.type = OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE;
|
||||
message.h.teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
rv = ogs_gtp_build_msg(&pkbuf, &message);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
@ -378,8 +380,6 @@ void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
|
|||
void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
|
||||
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
|
||||
{
|
||||
ogs_gtp_cause_t cause;
|
||||
|
||||
int rv;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_gtp_xact_t *s5c_xact = NULL;
|
||||
|
@ -389,52 +389,26 @@ void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
|
|||
ogs_assert(s11_xact);
|
||||
ogs_assert(message);
|
||||
|
||||
req = &message->delete_session_request;
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[SGW] Delete Session Reqeust");
|
||||
|
||||
memset(&cause, 0, sizeof cause);
|
||||
|
||||
if (!sgw_ue) {
|
||||
ogs_warn("No Context");
|
||||
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
req = &message->delete_session_request;
|
||||
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_message_t errmsg;
|
||||
ogs_gtp_delete_session_response_t *rsp = NULL;
|
||||
|
||||
ogs_debug("[SGW] Delete Session Response");
|
||||
|
||||
rsp = &errmsg.delete_session_response;
|
||||
memset(&errmsg, 0, sizeof(ogs_gtp_message_t));
|
||||
|
||||
/* Set Cause */
|
||||
rsp->cause.presence = 1;
|
||||
rsp->cause.len = sizeof(cause);
|
||||
rsp->cause.data = &cause;
|
||||
|
||||
errmsg.h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE;
|
||||
if (sgw_ue)
|
||||
errmsg.h.teid = sgw_ue->mme_s11_teid;
|
||||
rv = ogs_gtp_build_msg(&pkbuf, &errmsg);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_update_tx(s11_xact, &errmsg.h, pkbuf);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_xact_commit(s11_xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
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);
|
||||
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]",
|
||||
|
@ -482,9 +456,8 @@ void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact,
|
|||
ogs_assert(s5c_xact);
|
||||
|
||||
ogs_debug("[SGW] Cerate Bearer Reqeust");
|
||||
req = &message->create_bearer_response;
|
||||
ogs_assert(req);
|
||||
|
||||
req = &message->create_bearer_response;
|
||||
if (req->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
return;
|
||||
|
@ -614,10 +587,9 @@ void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact,
|
|||
s5c_xact = s11_xact->assoc_xact;
|
||||
ogs_assert(s5c_xact);
|
||||
|
||||
req = &message->update_bearer_response;
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[SGW] Update Bearer Reqeust");
|
||||
|
||||
req = &message->update_bearer_response;
|
||||
if (req->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
return;
|
||||
|
@ -667,10 +639,9 @@ void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact,
|
|||
s5c_xact = s11_xact->assoc_xact;
|
||||
ogs_assert(s5c_xact);
|
||||
|
||||
req = &message->delete_bearer_response;
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[SGW] Delete Bearer Response");
|
||||
|
||||
req = &message->delete_bearer_response;
|
||||
if (req->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
return;
|
||||
|
@ -724,49 +695,50 @@ void sgw_s11_handle_release_access_bearers_request(ogs_gtp_xact_t *s11_xact,
|
|||
|
||||
ogs_debug("[SGW] Release Access Bearers Request");
|
||||
|
||||
rsp = &message.release_access_bearers_response;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
rsp = &message.release_access_bearers_response;
|
||||
memset(&message, 0, sizeof(ogs_gtp_message_t));
|
||||
message.h.type = OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE;
|
||||
if (sgw_ue)
|
||||
message.h.teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
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 */
|
||||
SGW_SET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE);
|
||||
/* ReSet UE state to S1UE_INACTIVE */
|
||||
SGW_RESET_UE_STATE(sgw_ue, SGW_DL_NOTI_SENT);
|
||||
|
||||
/* Release S1U(DL) path */
|
||||
sess = sgw_sess_first(sgw_ue);
|
||||
while (sess) {
|
||||
bearer = ogs_list_first(&sess->bearer_list);
|
||||
while (bearer) {
|
||||
next_bearer = ogs_list_next(bearer);
|
||||
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
|
||||
s1u_tunnel->remote_teid = 0;
|
||||
|
||||
bearer = next_bearer;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!sgw_ue) {
|
||||
ogs_warn("No Context");
|
||||
cause.value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
|
||||
} else {
|
||||
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 */
|
||||
SGW_SET_UE_STATE(sgw_ue, SGW_S1U_INACTIVE);
|
||||
/* ReSet UE state to S1UE_INACTIVE */
|
||||
SGW_RESET_UE_STATE(sgw_ue, SGW_DL_NOTI_SENT);
|
||||
|
||||
/* Release S1U(DL) path */
|
||||
sess = sgw_sess_first(sgw_ue);
|
||||
while (sess) {
|
||||
bearer = ogs_list_first(&sess->bearer_list);
|
||||
while (bearer) {
|
||||
next_bearer = ogs_list_next(bearer);
|
||||
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
|
||||
s1u_tunnel->remote_teid = 0;
|
||||
|
||||
bearer = next_bearer;
|
||||
}
|
||||
|
||||
sess = sgw_sess_next(sess);
|
||||
}
|
||||
|
||||
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
message.h.type = OGS_GTP_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE;
|
||||
message.h.teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
rv = ogs_gtp_build_msg(&pkbuf, &message);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
@ -828,15 +800,17 @@ void sgw_s11_handle_downlink_data_notification_ack(
|
|||
ogs_gtp_downlink_data_notification_acknowledge_t *ack)
|
||||
{
|
||||
int rv;
|
||||
ogs_assert(sgw_ue);
|
||||
ogs_assert(s11_xact);
|
||||
|
||||
ogs_debug("[SGW] Downlink Data Notification Acknowledge");
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
|
||||
|
@ -861,27 +835,21 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
|
|||
ogs_gtp_f_teid_t rsp_ul_teid[GTP_MAX_NUM_OF_INDIRECT_TUNNEL];
|
||||
int len;
|
||||
|
||||
ogs_assert(sgw_ue);
|
||||
ogs_assert(s11_xact);
|
||||
ogs_assert(req);
|
||||
|
||||
ogs_debug("[SGW] Create Indirect Data Forwarding Tunnel Request");
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
|
||||
|
||||
rsp = &message.create_indirect_data_forwarding_tunnel_response;
|
||||
memset(&message, 0, sizeof(ogs_gtp_message_t));
|
||||
|
||||
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_gtp_bearers_in_create_indirect_tunnel_request(&req_bearers, req);
|
||||
ogs_gtp_bearers_in_create_indirect_tunnel_response(&rsp_bearers, rsp);
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0; req_bearers[i]->presence; i++) {
|
||||
if (req_bearers[i]->eps_bearer_id.presence == 0) {
|
||||
ogs_error("No EBI");
|
||||
|
@ -979,6 +947,12 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1007,10 +981,14 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
|
|||
|
||||
ogs_gtp_cause_t cause;
|
||||
|
||||
ogs_assert(sgw_ue);
|
||||
ogs_assert(s11_xact);
|
||||
|
||||
ogs_debug("[SGW] Delete Indirect Data Forwarding Tunnel Request");
|
||||
|
||||
rsp = &message.delete_indirect_data_forwarding_tunnel_response;
|
||||
memset(&message, 0, sizeof(ogs_gtp_message_t));
|
||||
|
||||
ogs_assert(sgw_ue);
|
||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
|
||||
|
||||
|
@ -1039,12 +1017,8 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
|
|||
sess = sgw_sess_next(sess);
|
||||
}
|
||||
|
||||
rsp = &message.delete_indirect_data_forwarding_tunnel_response;
|
||||
memset(&message, 0, sizeof(ogs_gtp_message_t));
|
||||
|
||||
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);
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#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))
|
||||
|
||||
void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
|
||||
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message)
|
||||
{
|
||||
|
@ -31,6 +35,7 @@ void sgw_s5c_handle_create_session_response(ogs_gtp_xact_t *s5c_xact,
|
|||
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;
|
||||
|
||||
|
@ -40,46 +45,87 @@ void sgw_s5c_handle_create_session_response(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);
|
||||
s11_xact = s5c_xact->assoc_xact;
|
||||
ogs_assert(s11_xact);
|
||||
ogs_assert(gtp_message);
|
||||
|
||||
ogs_debug("[SGW] Create Session Response");
|
||||
|
||||
rsp = >p_message->create_session_response;
|
||||
if (rsp->cause.presence == 0) {
|
||||
ogs_error("No Cause");
|
||||
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
|
||||
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
|
||||
return;
|
||||
}
|
||||
cause = rsp->cause.data;
|
||||
ogs_assert(cause);
|
||||
if (cause->value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_warn("No Accept [%d]", cause->value);
|
||||
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
|
||||
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
|
||||
cause->value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
bearer = sgw_bearer_find_by_sess_ebi(sess,
|
||||
rsp->bearer_contexts_created.eps_bearer_id.u8);
|
||||
ogs_assert(bearer);
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s5u_tunnel);
|
||||
if (sess) {
|
||||
bearer = sgw_bearer_find_by_sess_ebi(sess,
|
||||
rsp->bearer_contexts_created.eps_bearer_id.u8);
|
||||
ogs_assert(bearer);
|
||||
s1u_tunnel = sgw_s1u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s1u_tunnel);
|
||||
s5u_tunnel = sgw_s5u_tunnel_in_bearer(bearer);
|
||||
ogs_assert(s5u_tunnel);
|
||||
|
||||
sgw_ue = sess->sgw_ue;
|
||||
ogs_assert(sgw_ue);
|
||||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
@ -162,54 +208,58 @@ void sgw_s5c_handle_delete_session_response(ogs_gtp_xact_t *s5c_xact,
|
|||
ogs_gtp_xact_t *s11_xact = NULL;
|
||||
ogs_gtp_delete_session_response_t *rsp = NULL;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
uint32_t mme_s11_teid;
|
||||
ogs_gtp_cause_t *cause = NULL;
|
||||
sgw_ue_t *sgw_ue = NULL;
|
||||
|
||||
ogs_assert(sess);
|
||||
sgw_ue = sess->sgw_ue;
|
||||
ogs_assert(s5c_xact);
|
||||
s11_xact = s5c_xact->assoc_xact;
|
||||
ogs_assert(s11_xact);
|
||||
ogs_assert(gtp_message);
|
||||
|
||||
rsp = >p_message->delete_session_response;
|
||||
ogs_debug("[SGW] Delete Session Response");
|
||||
|
||||
rsp = >p_message->delete_session_response;
|
||||
if (rsp->cause.presence == 0) {
|
||||
ogs_error("No Cause");
|
||||
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
|
||||
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_MANDATORY_IE_MISSING);
|
||||
return;
|
||||
}
|
||||
|
||||
cause = rsp->cause.data;
|
||||
ogs_assert(cause);
|
||||
|
||||
/* Remove a pgw session */
|
||||
if (sess) {
|
||||
ogs_debug("[SGW] Delete Session Response");
|
||||
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);
|
||||
|
||||
/* backup sgw_s5c_teid in session context */
|
||||
mme_s11_teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
if (sgw_sess_remove(sess) != OGS_OK)
|
||||
{
|
||||
ogs_error("Error on PGW session removal");
|
||||
cause->value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
} else {
|
||||
cause->value = OGS_GTP_CAUSE_INVALID_PEER;
|
||||
ogs_error("Cannot find session");
|
||||
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");
|
||||
SEND_ERROR_MESSAGE(s11_xact, sgw_ue,
|
||||
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP_CAUSE_CONTEXT_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
sgw_ue = sess->sgw_ue;
|
||||
ogs_assert(sgw_ue);
|
||||
|
||||
/* Remove a pgw session */
|
||||
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);
|
||||
|
||||
sgw_sess_remove(sess);
|
||||
|
||||
rv = ogs_gtp_xact_commit(s5c_xact);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
gtp_message->h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE;
|
||||
gtp_message->h.teid = mme_s11_teid;
|
||||
gtp_message->h.teid = sgw_ue->mme_s11_teid;
|
||||
|
||||
rv = ogs_gtp_build_msg(&pkbuf, gtp_message);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
|
|
@ -49,7 +49,6 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
|
|||
sgw_ue_t *sgw_ue = NULL;
|
||||
sgw_sess_t *sess = NULL;
|
||||
sgw_bearer_t *bearer = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_gtp_node_t *gnode = NULL;
|
||||
|
||||
sgw_sm_debug(e);
|
||||
|
@ -74,39 +73,6 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
|
|||
rv = ogs_gtp_parse_msg(&message, pkbuf);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
addr = e->addr;
|
||||
ogs_assert(addr);
|
||||
ogs_free(e->addr);
|
||||
|
||||
/*
|
||||
* 5.5.2 in spec 29.274
|
||||
*
|
||||
* If a peer's TEID is not available, the TEID field still shall be
|
||||
* present in the header and its value shall be set to "0" in the
|
||||
* following messages:
|
||||
*
|
||||
* - Create Session Request message on S2a/S2b/S5/S8
|
||||
*
|
||||
* - Create Session Request message on S4/S11, if for a given UE,
|
||||
* the SGSN/MME has not yet obtained the Control TEID of the SGW.
|
||||
*
|
||||
* - If a node receives a message and the TEID-C in the GTPv2 header of
|
||||
* the received message is not known, it shall respond with
|
||||
* "Context not found" Cause in the corresponding response message
|
||||
* to the sender, the TEID used in the GTPv2-C header in the response
|
||||
* message shall be then set to zero.
|
||||
*
|
||||
* - If a node receives a request message containing protocol error,
|
||||
* e.g. Mandatory IE missing, which requires the receiver to reject
|
||||
* the message as specified in clause 7.7, it shall reject
|
||||
* the request message. For the response message, the node should
|
||||
* look up the remote peer's TEID and accordingly set the GTPv2-C
|
||||
* header TEID and the message cause code. As an implementation
|
||||
* option, the node may not look up the remote peer's TEID and
|
||||
* set the GTPv2-C header TEID to zero in the response message.
|
||||
* However in this case, the cause code shall not be set to
|
||||
* "Context not found".
|
||||
*/
|
||||
if (message.h.teid != 0) {
|
||||
/* Cause is not "Context not found" */
|
||||
sgw_ue = sgw_ue_find_by_teid(message.h.teid);
|
||||
|
@ -115,20 +81,10 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
|
|||
if (sgw_ue) {
|
||||
gnode = sgw_ue->gnode;
|
||||
ogs_assert(gnode);
|
||||
|
||||
} else {
|
||||
ogs_assert(e->addr);
|
||||
|
||||
gnode = ogs_gtp_node_find_by_addr(
|
||||
&sgw_self()->mme_s11_list, e->addr);
|
||||
if (!gnode) {
|
||||
gnode = ogs_gtp_node_add_by_addr(
|
||||
&sgw_self()->mme_s11_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) {
|
||||
|
@ -200,35 +156,6 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
|
|||
rv = ogs_gtp_parse_msg(&message, pkbuf);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
/*
|
||||
* 5.5.2 in spec 29.274
|
||||
*
|
||||
* If a peer's TEID is not available, the TEID field still shall be
|
||||
* present in the header and its value shall be set to "0" in the
|
||||
* following messages:
|
||||
*
|
||||
* - Create Session Request message on S2a/S2b/S5/S8
|
||||
*
|
||||
* - Create Session Request message on S4/S11, if for a given UE,
|
||||
* the SGSN/MME has not yet obtained the Control TEID of the SGW.
|
||||
*
|
||||
* - If a node receives a message and the TEID-C in the GTPv2 header of
|
||||
* the received message is not known, it shall respond with
|
||||
* "Context not found" Cause in the corresponding response message
|
||||
* to the sender, the TEID used in the GTPv2-C header in the response
|
||||
* message shall be then set to zero.
|
||||
*
|
||||
* - If a node receives a request message containing protocol error,
|
||||
* e.g. Mandatory IE missing, which requires the receiver to reject
|
||||
* the message as specified in clause 7.7, it shall reject
|
||||
* the request message. For the response message, the node should
|
||||
* look up the remote peer's TEID and accordingly set the GTPv2-C
|
||||
* header TEID and the message cause code. As an implementation
|
||||
* option, the node may not look up the remote peer's TEID and
|
||||
* set the GTPv2-C header TEID to zero in the response message.
|
||||
* However in this case, the cause code shall not be set to
|
||||
* "Context not found".
|
||||
*/
|
||||
if (message.h.teid != 0) {
|
||||
sess = sgw_sess_find_by_teid(message.h.teid);
|
||||
}
|
||||
|
@ -236,15 +163,10 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
|
|||
if (sess) {
|
||||
gnode = sess->gnode;
|
||||
ogs_assert(gnode);
|
||||
|
||||
} else {
|
||||
ogs_assert(e->addr);
|
||||
|
||||
gnode = ogs_gtp_node_find_by_addr(
|
||||
&sgw_self()->pgw_s5c_list, e->addr);
|
||||
gnode = e->gnode;
|
||||
ogs_assert(gnode);
|
||||
}
|
||||
ogs_free(e->addr);
|
||||
|
||||
rv = ogs_gtp_xact_receive(gnode, &message.h, &xact);
|
||||
if (rv != OGS_OK) {
|
||||
|
|
Loading…
Reference in New Issue