diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 89a453efe..9ff3f5cc4 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -86,6 +86,9 @@ typedef struct ogs_gtp_xact_s { ogs_timer_t *tm_holding; /**< Timer waiting for holding message */ uint8_t holding_rcount; + uint32_t local_teid; /**< Local TEID, + expected in reply from peer */ + void *assoc_xact; /**< Associated GTP transaction */ void *pfcp_xact; /**< Associated PFCP transaction */ diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index 3eaa3d07b..bd03a9ab1 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -65,7 +65,8 @@ typedef struct ogs_pfcp_xact_s { ogs_timer_t *tm_delayed_commit; /**< Timer waiting for commit xact */ - uint64_t local_seid; /**< Local SEID, expected in reply from peer */ + uint64_t local_seid; /**< Local SEID, + expected in reply from peer */ void *assoc_xact; /**< Associated GTP transaction */ ogs_pkbuf_t *gtpbuf; /**< GTP packet buffer */ diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index 581799352..688a0aaac 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -228,6 +228,7 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action) xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->create_action = create_action; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -260,6 +261,7 @@ int mme_gtp_send_modify_bearer_request( xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); xact->modify_action = modify_action; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -292,6 +294,7 @@ int mme_gtp_send_delete_session_request( xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, s11buf, timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->delete_action = action; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -470,6 +473,7 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action) xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); xact->release_action = action; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -586,6 +590,7 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -618,6 +623,7 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); xact->delete_indirect_action = action; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -652,6 +658,7 @@ int mme_gtp_send_bearer_resource_command( xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); xact->xid |= OGS_GTP_CMD_XACT_ID; + xact->local_teid = mme_ue->mme_s11_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 799f51a74..33bf3f913 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -562,6 +562,13 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { /* Cause is not "Context not found" */ mme_ue = mme_ue_find_by_teid(gtp_message.h.teid); + } else if (xact->local_teid) { /* rx no TEID or TEID=0 */ + /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some + * conditions, such as cause "Session context not found". In those + * cases, we still want to identify the local session which + * originated the message, so try harder by using the TEID we + * locally stored in xact when sending the original request: */ + mme_ue = mme_ue_find_by_teid(xact->local_teid); } switch (gtp_message.h.type) { @@ -572,14 +579,17 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) mme_s11_handle_echo_response(xact, >p_message.echo_response); break; case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_create_session_response( xact, mme_ue, >p_message.create_session_response); break; case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_modify_bearer_response( xact, mme_ue, >p_message.modify_bearer_response); break; case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_delete_session_response( xact, mme_ue, >p_message.delete_session_response); break; @@ -596,6 +606,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) xact, mme_ue, >p_message.delete_bearer_request); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_release_access_bearers_response( xact, mme_ue, >p_message.release_access_bearers_response); break; @@ -604,16 +615,19 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) xact, mme_ue, >p_message.downlink_data_notification); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_create_indirect_data_forwarding_tunnel_response( xact, mme_ue, >p_message.create_indirect_data_forwarding_tunnel_response); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( xact, mme_ue, >p_message.delete_indirect_data_forwarding_tunnel_response); break; case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); mme_s11_handle_bearer_resource_failure_indication( xact, mme_ue, >p_message.bearer_resource_failure_indication); diff --git a/src/sgwc/pfcp-sm.c b/src/sgwc/pfcp-sm.c index 76bdb8371..f232dc20e 100644 --- a/src/sgwc/pfcp-sm.c +++ b/src/sgwc/pfcp-sm.c @@ -190,7 +190,7 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) * conditions, such as cause "Session context not found". In those * cases, we still want to identify the local session which * originated the message, so try harder by using the SEID we - * locacally stored in xact when sending the original request: */ + * locally stored in xact when sending the original request: */ sess = sgwc_sess_find_by_seid(xact->local_seid); } diff --git a/src/sgwc/sgwc-sm.c b/src/sgwc/sgwc-sm.c index 2dc8ab197..7265f95a8 100644 --- a/src/sgwc/sgwc-sm.c +++ b/src/sgwc/sgwc-sm.c @@ -157,6 +157,13 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { /* Cause is not "Context not found" */ sgwc_ue = sgwc_ue_find_by_teid(gtp_message.h.teid); + } else if (gtp_xact->local_teid) { /* rx no TEID or TEID=0 */ + /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some + * conditions, such as cause "Session context not found". In those + * cases, we still want to identify the local session which + * originated the message, so try harder by using the TEID we + * locally stored in xact when sending the original request: */ + sgwc_ue = sgwc_ue_find_by_teid(gtp_xact->local_teid); } switch(gtp_message.h.type) { @@ -185,14 +192,17 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) sgwc_ue, gtp_xact, recvbuf, >p_message); break; case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); sgwc_s11_handle_create_bearer_response( sgwc_ue, gtp_xact, recvbuf, >p_message); break; case OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); sgwc_s11_handle_update_bearer_response( sgwc_ue, gtp_xact, recvbuf, >p_message); break; case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); sgwc_s11_handle_delete_bearer_response( sgwc_ue, gtp_xact, recvbuf, >p_message); break; @@ -245,6 +255,13 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { sess = sgwc_sess_find_by_teid(gtp_message.h.teid); + } else if (gtp_xact->local_teid) { /* rx no TEID or TEID=0 */ + /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some + * conditions, such as cause "Session context not found". In those + * cases, we still want to identify the local session which + * originated the message, so try harder by using the TEID we + * locally stored in xact when sending the original request: */ + sess = sgwc_sess_find_by_teid(gtp_xact->local_teid); } switch(gtp_message.h.type) { @@ -255,15 +272,18 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) sgwc_handle_echo_response(gtp_xact, >p_message.echo_response); break; case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); sgwc_s5c_handle_create_session_response( sess, gtp_xact, recvbuf, >p_message); break; - case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: - sgwc_s5c_handle_delete_session_response( + case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); + sgwc_s5c_handle_modify_bearer_response( sess, gtp_xact, recvbuf, >p_message); break; - case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: - sgwc_s5c_handle_modify_bearer_response( + case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); + sgwc_s5c_handle_delete_session_response( sess, gtp_xact, recvbuf, >p_message); break; case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: @@ -279,6 +299,7 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) sess, gtp_xact, recvbuf, >p_message); break; case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: + if (!gtp_message.h.teid_presence) ogs_error("No TEID"); sgwc_s5c_handle_bearer_resource_failure_indication( sess, gtp_xact, recvbuf, >p_message); break; diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index ca8841288..fe13b36cc 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -382,6 +382,7 @@ void sgwc_sxa_handle_session_establishment_response( s5c_xact = ogs_gtp_xact_local_create( sess->gnode, &send_message.h, pkbuf, sess_timeout, sess); ogs_expect_or_return(s5c_xact); + s5c_xact->local_teid = sess->sgw_s5c_teid; s5c_xact->modify_action = OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST; @@ -419,6 +420,7 @@ void sgwc_sxa_handle_session_establishment_response( s5c_xact = ogs_gtp_xact_local_create( sess->gnode, &recv_message->h, pkbuf, sess_timeout, sess); ogs_expect_or_return(s5c_xact); + s5c_xact->local_teid = sess->sgw_s5c_teid; } ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -752,6 +754,7 @@ void sgwc_sxa_handle_session_modification_response( s11_xact = ogs_gtp_xact_local_create(sgwc_ue->gnode, &recv_message->h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(s11_xact); + s11_xact->local_teid = sgwc_ue->sgw_s11_teid; ogs_gtp_xact_associate(s5c_xact, s11_xact); @@ -1041,6 +1044,7 @@ void sgwc_sxa_handle_session_modification_response( sess->gnode, &recv_message->h, pkbuf, sess_timeout, sess); ogs_expect_or_return(s5c_xact); + s5c_xact->local_teid = sess->sgw_s5c_teid; ogs_gtp_xact_associate(s11_xact, s5c_xact); diff --git a/src/smf/binding.c b/src/smf/binding.c index ef3922b07..9b3260b7d 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -369,6 +369,7 @@ void smf_bearer_binding(smf_sess_t *sess) xact = ogs_gtp_xact_local_create( sess->gnode, &h, pkbuf, gtp_bearer_timeout, bearer); ogs_expect_or_return(xact); + xact->local_teid = sess->smf_n4_teid; if (ogs_list_count(&bearer->pf_to_add_list) > 0) xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE; @@ -438,6 +439,7 @@ int smf_gtp2_send_create_bearer_request(smf_bearer_t *bearer) xact = ogs_gtp_xact_local_create( sess->gnode, &h, pkbuf, gtp_bearer_timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->local_teid = sess->smf_n4_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/smf/gtp-path.c b/src/smf/gtp-path.c index f4ef18e49..f5b35d7a7 100644 --- a/src/smf/gtp-path.c +++ b/src/smf/gtp-path.c @@ -542,6 +542,7 @@ int smf_gtp2_send_delete_bearer_request( xact = ogs_gtp_xact_local_create( sess->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->local_teid = sess->smf_n4_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 55cc78293..226c2fe54 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -192,7 +192,7 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) * conditions, such as cause "Session context not found". In those * cases, we still want to identify the local session which * originated the message, so try harder by using the SEID we - * locacally stored in xact when sending the original request: */ + * locally stored in xact when sending the original request: */ sess = smf_sess_find_by_seid(xact->local_seid); } if (sess) diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index a7d0e5232..82a821d6b 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -115,8 +115,15 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) } e->gtp_xact = gtp_xact; - if (gtp2_message.h.teid != 0) { + if (gtp2_message.h.teid_presence && gtp2_message.h.teid != 0) { sess = smf_sess_find_by_teid(gtp2_message.h.teid); + } else if (gtp_xact->local_teid) { /* rx no TEID or TEID=0 */ + /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some + * conditions, such as cause "Session context not found". In those + * cases, we still want to identify the local session which + * originated the message, so try harder by using the TEID we + * locally stored in xact when sending the original request: */ + sess = smf_sess_find_by_teid(gtp_xact->local_teid); } switch(gtp2_message.h.type) { @@ -161,16 +168,20 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) sess, gtp_xact, recvbuf, >p2_message.modify_bearer_request); break; case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: + if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); smf_s5c_handle_create_bearer_response( sess, gtp_xact, >p2_message.create_bearer_response); break; case OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE: + if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); smf_s5c_handle_update_bearer_response( sess, gtp_xact, >p2_message.update_bearer_response); break; case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: + if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); if (!sess) { /* TODO: NACK the message */ + ogs_error("TODO: NACK the message"); break; } e->sess = sess;