diff --git a/src/smf/gn-handler.c b/src/smf/gn-handler.c index ac67887dce..c7481d917c 100644 --- a/src/smf/gn-handler.c +++ b/src/smf/gn-handler.c @@ -299,7 +299,7 @@ void smf_gn_handle_update_pdp_context_request( uint8_t cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED; ogs_gtp1_header_t h; - ogs_pkbuf_t *pkbuf = NULL; + ogs_pfcp_pdr_t *pdr = NULL; smf_bearer_t *bearer = NULL; smf_ue_t *smf_ue = NULL; @@ -356,6 +356,7 @@ void smf_gn_handle_update_pdp_context_request( ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, OGS_GTP1_UPDATE_PDP_CONTEXT_RESPONSE_TYPE, OGS_GTP1_CAUSE_NON_EXISTENT); + return; } } @@ -386,12 +387,43 @@ void smf_gn_handle_update_pdp_context_request( h.type = OGS_GTP1_UPDATE_PDP_CONTEXT_RESPONSE_TYPE; h.teid = sess->sgw_s5c_teid; - pkbuf = smf_gn_build_update_pdp_context_response(h.type, sess, bearer); - ogs_expect_or_return(pkbuf); + /* Set bearer so it's accessible later when handling PFCP Session Modification Response */ + xact->data = bearer; - rv = ogs_gtp1_xact_update_tx(xact, &h, pkbuf); - ogs_expect_or_return(rv == OGS_OK); + /* Update remote TEID and GTP-U IP address on the UPF. UpdatePDPContextResp + * will be sent when UPF answers back this request + */ + ogs_list_for_each(&sess->pfcp.pdr_list, pdr) { + ogs_pfcp_far_t *far = pdr->far; + ogs_assert(far); - rv = ogs_gtp_xact_commit(xact); - ogs_expect(rv == OGS_OK); + if (pdr->src_if != OGS_PFCP_INTERFACE_CORE || + far->dst_if != OGS_PFCP_INTERFACE_ACCESS) + continue; + if (!(far->apply_action & OGS_PFCP_APPLY_ACTION_FORW)) + continue; + + if (pdr->id == bearer->dl_pdr->id) { + rv = ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip, + &far->outer_header_creation, + &far->outer_header_creation_len); + ogs_assert(rv == OGS_OK); + far->outer_header_creation.teid = bearer->sgw_s5u_teid; + } + } + + rv = smf_epc_pfcp_send_session_modification_request(sess, xact, + OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP1_CAUSE_REACTIACTION_REQUESTED); + ogs_assert(rv == OGS_OK); + + /* TODO: TS 29.061: Upon reception of an UpdatePDPContextRequest from the + SGSN, the GGSN may send an Accounting Request (Interim) to the Diameter + server to update the necessary information related to this PDP context. */ + /* The P-GW need not wait for the Diameter Accounting Answer message from + the Diameter server before sending the response for the triggering + signalling message (e.g. Modify Bearer Response). The P-GW may delete the + bearer if the Accounting Answer is not received from the Diameter + server.*/ } diff --git a/src/smf/gtp-path.c b/src/smf/gtp-path.c index 35c2eb450d..da9e617f23 100644 --- a/src/smf/gtp-path.c +++ b/src/smf/gtp-path.c @@ -361,7 +361,7 @@ int smf_gtp1_send_delete_pdp_context_response( } #if 0 -int smf_gtp_send_update_pdp_context_request( +int smf_gtp1_send_update_pdp_context_request( smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value) { int rv; @@ -376,7 +376,7 @@ int smf_gtp_send_update_pdp_context_request( sess = bearer->sess; ogs_assert(sess); - memset(&h, 0, sizeof(ogs_gtp_header_t)); + memset(&h, 0, sizeof(ogs_gtp1_header_t)); h.type = OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE; h.teid = sess->sgw_s5c_teid; @@ -395,6 +395,38 @@ int smf_gtp_send_update_pdp_context_request( } #endif +int smf_gtp1_send_update_pdp_context_response( + smf_bearer_t *bearer, ogs_gtp_xact_t *xact) +{ + int rv; + + ogs_gtp1_header_t h; + ogs_pkbuf_t *pkbuf = NULL; + + smf_sess_t *sess = NULL; + + ogs_assert(bearer); + ogs_assert(xact); + sess = bearer->sess; + ogs_assert(sess); + + memset(&h, 0, sizeof(ogs_gtp1_header_t)); + h.type = OGS_GTP1_UPDATE_PDP_CONTEXT_RESPONSE_TYPE; + h.teid = sess->sgw_s5c_teid; + + pkbuf = smf_gn_build_update_pdp_context_response( + h.type, sess, bearer); + ogs_expect_or_return_val(pkbuf, OGS_ERROR); + + rv = ogs_gtp1_xact_update_tx(xact, &h, pkbuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + + rv = ogs_gtp_xact_commit(xact); + ogs_expect(rv == OGS_OK); + + return rv; +} + int smf_gtp_send_create_session_response( smf_sess_t *sess, ogs_gtp_xact_t *xact) { diff --git a/src/smf/gtp-path.h b/src/smf/gtp-path.h index b2520bc715..9673a055ad 100644 --- a/src/smf/gtp-path.h +++ b/src/smf/gtp-path.h @@ -33,8 +33,10 @@ int smf_gtp1_send_create_pdp_context_response( smf_sess_t *sess, ogs_gtp_xact_t *xact); int smf_gtp1_send_delete_pdp_context_response( smf_sess_t *sess, ogs_gtp_xact_t *xact); -int smf_gtp_send_update_pdp_context_request( +int smf_gtp1_send_update_pdp_context_request( smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value); +int smf_gtp1_send_update_pdp_context_response( + smf_bearer_t *bearer, ogs_gtp_xact_t *xact); int smf_gtp_send_create_session_response( smf_sess_t *sess, ogs_gtp_xact_t *xact); diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 6c1c6a39aa..5405a6fd46 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -1105,7 +1105,13 @@ void smf_epc_n4_handle_session_modification_response( } } else if (flags & OGS_PFCP_MODIFY_ACTIVATE) { - /* Nothing */ + /* SMF send Update PDP Context Response (GTPv1C) to SGSN */ + if (gtp_xact->gtp_version == 1) { + bearer = gtp_xact->data; + smf_gtp1_send_update_pdp_context_response(bearer, gtp_xact); + } else { + /* TODO: SMF send Modify Bearer Response (GTPv2C) to SGWC */ + } } } diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 721d05885a..20441af5e2 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -423,6 +423,10 @@ void smf_s5c_handle_modify_bearer_request( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); + /* TODO: Update remote GTP-U IP addr + TEID in the UPF through PFCP, similar + * to what is done in smf_gn_handle_update_pdp_context_request() + */ + memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_MODIFY_BEARER_RESPONSE_TYPE; h.teid = sess->sgw_s5c_teid;