forked from acouzens/open5gs
[SMF] fix the crash during IMS calls (#1238)
If PFCP is not deactivated, some eNBs send an GTP error indication. To solve the problem, SMF deactivates the bearer that will be deleted.
This commit is contained in:
parent
d919b2744c
commit
fc8c807da2
|
@ -841,18 +841,25 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess)
|
|||
ogs_assert(sess);
|
||||
|
||||
ogs_pool_alloc(&ogs_pfcp_pdr_pool, &pdr);
|
||||
ogs_assert(pdr);
|
||||
if (pdr == NULL) {
|
||||
ogs_error("pdr_pool() failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(pdr, 0, sizeof *pdr);
|
||||
|
||||
ogs_pool_alloc(&sess->pdr_id_pool, &pdr->id_node);
|
||||
if (pdr->id_node == NULL) {
|
||||
ogs_error("pdr_id_pool() failed");
|
||||
ogs_pool_free(&ogs_pfcp_pdr_pool, pdr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdr->obj.type = OGS_PFCP_OBJ_PDR_TYPE;
|
||||
|
||||
pdr->index = ogs_pool_index(&ogs_pfcp_pdr_pool, pdr);
|
||||
ogs_assert(pdr->index > 0 &&
|
||||
pdr->index <= ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR);
|
||||
|
||||
ogs_pool_alloc(&sess->pdr_id_pool, &pdr->id_node);
|
||||
ogs_assert(pdr->id_node);
|
||||
|
||||
pdr->id = *(pdr->id_node);
|
||||
ogs_assert(pdr->id > 0 && pdr->id <= OGS_MAX_NUM_OF_PDR);
|
||||
|
||||
|
@ -1018,11 +1025,18 @@ ogs_pfcp_far_t *ogs_pfcp_far_add(ogs_pfcp_sess_t *sess)
|
|||
ogs_assert(sess);
|
||||
|
||||
ogs_pool_alloc(&ogs_pfcp_far_pool, &far);
|
||||
ogs_assert(far);
|
||||
if (far == NULL) {
|
||||
ogs_error("far_pool() failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(far, 0, sizeof *far);
|
||||
|
||||
ogs_pool_alloc(&sess->far_id_pool, &far->id_node);
|
||||
ogs_assert(far->id_node);
|
||||
if (far->id_node == NULL) {
|
||||
ogs_error("far_id_pool() failed");
|
||||
ogs_pool_free(&ogs_pfcp_far_pool, far);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
far->id = *(far->id_node);
|
||||
ogs_assert(far->id > 0 && far->id <= OGS_MAX_NUM_OF_FAR);
|
||||
|
@ -1229,11 +1243,18 @@ ogs_pfcp_urr_t *ogs_pfcp_urr_add(ogs_pfcp_sess_t *sess)
|
|||
ogs_assert(sess);
|
||||
|
||||
ogs_pool_alloc(&ogs_pfcp_urr_pool, &urr);
|
||||
ogs_assert(urr);
|
||||
if (urr == NULL) {
|
||||
ogs_error("urr_pool() failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(urr, 0, sizeof *urr);
|
||||
|
||||
ogs_pool_alloc(&sess->urr_id_pool, &urr->id_node);
|
||||
ogs_assert(urr->id_node);
|
||||
if (urr->id_node == NULL) {
|
||||
ogs_error("urr_id_pool() failed");
|
||||
ogs_pool_free(&ogs_pfcp_urr_pool, urr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
urr->id = *(urr->id_node);
|
||||
ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR);
|
||||
|
@ -1307,11 +1328,18 @@ ogs_pfcp_qer_t *ogs_pfcp_qer_add(ogs_pfcp_sess_t *sess)
|
|||
ogs_assert(sess);
|
||||
|
||||
ogs_pool_alloc(&ogs_pfcp_qer_pool, &qer);
|
||||
ogs_assert(qer);
|
||||
if (qer == NULL) {
|
||||
ogs_error("qer_pool() failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(qer, 0, sizeof *qer);
|
||||
|
||||
ogs_pool_alloc(&sess->qer_id_pool, &qer->id_node);
|
||||
ogs_assert(qer->id_node);
|
||||
if (qer->id_node == NULL) {
|
||||
ogs_error("qer_id_pool() failed");
|
||||
ogs_pool_free(&ogs_pfcp_qer_pool, qer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qer->id = *(qer->id_node);
|
||||
ogs_assert(qer->id > 0 && qer->id <= OGS_MAX_NUM_OF_QER);
|
||||
|
|
|
@ -66,6 +66,9 @@ typedef struct ogs_pfcp_xact_s {
|
|||
void *assoc_xact; /**< Associated GTP transaction */
|
||||
ogs_pkbuf_t *gtpbuf; /**< GTP packet buffer */
|
||||
|
||||
uint8_t gtp_pti; /**< GTP Procedure transaction identity */
|
||||
uint8_t gtp_cause; /**< GTP Cause Value */
|
||||
|
||||
void *assoc_stream; /**< Associated SBI session */
|
||||
|
||||
bool epc; /**< EPC or 5GC */
|
||||
|
|
|
@ -48,7 +48,9 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data)
|
|||
}
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_REMOVE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
break;
|
||||
case OGS_GTP_UPDATE_BEARER_REQUEST_TYPE:
|
||||
ogs_error("[%s] No Update Bearer Response", smf_ue->imsi_bcd);
|
||||
|
@ -143,6 +145,13 @@ void smf_bearer_binding(smf_sess_t *sess)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ogs_list_count(&sess->bearer_list) >=
|
||||
OGS_MAX_NUM_OF_BEARER) {
|
||||
ogs_error("Bearer Overflow[%d]",
|
||||
ogs_list_count(&sess->bearer_list));
|
||||
continue;
|
||||
}
|
||||
|
||||
bearer = smf_bearer_add(sess);
|
||||
ogs_assert(bearer);
|
||||
|
||||
|
@ -323,7 +332,9 @@ void smf_bearer_binding(smf_sess_t *sess)
|
|||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_CREATE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_CREATE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
} else {
|
||||
ogs_gtp_tft_t tft;
|
||||
|
||||
|
@ -368,9 +379,20 @@ void smf_bearer_binding(smf_sess_t *sess)
|
|||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* TS23.214
|
||||
* 6.3.1.7 Procedures with modification of bearer
|
||||
* p50
|
||||
* 2. ...
|
||||
* For "PGW/MME initiated bearer deactivation procedure",
|
||||
* PGW-C shall indicate PGW-U to stop counting and stop
|
||||
* forwarding downlink packets for the affected bearer(s).
|
||||
*/
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_gtp_send_delete_bearer_request(
|
||||
bearer, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
} else {
|
||||
ogs_error("Invalid Type[%d]", pcc_rule->type);
|
||||
|
@ -445,6 +467,13 @@ void smf_qos_flow_binding(smf_sess_t *sess)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ogs_list_count(&sess->bearer_list) >=
|
||||
OGS_MAX_NUM_OF_BEARER) {
|
||||
ogs_error("QosFlow Overflow[%d]",
|
||||
ogs_list_count(&sess->bearer_list));
|
||||
continue;
|
||||
}
|
||||
|
||||
qos_flow = smf_qos_flow_add(sess);
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ typedef struct smf_sess_s {
|
|||
|
||||
char *sm_context_ref; /* smContextRef */
|
||||
uint8_t psi; /* PDU session identity */
|
||||
uint8_t pti; /* Procedure transaction identity */
|
||||
uint8_t pti; /* 5GS-NAS : Procedure transaction identity */
|
||||
|
||||
char *sm_context_status_uri; /* SmContextStatusNotification */
|
||||
struct {
|
||||
|
|
|
@ -510,7 +510,9 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data)
|
|||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_REMOVE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
break;
|
||||
default:
|
||||
ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]",
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "context.h"
|
||||
#include "timer.h"
|
||||
#include "s5c-build.h"
|
||||
#include "pfcp-path.h"
|
||||
#include "gtp-path.h"
|
||||
#include "n4-handler.h"
|
||||
|
@ -230,8 +231,14 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
/* 'stream' could be NULL in smf_qos_flow_binding() */
|
||||
stream = xact->assoc_stream;
|
||||
|
||||
/* If smf_5gc_pfcp_send_qos_flow_modification_request() is called */
|
||||
qos_flow = xact->data;
|
||||
if (flags & OGS_PFCP_MODIFY_SESSION) {
|
||||
/* If smf_5gc_pfcp_send_session_modification_request() is called */
|
||||
|
||||
} else {
|
||||
/* If smf_5gc_pfcp_send_qos_flow_modification_request() is called */
|
||||
qos_flow = xact->data;
|
||||
ogs_assert(qos_flow);
|
||||
}
|
||||
|
||||
ogs_pfcp_xact_commit(xact);
|
||||
|
||||
|
@ -411,6 +418,8 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
} else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
|
||||
param.n1smbuf = gsm_build_qos_flow_modification_command(
|
||||
|
@ -432,6 +441,7 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL;
|
||||
|
||||
ogs_assert(stream);
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
n1smbuf = gsm_build_qos_flow_modification_command(
|
||||
qos_flow, sess->pti,
|
||||
|
@ -464,6 +474,8 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
} else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
|
||||
param.n1smbuf = gsm_build_qos_flow_modification_command(
|
||||
|
@ -510,6 +522,8 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
}
|
||||
|
||||
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
|
||||
param.n1smbuf = gsm_build_qos_flow_modification_command(
|
||||
|
@ -528,6 +542,7 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL;
|
||||
|
||||
ogs_assert(stream);
|
||||
ogs_assert(qos_flow);
|
||||
|
||||
n1smbuf = gsm_build_qos_flow_modification_command(
|
||||
qos_flow, sess->pti,
|
||||
|
@ -612,7 +627,6 @@ void smf_5gc_n4_handle_session_deletion_response(
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
||||
|
@ -730,24 +744,27 @@ void smf_epc_n4_handle_session_establishment_response(
|
|||
ogs_assert(far);
|
||||
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
|
||||
smf_bearer_t *pdr_bearer = NULL;
|
||||
|
||||
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
|
||||
ogs_pfcp_far_teid_hash_set(far);
|
||||
|
||||
bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
|
||||
if (bearer) {
|
||||
pdr_bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
|
||||
if (pdr_bearer) {
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
if (bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(bearer->pgw_s5u_addr);
|
||||
if (bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(bearer->pgw_s5u_addr6);
|
||||
if (pdr_bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr);
|
||||
if (pdr_bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr6);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_pfcp_f_teid_to_sockaddr(
|
||||
&pdr->f_teid, pdr->f_teid_len,
|
||||
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6));
|
||||
bearer->pgw_s5u_teid = pdr->f_teid.teid;
|
||||
&pdr_bearer->pgw_s5u_addr,
|
||||
&pdr_bearer->pgw_s5u_addr6));
|
||||
pdr_bearer->pgw_s5u_teid = pdr->f_teid.teid;
|
||||
}
|
||||
}
|
||||
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
|
||||
|
@ -784,23 +801,28 @@ void smf_epc_n4_handle_session_establishment_response(
|
|||
ogs_assert(OGS_OK == smf_gtp_send_create_session_response(sess, gtp_xact));
|
||||
|
||||
if (sess->gtp_rat_type == OGS_GTP_RAT_TYPE_WLAN) {
|
||||
/*
|
||||
* TS23.214
|
||||
* 6.3.1.7 Procedures with modification of bearer
|
||||
* p50
|
||||
* 2. ...
|
||||
* For "PGW/MME initiated bearer deactivation procedure",
|
||||
* PGW-C shall indicate PGW-U to stop counting and stop
|
||||
* forwarding downlink packets for the affected bearer(s).
|
||||
*/
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
smf_sess_t *eutran_sess = NULL;
|
||||
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
ogs_assert(sess->session.name);
|
||||
eutran_sess = smf_sess_find_by_apn(
|
||||
smf_ue, sess->session.name, OGS_GTP_RAT_TYPE_EUTRAN);
|
||||
smf_ue, sess->session.name, OGS_GTP_RAT_TYPE_EUTRAN);
|
||||
if (eutran_sess) {
|
||||
smf_bearer_t *eutran_linked_bearer =
|
||||
ogs_list_first(&eutran_sess->bearer_list);
|
||||
ogs_assert(eutran_linked_bearer);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_gtp_send_delete_bearer_request(
|
||||
eutran_linked_bearer,
|
||||
smf_epc_pfcp_send_session_modification_request(
|
||||
eutran_sess, NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP));
|
||||
}
|
||||
|
@ -816,6 +838,9 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
int i;
|
||||
|
||||
smf_bearer_t *bearer = NULL;
|
||||
ogs_gtp_xact_t *gtp_xact = NULL;
|
||||
uint8_t gtp_pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
||||
uint8_t gtp_cause = OGS_GTP_CAUSE_UNDEFINED_VALUE;
|
||||
uint64_t flags = 0;
|
||||
|
||||
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
||||
|
@ -824,11 +849,21 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
ogs_assert(xact);
|
||||
ogs_assert(rsp);
|
||||
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
if (flags & OGS_PFCP_MODIFY_SESSION) {
|
||||
/* If smf_epc_pfcp_send_session_modification_request() is called */
|
||||
|
||||
} else {
|
||||
/* If smf_epc_pfcp_send_bearer_modification_request() is called */
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
}
|
||||
flags = xact->modify_flags;
|
||||
ogs_assert(flags);
|
||||
|
||||
gtp_xact = xact->assoc_xact;
|
||||
gtp_pti = xact->gtp_pti;
|
||||
gtp_cause = xact->gtp_cause;
|
||||
|
||||
ogs_pfcp_xact_commit(xact);
|
||||
|
||||
if (!sess) {
|
||||
|
@ -864,22 +899,28 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
ogs_assert(far);
|
||||
|
||||
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
|
||||
smf_bearer_t *pdr_bearer = NULL;
|
||||
|
||||
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
|
||||
ogs_pfcp_far_teid_hash_set(far);
|
||||
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
if (bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(bearer->pgw_s5u_addr);
|
||||
if (bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(bearer->pgw_s5u_addr6);
|
||||
pdr_bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
|
||||
if (pdr_bearer) {
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (sess->pfcp_node->up_function_features.ftup &&
|
||||
pdr->f_teid_len) {
|
||||
if (pdr_bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr);
|
||||
if (pdr_bearer->pgw_s5u_addr)
|
||||
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr6);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_pfcp_f_teid_to_sockaddr(
|
||||
&pdr->f_teid, pdr->f_teid_len,
|
||||
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6));
|
||||
bearer->pgw_s5u_teid = pdr->f_teid.teid;
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_pfcp_f_teid_to_sockaddr(
|
||||
&pdr->f_teid, pdr->f_teid_len,
|
||||
&pdr_bearer->pgw_s5u_addr,
|
||||
&pdr_bearer->pgw_s5u_addr6));
|
||||
pdr_bearer->pgw_s5u_teid = pdr->f_teid.teid;
|
||||
}
|
||||
}
|
||||
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
|
||||
ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr));
|
||||
|
@ -892,11 +933,101 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
}
|
||||
|
||||
if (flags & OGS_PFCP_MODIFY_REMOVE) {
|
||||
ogs_assert(bearer);
|
||||
smf_bearer_remove(bearer);
|
||||
|
||||
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
|
||||
ogs_assert(bearer);
|
||||
ogs_assert(OGS_OK == smf_gtp_send_create_bearer_request(bearer));
|
||||
|
||||
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
|
||||
/*
|
||||
* TS23.214
|
||||
* 6.3.1.7 Procedures with modification of bearer
|
||||
* p50
|
||||
* 2. ...
|
||||
* For "PGW/MME initiated bearer deactivation procedure",
|
||||
* PGW-C shall indicate PGW-U to stop counting and stop
|
||||
* forwarding downlink packets for the affected bearer(s).
|
||||
*/
|
||||
if (gtp_xact) {
|
||||
/*
|
||||
* 1. MME sends Bearer Resource Command to SGW/SMF.
|
||||
* 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
|
||||
* 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
|
||||
*/
|
||||
ogs_gtp_header_t h;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
int rv;
|
||||
|
||||
ogs_assert(bearer);
|
||||
|
||||
memset(&h, 0, sizeof(ogs_gtp_header_t));
|
||||
h.teid = sess->sgw_s5c_teid;
|
||||
h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE;
|
||||
|
||||
pkbuf = smf_s5c_build_delete_bearer_request(
|
||||
h.type, bearer, gtp_pti, gtp_cause);
|
||||
ogs_expect_or_return(pkbuf);
|
||||
|
||||
rv = ogs_gtp_xact_update_tx(gtp_xact, &h, pkbuf);
|
||||
ogs_expect_or_return(rv == OGS_OK);
|
||||
|
||||
/* IMPORTANT:
|
||||
*
|
||||
* When initiaited by Bearer Resource Command,
|
||||
* there must be bearer context in the Transaction.
|
||||
* Otherwise, the bearer context cannot be found
|
||||
* in GTP response message.
|
||||
*
|
||||
* For example,
|
||||
* 1. MME sends Bearer Resource Command to SGW-C, SMF.
|
||||
* 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME.
|
||||
* 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF.
|
||||
*
|
||||
* On number 3 step, if MME sends Response without Bearer Context,
|
||||
* we need a way to find Bearer context.
|
||||
*
|
||||
* To do this, I saved Bearer Context in Transaction Context.
|
||||
*/
|
||||
gtp_xact->data = bearer;
|
||||
|
||||
rv = ogs_gtp_xact_commit(gtp_xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
|
||||
} else {
|
||||
if (flags & OGS_PFCP_MODIFY_SESSION) {
|
||||
/*
|
||||
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME.
|
||||
* 2. MME sends Delete Bearer Response to SGW/SMF.
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG.
|
||||
* 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF.
|
||||
*/
|
||||
smf_bearer_t *linked_bearer =
|
||||
ogs_list_first(&sess->bearer_list);
|
||||
ogs_assert(linked_bearer);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_gtp_send_delete_bearer_request(
|
||||
linked_bearer, gtp_pti, gtp_cause));
|
||||
} else {
|
||||
/*
|
||||
* 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME.
|
||||
* 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF.
|
||||
*/
|
||||
ogs_assert(bearer);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_gtp_send_delete_bearer_request(
|
||||
bearer,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
gtp_cause));
|
||||
}
|
||||
}
|
||||
|
||||
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||
/* Nothing */
|
||||
}
|
||||
|
|
|
@ -265,6 +265,9 @@ static void sess_epc_timeout(ogs_pfcp_xact_t *xact, void *data)
|
|||
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
|
||||
ogs_warn("No PFCP session establishment response");
|
||||
break;
|
||||
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
||||
ogs_error("No PFCP session modification response");
|
||||
break;
|
||||
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
|
||||
ogs_error("No PFCP session deletion response");
|
||||
break;
|
||||
|
@ -451,8 +454,44 @@ int smf_epc_pfcp_send_session_establishment_request(
|
|||
return rv;
|
||||
}
|
||||
|
||||
int smf_epc_pfcp_send_session_modification_request(
|
||||
smf_sess_t *sess, void *gtp_xact,
|
||||
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *n4buf = NULL;
|
||||
ogs_pfcp_header_t h;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
||||
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
|
||||
h.seid = sess->upf_n4_seid;
|
||||
|
||||
n4buf = smf_n4_build_session_modification_request(h.type, sess, flags);
|
||||
ogs_expect_or_return_val(n4buf, OGS_ERROR);
|
||||
|
||||
xact = ogs_pfcp_xact_local_create(
|
||||
sess->pfcp_node, &h, n4buf, sess_epc_timeout, sess);
|
||||
ogs_expect_or_return_val(xact, OGS_ERROR);
|
||||
|
||||
xact->epc = true; /* EPC PFCP transaction */
|
||||
xact->assoc_xact = gtp_xact;
|
||||
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
|
||||
|
||||
xact->gtp_pti = gtp_pti;
|
||||
xact->gtp_cause = gtp_cause;
|
||||
|
||||
rv = ogs_pfcp_xact_commit(xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int smf_epc_pfcp_send_bearer_modification_request(
|
||||
smf_bearer_t *bearer, uint64_t flags)
|
||||
smf_bearer_t *bearer, void *gtp_xact,
|
||||
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *n4buf = NULL;
|
||||
|
@ -476,8 +515,12 @@ int smf_epc_pfcp_send_bearer_modification_request(
|
|||
ogs_expect_or_return_val(xact, OGS_ERROR);
|
||||
|
||||
xact->epc = true; /* EPC PFCP transaction */
|
||||
xact->assoc_xact = gtp_xact;
|
||||
xact->modify_flags = flags;
|
||||
|
||||
xact->gtp_pti = gtp_pti;
|
||||
xact->gtp_cause = gtp_cause;
|
||||
|
||||
rv = ogs_pfcp_xact_commit(xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
|
||||
|
|
|
@ -41,8 +41,12 @@ int smf_5gc_pfcp_send_session_deletion_request(
|
|||
|
||||
int smf_epc_pfcp_send_session_establishment_request(
|
||||
smf_sess_t *sess, void *gtp_xact);
|
||||
int smf_epc_pfcp_send_session_modification_request(
|
||||
smf_sess_t *sess, void *gtp_xact,
|
||||
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause);
|
||||
int smf_epc_pfcp_send_bearer_modification_request(
|
||||
smf_bearer_t *bearer, uint64_t flags);
|
||||
smf_bearer_t *bearer, void *gtp_xact,
|
||||
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause);
|
||||
int smf_epc_pfcp_send_session_deletion_request(
|
||||
smf_sess_t *sess, void *gtp_xact);
|
||||
|
||||
|
|
|
@ -448,8 +448,9 @@ void smf_s5c_handle_modify_bearer_request(
|
|||
ogs_expect_or_return(ogs_list_first(&wlan_sess->bearer_list));
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_gtp_send_delete_bearer_request(
|
||||
ogs_list_first(&wlan_sess->bearer_list),
|
||||
smf_epc_pfcp_send_session_modification_request(
|
||||
wlan_sess, NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP));
|
||||
}
|
||||
|
@ -468,6 +469,9 @@ void smf_s5c_handle_create_bearer_response(
|
|||
ogs_assert(xact);
|
||||
ogs_assert(rsp);
|
||||
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
|
||||
ogs_debug("Create Bearer Response");
|
||||
|
||||
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
|
||||
|
@ -509,9 +513,6 @@ void smf_s5c_handle_create_bearer_response(
|
|||
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context in TEID");
|
||||
|
||||
|
@ -547,7 +548,9 @@ void smf_s5c_handle_create_bearer_response(
|
|||
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_REMOVE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -583,7 +586,9 @@ void smf_s5c_handle_create_bearer_response(
|
|||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_ACTIVATE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_ACTIVATE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
}
|
||||
|
||||
void smf_s5c_handle_update_bearer_response(
|
||||
|
@ -601,6 +606,9 @@ void smf_s5c_handle_update_bearer_response(
|
|||
gtp_flags = xact->update_flags;
|
||||
ogs_assert(gtp_flags);
|
||||
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
|
||||
ogs_debug("Update Bearer Response");
|
||||
|
||||
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
|
||||
|
@ -617,9 +625,6 @@ void smf_s5c_handle_update_bearer_response(
|
|||
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
bearer = xact->data;
|
||||
ogs_assert(bearer);
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context in TEID");
|
||||
|
||||
|
@ -674,7 +679,10 @@ void smf_s5c_handle_update_bearer_response(
|
|||
|
||||
if (pfcp_flags)
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(bearer, pfcp_flags));
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, NULL, pfcp_flags,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
}
|
||||
|
||||
void smf_s5c_handle_delete_bearer_response(
|
||||
|
@ -786,7 +794,9 @@ void smf_s5c_handle_delete_bearer_response(
|
|||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, OGS_PFCP_MODIFY_REMOVE));
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1134,21 +1144,28 @@ void smf_s5c_handle_bearer_resource_command(
|
|||
return;
|
||||
}
|
||||
|
||||
memset(&h, 0, sizeof(ogs_gtp_header_t));
|
||||
h.teid = sess->sgw_s5c_teid;
|
||||
|
||||
if (tft_delete) {
|
||||
h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE;
|
||||
pkbuf = smf_s5c_build_delete_bearer_request(
|
||||
h.type, bearer, cmd->procedure_transaction_id.u8,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE);
|
||||
ogs_expect_or_return(pkbuf);
|
||||
|
||||
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
|
||||
ogs_expect_or_return(rv == OGS_OK);
|
||||
/*
|
||||
* TS23.214
|
||||
* 6.3.1.7 Procedures with modification of bearer
|
||||
* p50
|
||||
* 2. ...
|
||||
* For "PGW/MME initiated bearer deactivation procedure",
|
||||
* PGW-C shall indicate PGW-U to stop counting and stop
|
||||
* forwarding downlink packets for the affected bearer(s).
|
||||
*/
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, xact,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
cmd->procedure_transaction_id.u8,
|
||||
OGS_GTP_CAUSE_UNDEFINED_VALUE));
|
||||
|
||||
} else {
|
||||
memset(&h, 0, sizeof(ogs_gtp_header_t));
|
||||
h.teid = sess->sgw_s5c_teid;
|
||||
h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE;
|
||||
|
||||
pkbuf = smf_s5c_build_update_bearer_request(
|
||||
h.type, bearer, cmd->procedure_transaction_id.u8,
|
||||
tft_update ? &tft : NULL, qos_update);
|
||||
|
@ -1161,26 +1178,26 @@ void smf_s5c_handle_bearer_resource_command(
|
|||
xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE;
|
||||
if (qos_update)
|
||||
xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE;
|
||||
|
||||
/* IMPORTANT:
|
||||
*
|
||||
* When initiaited by Bearer Resource Command, there must be bearer context
|
||||
* in the Transaction. Otherwise, the bearer context cannot be found
|
||||
* in GTP response message.
|
||||
*
|
||||
* For example,
|
||||
* 1. MME sends Bearer Resource Command to SGW-C, SMF.
|
||||
* 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME.
|
||||
* 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF.
|
||||
*
|
||||
* On number 3 step, if MME sends Response without Bearer Context,
|
||||
* we need a way to find Bearer context.
|
||||
*
|
||||
* To do this, I saved Bearer Context in Transaction Context.
|
||||
*/
|
||||
xact->data = bearer;
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
/* IMPORTANT:
|
||||
*
|
||||
* When initiaited by Bearer Resource Command, there must be bearer context
|
||||
* in the Transaction. Otherwise, the beare context cannot be found
|
||||
* in GTP response message.
|
||||
*
|
||||
* For example,
|
||||
* 1. MME sends Bearer Resource Command to SGW-C, SMF.
|
||||
* 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME.
|
||||
* 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF.
|
||||
*
|
||||
* On number 3 step, if MME sends Response without Bearer Context,
|
||||
* we need a way to find Bearer context.
|
||||
*
|
||||
* To do this, I saved Bearer Context in Transaction Context.
|
||||
*/
|
||||
xact->data = bearer;
|
||||
|
||||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue