forked from acouzens/open5gs
[SMF] Integrate session tear down cycle into sess->sm (#1500)
* [SMF] smf_sm.c Fix indentation * [SMF] gsm-sm: log fsm events * [SMF] Integrate session tear down cycle into sess->sm
This commit is contained in:
parent
79de674fd8
commit
2de12e32f4
|
@ -34,6 +34,14 @@ extern struct dict_object *ogs_diam_s6b_application;
|
|||
|
||||
extern struct dict_object *ogs_diam_s6b_mip6_feature_vector;
|
||||
|
||||
typedef struct ogs_diam_s6b_message_s {
|
||||
#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 1
|
||||
uint16_t cmd_code;
|
||||
uint32_t result_code;
|
||||
uint32_t *err;
|
||||
uint32_t *exp_err;
|
||||
} ogs_diam_s6b_message_t;
|
||||
|
||||
int ogs_diam_s6b_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -214,7 +214,13 @@ typedef struct smf_sess_s {
|
|||
bool gx_ccr_init_in_flight; /* Waiting for Gx CCA */
|
||||
uint32_t gx_cca_init_err; /* Gx CCA RXed error code */
|
||||
bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */
|
||||
uint32_t gy_cca_init_err; /* Gx CCA RXed error code */
|
||||
uint32_t gy_cca_init_err; /* Gy CCA RXed error code */
|
||||
bool gx_ccr_term_in_flight; /* Waiting for Gx CCA */
|
||||
uint32_t gx_cca_term_err; /* Gx CCA RXed error code */
|
||||
bool gy_ccr_term_in_flight; /* Waiting for Gy CCA */
|
||||
uint32_t gy_cca_term_err; /* Gy CCA RXed error code */
|
||||
bool s6b_str_in_flight; /* Waiting for S6B CCA */
|
||||
uint32_t s6b_sta_err; /* S6B CCA RXed error code */
|
||||
} sm_data;
|
||||
|
||||
ogs_pfcp_sess_t pfcp; /* PFCP session context */
|
||||
|
|
|
@ -64,6 +64,8 @@ const char *smf_event_get_name(smf_event_t *e)
|
|||
|
||||
case SMF_EVT_S5C_MESSAGE:
|
||||
return "SMF_EVT_S5C_MESSAGE";
|
||||
case SMF_EVT_S6B_MESSAGE:
|
||||
return "SMF_EVT_S6B_MESSAGE";
|
||||
case SMF_EVT_GN_MESSAGE:
|
||||
return "SMF_EVT_GN_MESSAGE";
|
||||
case SMF_EVT_GX_MESSAGE:
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct ogs_pfcp_xact_s ogs_pfcp_xact_t;
|
|||
typedef struct ogs_pfcp_message_s ogs_pfcp_message_t;
|
||||
typedef struct ogs_diam_gx_message_s ogs_diam_gx_message_t;
|
||||
typedef struct ogs_diam_gy_message_s ogs_diam_gy_message_t;
|
||||
typedef struct ogs_diam_s6b_message_s ogs_diam_s6b_message_t;
|
||||
typedef struct smf_sess_s smf_sess_t;
|
||||
typedef struct smf_upf_s smf_upf_t;
|
||||
typedef struct ogs_sbi_request_s ogs_sbi_request_t;
|
||||
|
@ -48,6 +49,7 @@ typedef enum {
|
|||
SMF_EVT_BASE = OGS_FSM_USER_SIG,
|
||||
|
||||
SMF_EVT_S5C_MESSAGE,
|
||||
SMF_EVT_S6B_MESSAGE,
|
||||
SMF_EVT_GN_MESSAGE,
|
||||
SMF_EVT_GX_MESSAGE,
|
||||
SMF_EVT_GY_MESSAGE,
|
||||
|
@ -90,6 +92,7 @@ typedef struct smf_event_s {
|
|||
union {
|
||||
ogs_diam_gx_message_t *gx_message;
|
||||
ogs_diam_gy_message_t *gy_message;
|
||||
ogs_diam_s6b_message_t *s6b_message;
|
||||
};
|
||||
|
||||
struct {
|
||||
|
|
|
@ -239,39 +239,20 @@ uint8_t smf_gn_handle_create_pdp_context_request(
|
|||
return cause_value;
|
||||
}
|
||||
|
||||
void smf_gn_handle_delete_pdp_context_request(
|
||||
uint8_t smf_gn_handle_delete_pdp_context_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp1_delete_pdp_context_request_t *req)
|
||||
{
|
||||
uint8_t cause_value = 0;
|
||||
|
||||
ogs_debug("Delete PDP Context Request");
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(req);
|
||||
|
||||
cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED;
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context");
|
||||
cause_value = OGS_GTP1_CAUSE_NON_EXISTENT;
|
||||
} else {
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
||||
ogs_error("No Gx Diameter Peer");
|
||||
cause_value = OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_gtp1_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
|
||||
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, cause_value);
|
||||
return;
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
||||
ogs_error("No Gx Diameter Peer");
|
||||
return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE;
|
||||
}
|
||||
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
smf_gx_send_ccr(sess, xact,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
return OGS_GTP1_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
void smf_gn_handle_update_pdp_context_request(
|
||||
|
|
|
@ -35,7 +35,7 @@ void smf_gn_handle_echo_response(
|
|||
uint8_t smf_gn_handle_create_pdp_context_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp1_create_pdp_context_request_t *req);
|
||||
void smf_gn_handle_delete_pdp_context_request(
|
||||
uint8_t smf_gn_handle_delete_pdp_context_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp1_delete_pdp_context_request_t *req);
|
||||
void smf_gn_handle_update_pdp_context_request(
|
||||
|
|
265
src/smf/gsm-sm.c
265
src/smf/gsm-sm.c
|
@ -76,6 +76,16 @@ static void send_gtp_create_err_msg(const smf_sess_t *sess, ogs_gtp_xact_t *gtp_
|
|||
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause);
|
||||
}
|
||||
|
||||
static void send_gtp_delete_err_msg(const smf_sess_t *sess, ogs_gtp_xact_t *gtp_xact, uint8_t gtp_cause)
|
||||
{
|
||||
if (gtp_xact->gtp_version == 1)
|
||||
ogs_gtp1_send_error_message(gtp_xact, sess->sgw_s5c_teid,
|
||||
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, gtp_cause);
|
||||
else
|
||||
ogs_gtp2_send_error_message(gtp_xact, sess->sgw_s5c_teid,
|
||||
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp_cause);
|
||||
}
|
||||
|
||||
static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e)
|
||||
{
|
||||
int use_gy = smf_use_gy_iface();
|
||||
|
@ -103,6 +113,41 @@ static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool send_ccr_termination_req_gx_gy_s6b(smf_sess_t *sess, smf_event_t *e)
|
||||
{
|
||||
/* TODO: we should take into account here whether "sess" has an active Gy
|
||||
session created, not whether one was supposedly created as per policy */
|
||||
int use_gy = smf_use_gy_iface();
|
||||
|
||||
if (use_gy == -1) {
|
||||
ogs_error("No Gy Diameter Peer");
|
||||
/* TODO: drop Gx connection here, possibly move to another "releasing" state! */
|
||||
uint8_t gtp_cause = (e->gtp_xact->gtp_version == 1) ?
|
||||
OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE :
|
||||
OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
|
||||
send_gtp_delete_err_msg(sess, e->gtp_xact, gtp_cause);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
|
||||
sess->sm_data.s6b_str_in_flight = true;
|
||||
smf_s6b_send_str(sess, e->gtp_xact,
|
||||
OGS_DIAM_TERMINATION_CAUSE_DIAMETER_LOGOUT);
|
||||
}
|
||||
|
||||
sess->sm_data.gx_ccr_term_in_flight = true;
|
||||
smf_gx_send_ccr(sess, e->gtp_xact,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
|
||||
if (use_gy == 1) {
|
||||
/* Gy is available, set up session for the bearer before accepting it towards the UE */
|
||||
sess->sm_data.gy_ccr_term_in_flight = true;
|
||||
smf_gy_send_ccr(sess, e->gtp_xact,
|
||||
OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
ogs_assert(s);
|
||||
|
@ -110,6 +155,8 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
|||
smf_sess_t *sess = e->sess;
|
||||
uint8_t gtp1_cause, gtp2_cause;
|
||||
|
||||
smf_sm_debug(e);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
/* reset state: */
|
||||
|
@ -171,6 +218,8 @@ void smf_gsm_state_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e)
|
|||
smf_sess_t *sess = e->sess;
|
||||
uint32_t diam_err;
|
||||
|
||||
smf_sm_debug(e);
|
||||
|
||||
switch (e->id) {
|
||||
case SMF_EVT_GX_MESSAGE:
|
||||
switch(e->gx_message->cmd_code) {
|
||||
|
@ -235,6 +284,8 @@ void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
|
|||
smf_sess_t *sess = e->sess;
|
||||
uint8_t pfcp_cause, gtp_cause;
|
||||
|
||||
smf_sm_debug(e);
|
||||
|
||||
switch (e->id) {
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
switch (e->pfcp_message->h.type) {
|
||||
|
@ -322,6 +373,8 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
uint8_t pfcp_cause;
|
||||
uint8_t gtp1_cause, gtp2_cause;
|
||||
bool release;
|
||||
|
||||
int state = 0;
|
||||
|
||||
|
@ -340,6 +393,44 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
case OGS_FSM_EXIT_SIG:
|
||||
break;
|
||||
|
||||
case SMF_EVT_GN_MESSAGE:
|
||||
switch(e->gtp1_message->h.type) {
|
||||
case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE:
|
||||
gtp1_cause = smf_gn_handle_delete_pdp_context_request(sess,
|
||||
e->gtp_xact,
|
||||
&e->gtp1_message->delete_pdp_context_request);
|
||||
if (gtp1_cause != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_gtp1_send_error_message(e->gtp_xact, sess->sgw_s5c_teid,
|
||||
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, gtp1_cause);
|
||||
return;
|
||||
}
|
||||
OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion);
|
||||
}
|
||||
break;
|
||||
|
||||
case SMF_EVT_S5C_MESSAGE:
|
||||
switch(e->gtp2_message->h.type) {
|
||||
case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE:
|
||||
gtp2_cause = smf_s5c_handle_delete_session_request(sess, e->gtp_xact,
|
||||
&e->gtp2_message->delete_session_request);
|
||||
if (gtp2_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_gtp2_send_error_message(e->gtp_xact, sess->sgw_s5c_teid,
|
||||
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp2_cause);
|
||||
return;
|
||||
}
|
||||
OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion);
|
||||
break;
|
||||
case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE:
|
||||
release = smf_s5c_handle_delete_bearer_response(
|
||||
sess, e->gtp_xact, &e->gtp2_message->delete_bearer_response);
|
||||
if (release) {
|
||||
e->gtp_xact = NULL;
|
||||
OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
switch (e->pfcp_message->h.type) {
|
||||
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
||||
|
@ -361,6 +452,14 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_assert(param.n2smbuf);
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
||||
break;
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
/* This is left here for 5gc sessions to properly receive messages,
|
||||
since tear down transitions are not implemented yet for 5gc
|
||||
sessions. See #if0 in smf_gsm_state_initial_wait_pfcp_deletion() */
|
||||
assert(!e->pfcp_xact->epc);
|
||||
smf_5gc_n4_handle_session_deletion_response(sess,
|
||||
e->pfcp_xact, &e->pfcp_message->pfcp_session_deletion_response);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -743,6 +842,171 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
void smf_gsm_state_release_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
smf_sess_t *sess = NULL;
|
||||
uint8_t pfcp_cause, gtp_cause;
|
||||
ogs_gtp_xact_t *gtp_xact;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
smf_sm_debug(e);
|
||||
|
||||
sess = e->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_session_deletion_request(sess, e->gtp_xact));
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
break;
|
||||
|
||||
case SMF_EVT_GN_MESSAGE:
|
||||
case SMF_EVT_S5C_MESSAGE:
|
||||
break; /* ignore */
|
||||
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
gtp_xact = e->pfcp_xact->assoc_xact;
|
||||
switch (e->pfcp_message->h.type) {
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
if (e->pfcp_xact->epc) {
|
||||
gtp_xact = e->pfcp_xact->assoc_xact;
|
||||
pfcp_cause = smf_epc_n4_handle_session_deletion_response(sess,
|
||||
e->pfcp_xact, &e->pfcp_message->pfcp_session_deletion_response);
|
||||
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
||||
/* FIXME: tear down Gy and Gx */
|
||||
gtp_cause = gtp_cause_from_pfcp(pfcp_cause, gtp_xact->gtp_version);
|
||||
send_gtp_delete_err_msg(sess, gtp_xact, gtp_cause);
|
||||
return;
|
||||
}
|
||||
e->gtp_xact = gtp_xact;
|
||||
if (send_ccr_termination_req_gx_gy_s6b(sess, e) == true)
|
||||
OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_auth);
|
||||
/* else: free session? */
|
||||
} else {
|
||||
#if 0
|
||||
/* This is currently not happening, since 5gc isn't yet properly
|
||||
integrated and doesn't move to this state */
|
||||
smf_5gc_n4_handle_session_deletion_response(sess,
|
||||
e->pfcp_xact, &message->pfcp_session_deletion_response);
|
||||
return; /* TODO: implement handling of errors here */
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown event %s", smf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void smf_gsm_state_release_wait_auth(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
ogs_assert(e && e->sess);
|
||||
smf_sess_t *sess = e->sess;
|
||||
uint32_t diam_err;
|
||||
|
||||
smf_sm_debug(e);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
/* reset state: */
|
||||
sess->sm_data.gx_cca_term_err = ER_DIAMETER_SUCCESS;
|
||||
sess->sm_data.gy_cca_term_err = ER_DIAMETER_SUCCESS;
|
||||
sess->sm_data.s6b_sta_err = ER_DIAMETER_SUCCESS;
|
||||
break;
|
||||
|
||||
case SMF_EVT_GN_MESSAGE:
|
||||
case SMF_EVT_S5C_MESSAGE:
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
break; /* ignore */
|
||||
|
||||
case SMF_EVT_GX_MESSAGE:
|
||||
switch(e->gx_message->cmd_code) {
|
||||
case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL:
|
||||
switch(e->gx_message->cc_request_type) {
|
||||
case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
||||
diam_err = smf_gx_handle_cca_termination_request(sess,
|
||||
e->gx_message, e->gtp_xact);
|
||||
sess->sm_data.gx_ccr_term_in_flight = false;
|
||||
sess->sm_data.gx_cca_term_err = diam_err;
|
||||
goto test_can_proceed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SMF_EVT_GY_MESSAGE:
|
||||
switch(e->gy_message->cmd_code) {
|
||||
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
|
||||
switch(e->gy_message->cc_request_type) {
|
||||
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
||||
ogs_assert(e->gtp_xact);
|
||||
diam_err = smf_gy_handle_cca_termination_request(sess,
|
||||
e->gy_message, e->gtp_xact);
|
||||
sess->sm_data.gy_ccr_term_in_flight = false;
|
||||
sess->sm_data.gy_cca_term_err = diam_err;
|
||||
goto test_can_proceed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SMF_EVT_S6B_MESSAGE:
|
||||
switch(e->s6b_message->cmd_code) {
|
||||
case OGS_DIAM_S6B_CMD_SESSION_TERMINATION:
|
||||
sess->sm_data.s6b_str_in_flight = false;
|
||||
/* TODO: validate error code from message below: */
|
||||
sess->sm_data.s6b_sta_err = ER_DIAMETER_SUCCESS;
|
||||
goto test_can_proceed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
test_can_proceed:
|
||||
/* First wait for both Gx and Gy requests to be done: */
|
||||
if (!sess->sm_data.gx_ccr_term_in_flight &&
|
||||
!sess->sm_data.gy_ccr_term_in_flight &&
|
||||
!sess->sm_data.s6b_str_in_flight) {
|
||||
diam_err = ER_DIAMETER_SUCCESS;
|
||||
if (sess->sm_data.gx_cca_term_err != ER_DIAMETER_SUCCESS)
|
||||
diam_err = sess->sm_data.gx_cca_term_err;
|
||||
if (sess->sm_data.gy_cca_term_err != ER_DIAMETER_SUCCESS)
|
||||
diam_err = sess->sm_data.gy_cca_term_err;
|
||||
if (sess->sm_data.s6b_sta_err != ER_DIAMETER_SUCCESS)
|
||||
diam_err = sess->sm_data.s6b_sta_err;
|
||||
|
||||
/* Initiated by peer request, let's answer: */
|
||||
if (e->gtp_xact) {
|
||||
if (diam_err == ER_DIAMETER_SUCCESS) {
|
||||
/*
|
||||
* 1. MME sends Delete Session Request to SGW/SMF.
|
||||
* 2. SMF sends Delete Session Response to SGW/MME.
|
||||
*/
|
||||
switch (e->gtp_xact->gtp_version) {
|
||||
case 1:
|
||||
ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, e->gtp_xact));
|
||||
break;
|
||||
case 2:
|
||||
ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, e->gtp_xact));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint8_t gtp_cause = gtp_cause_from_diameter(e->gtp_xact->gtp_version,
|
||||
diam_err, NULL);
|
||||
send_gtp_delete_err_msg(sess, e->gtp_xact, gtp_cause);
|
||||
}
|
||||
}
|
||||
OGS_FSM_TRAN(s, &smf_gsm_state_session_will_release);
|
||||
}
|
||||
}
|
||||
|
||||
void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
smf_sess_t *sess = NULL;
|
||||
|
@ -756,6 +1020,7 @@ void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
SMF_SESS_CLEAR(sess);
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
|
|
|
@ -243,26 +243,18 @@ uint32_t smf_gx_handle_cca_initial_request(
|
|||
return ER_DIAMETER_SUCCESS;
|
||||
}
|
||||
|
||||
void smf_gx_handle_cca_termination_request(
|
||||
uint32_t smf_gx_handle_cca_termination_request(
|
||||
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
||||
ogs_gtp_xact_t *gtp_xact)
|
||||
{
|
||||
ogs_assert(sess);
|
||||
ogs_assert(gx_message);
|
||||
ogs_assert(gtp_xact);
|
||||
|
||||
ogs_debug("[SMF] Delete Session Response");
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
/*
|
||||
* << 'gtp_xact' is NOT NULL >>
|
||||
*
|
||||
* 1. MME sends Delete Session Request to SGW/SMF.
|
||||
* 2. SMF sends Delete Session Response to SGW/MME.
|
||||
*/
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_session_deletion_request(sess, gtp_xact));
|
||||
return ER_DIAMETER_SUCCESS;
|
||||
}
|
||||
|
||||
void smf_gx_handle_re_auth_request(
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
uint32_t smf_gx_handle_cca_initial_request(
|
||||
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
||||
ogs_gtp_xact_t *gtp_xact);
|
||||
void smf_gx_handle_cca_termination_request(
|
||||
uint32_t smf_gx_handle_cca_termination_request(
|
||||
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
||||
ogs_gtp_xact_t *gtp_xact);
|
||||
void smf_gx_handle_re_auth_request(
|
||||
|
|
|
@ -93,7 +93,6 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
|||
struct sockaddr_in6 sin6;
|
||||
uint32_t charing_id;
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_assert(sess->ipv4 || sess->ipv6);
|
||||
|
@ -742,7 +741,6 @@ static void smf_gx_cca_cb(void *data, struct msg **msg)
|
|||
ogs_debug(" CC-Request-Number[%d]", cc_request_number);
|
||||
|
||||
xact = sess_data->xact[cc_request_number];
|
||||
ogs_assert(xact);
|
||||
sess = sess_data->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ void smf_gy_handle_cca_update_request(
|
|||
}
|
||||
}
|
||||
|
||||
void smf_gy_handle_cca_termination_request(
|
||||
uint32_t smf_gy_handle_cca_termination_request(
|
||||
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
|
||||
ogs_gtp_xact_t *gtp_xact)
|
||||
{
|
||||
|
@ -194,36 +194,7 @@ void smf_gy_handle_cca_termination_request(
|
|||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
if (gtp_xact) {
|
||||
/*
|
||||
* 1. MME sends Delete Session Request to SGW/SMF.
|
||||
* 2. SMF sends Delete Session Response to SGW/MME.
|
||||
*/
|
||||
switch (gtp_xact->gtp_version) {
|
||||
case 1:
|
||||
ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact));
|
||||
break;
|
||||
case 2:
|
||||
ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Note that the following messages are not processed here.
|
||||
* - Bearer Resource Command
|
||||
* - Delete Bearer Request/Response with DEDICATED BEARER.
|
||||
*/
|
||||
}
|
||||
SMF_SESS_CLEAR(sess);
|
||||
return;
|
||||
return ER_DIAMETER_SUCCESS;
|
||||
}
|
||||
|
||||
void smf_gy_handle_re_auth_request(
|
||||
|
|
|
@ -33,7 +33,7 @@ uint32_t smf_gy_handle_cca_initial_request(
|
|||
void smf_gy_handle_cca_update_request(
|
||||
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
|
||||
ogs_pfcp_xact_t *gtp_xact);
|
||||
void smf_gy_handle_cca_termination_request(
|
||||
uint32_t smf_gy_handle_cca_termination_request(
|
||||
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
|
||||
ogs_gtp_xact_t *gtp_xact);
|
||||
void smf_gy_handle_re_auth_request(
|
||||
|
|
|
@ -693,7 +693,7 @@ void smf_5gc_n4_handle_session_deletion_response(
|
|||
ogs_assert(stream);
|
||||
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
||||
|
||||
SMF_SESS_CLEAR(sess);
|
||||
OGS_FSM_TRAN(&sess->sm, smf_gsm_state_session_will_release);
|
||||
} else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) {
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
|
||||
|
@ -1045,61 +1045,28 @@ void smf_epc_n4_handle_session_modification_response(
|
|||
}
|
||||
}
|
||||
|
||||
void smf_epc_n4_handle_session_deletion_response(
|
||||
uint8_t smf_epc_n4_handle_session_deletion_response(
|
||||
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
||||
ogs_pfcp_session_deletion_response_t *rsp)
|
||||
{
|
||||
uint8_t cause_value = 0;
|
||||
uint8_t resp_type = 0;
|
||||
ogs_gtp_xact_t *gtp_xact = NULL;
|
||||
smf_bearer_t *bearer = NULL;
|
||||
unsigned int i;
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(xact);
|
||||
ogs_assert(rsp);
|
||||
|
||||
ogs_debug("Session Deletion Response [epc]");
|
||||
|
||||
gtp_xact = xact->assoc_xact;
|
||||
|
||||
ogs_pfcp_xact_commit(xact);
|
||||
|
||||
/* If !gtp_xact, set it to whatever valid, nothing is sent in the end anyway */
|
||||
uint8_t gtp_version = gtp_xact ? gtp_xact->gtp_version : 2;
|
||||
|
||||
if (gtp_version == 1) {
|
||||
resp_type = OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE;
|
||||
cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED;
|
||||
} else {
|
||||
resp_type = OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE;
|
||||
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context");
|
||||
cause_value = (gtp_version == 1) ?
|
||||
OGS_GTP1_CAUSE_NON_EXISTENT :
|
||||
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (rsp->cause.presence) {
|
||||
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8);
|
||||
cause_value = gtp_cause_from_pfcp(rsp->cause.u8, gtp_version);
|
||||
}
|
||||
} else {
|
||||
if (!rsp->cause.presence) {
|
||||
ogs_error("No Cause");
|
||||
cause_value = (gtp_xact->gtp_version == 1) ?
|
||||
OGS_GTP1_CAUSE_MANDATORY_IE_MISSING :
|
||||
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
return OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
if (gtp_xact &&
|
||||
((gtp_version == 1 && cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) ||
|
||||
(gtp_version == 2 && cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED))) {
|
||||
ogs_gtp_send_error_message(gtp_xact, sess->sgw_s5c_teid, resp_type,
|
||||
cause_value);
|
||||
return;
|
||||
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8);
|
||||
return rsp->cause.u8;
|
||||
}
|
||||
|
||||
ogs_assert(sess);
|
||||
|
@ -1124,48 +1091,7 @@ void smf_epc_n4_handle_session_deletion_response(
|
|||
sess->gy.duration += use_rep->duration_measurement.u32;
|
||||
}
|
||||
|
||||
switch(smf_use_gy_iface()) {
|
||||
case 1:
|
||||
/* Gy is available, terminate the Gy session before terminating it towards the UE */
|
||||
smf_gy_send_ccr(sess, gtp_xact,
|
||||
OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
return;
|
||||
case -1:
|
||||
ogs_error("No Gy Diameter Peer");
|
||||
break; /* continue below */
|
||||
/* default: continue below */
|
||||
}
|
||||
|
||||
if (gtp_xact) {
|
||||
/*
|
||||
* 1. MME sends Delete Session Request to SGW/SMF.
|
||||
* 2. SMF sends Delete Session Response to SGW/MME.
|
||||
*/
|
||||
switch (gtp_version) {
|
||||
case 1:
|
||||
ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact));
|
||||
break;
|
||||
case 2:
|
||||
ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Note that the following messages are not processed here.
|
||||
* - Bearer Resource Command
|
||||
* - Delete Bearer Request/Response with DEDICATED BEARER.
|
||||
*/
|
||||
}
|
||||
|
||||
SMF_SESS_CLEAR(sess);
|
||||
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
void smf_n4_handle_session_report_request(
|
||||
|
|
|
@ -42,7 +42,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
|
|||
void smf_epc_n4_handle_session_modification_response(
|
||||
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
||||
ogs_pfcp_session_modification_response_t *rsp);
|
||||
void smf_epc_n4_handle_session_deletion_response(
|
||||
uint8_t smf_epc_n4_handle_session_deletion_response(
|
||||
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
||||
ogs_pfcp_session_deletion_response_t *rsp);
|
||||
|
||||
|
|
|
@ -245,17 +245,9 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
|||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
if (!message->h.seid_presence) {
|
||||
if (!message->h.seid_presence)
|
||||
ogs_error("No SEID");
|
||||
break;
|
||||
}
|
||||
|
||||
if (xact->epc)
|
||||
smf_epc_n4_handle_session_deletion_response(
|
||||
sess, xact, &message->pfcp_session_deletion_response);
|
||||
else
|
||||
smf_5gc_n4_handle_session_deletion_response(
|
||||
sess, xact, &message->pfcp_session_deletion_response);
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE:
|
||||
|
|
|
@ -304,58 +304,31 @@ uint8_t smf_s5c_handle_create_session_request(
|
|||
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
void smf_s5c_handle_delete_session_request(
|
||||
uint8_t smf_s5c_handle_delete_session_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_delete_session_request_t *req)
|
||||
{
|
||||
uint8_t cause_value = 0;
|
||||
|
||||
ogs_debug("Delete Session Request");
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(req);
|
||||
|
||||
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
||||
|
||||
if (!sess) {
|
||||
ogs_warn("No Context");
|
||||
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
|
||||
} else {
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
||||
ogs_error("No Gx Diameter Peer");
|
||||
cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
||||
}
|
||||
|
||||
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) {
|
||||
ogs_error("No S6b Diameter Peer");
|
||||
cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
||||
}
|
||||
}
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
||||
ogs_error("No Gx Diameter Peer");
|
||||
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
||||
}
|
||||
|
||||
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
||||
ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
|
||||
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
|
||||
return;
|
||||
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
|
||||
if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) {
|
||||
ogs_error("No S6b Diameter Peer");
|
||||
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
switch (sess->gtp_rat_type) {
|
||||
case OGS_GTP2_RAT_TYPE_EUTRAN:
|
||||
smf_gx_send_ccr(sess, xact,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
break;
|
||||
case OGS_GTP2_RAT_TYPE_WLAN:
|
||||
smf_s6b_send_str(sess, xact,
|
||||
OGS_DIAM_TERMINATION_CAUSE_DIAMETER_LOGOUT);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
void smf_s5c_handle_modify_bearer_request(
|
||||
|
@ -664,7 +637,8 @@ void smf_s5c_handle_update_bearer_response(
|
|||
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
||||
}
|
||||
|
||||
void smf_s5c_handle_delete_bearer_response(
|
||||
/* return true if entire session must be released */
|
||||
bool smf_s5c_handle_delete_bearer_response(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_delete_bearer_response_t *rsp)
|
||||
{
|
||||
|
@ -717,66 +691,64 @@ void smf_s5c_handle_delete_bearer_response(
|
|||
ogs_error("No Cause");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
/* Release entire session: */
|
||||
return true;
|
||||
}
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_session_deletion_request(
|
||||
sess, NULL));
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
|
||||
* 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
|
||||
*/
|
||||
if (rsp->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
if (rsp->bearer_contexts.eps_bearer_id.presence == 0) {
|
||||
ogs_error("No EPS Bearer ID");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
|
||||
* 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
|
||||
*/
|
||||
if (rsp->bearer_contexts.presence == 0) {
|
||||
ogs_error("No Bearer");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
if (rsp->bearer_contexts.eps_bearer_id.presence == 0) {
|
||||
ogs_error("No EPS Bearer ID");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
if (rsp->cause.presence) {
|
||||
ogs_gtp2_cause_t *cause = rsp->cause.data;
|
||||
ogs_assert(cause);
|
||||
|
||||
if (rsp->cause.presence) {
|
||||
ogs_gtp2_cause_t *cause = rsp->cause.data;
|
||||
ogs_assert(cause);
|
||||
cause_value = cause->value;
|
||||
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
||||
if (rsp->bearer_contexts.cause.presence) {
|
||||
cause = rsp->bearer_contexts.cause.data;
|
||||
ogs_assert(cause);
|
||||
|
||||
cause_value = cause->value;
|
||||
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
||||
if (rsp->bearer_contexts.cause.presence) {
|
||||
cause = rsp->bearer_contexts.cause.data;
|
||||
ogs_assert(cause);
|
||||
|
||||
cause_value = cause->value;
|
||||
} else {
|
||||
ogs_error("No Cause");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
cause_value = cause->value;
|
||||
} else {
|
||||
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
|
||||
ogs_error("No Cause");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
} else {
|
||||
ogs_error("No Cause");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
|
||||
}
|
||||
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
||||
} else {
|
||||
ogs_error("No Cause");
|
||||
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
||||
}
|
||||
|
||||
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]",
|
||||
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_bearer_modification_request(
|
||||
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
||||
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
||||
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
||||
return false;
|
||||
}
|
||||
|
||||
static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp2_tft_t *tft, int i)
|
||||
|
|
|
@ -34,7 +34,7 @@ void smf_s5c_handle_echo_response(
|
|||
uint8_t smf_s5c_handle_create_session_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_create_session_request_t *req);
|
||||
void smf_s5c_handle_delete_session_request(
|
||||
uint8_t smf_s5c_handle_delete_session_request(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_delete_session_request_t *req);
|
||||
void smf_s5c_handle_modify_bearer_request(
|
||||
|
@ -46,7 +46,7 @@ void smf_s5c_handle_create_bearer_response(
|
|||
void smf_s5c_handle_update_bearer_response(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_update_bearer_response_t *req);
|
||||
void smf_s5c_handle_delete_bearer_response(
|
||||
bool smf_s5c_handle_delete_bearer_response(
|
||||
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
||||
ogs_gtp2_delete_bearer_response_t *req);
|
||||
void smf_s5c_handle_bearer_resource_command(
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "fd-path.h"
|
||||
|
||||
static struct session_handler *smf_s6b_reg = NULL;
|
||||
static struct disp_hdl *hdl_s6b_fb = NULL;
|
||||
static struct disp_hdl *hdl_s6b_fb = NULL;
|
||||
|
||||
struct sess_state {
|
||||
smf_sess_t *sess;
|
||||
|
@ -62,12 +62,12 @@ static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque)
|
|||
ogs_thread_mutex_unlock(&sess_state_mutex);
|
||||
}
|
||||
|
||||
static int smf_s6b_fb_cb(struct msg **msg, struct avp *avp,
|
||||
static int smf_s6b_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *sess, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
ogs_warn("Unexpected message received!");
|
||||
|
||||
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@ void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause)
|
|||
smf_ue_t *smf_ue = NULL;
|
||||
char *user_name = NULL;
|
||||
|
||||
ogs_assert(xact);
|
||||
//ogs_assert(xact);
|
||||
ogs_assert(sess);
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
@ -603,6 +603,7 @@ void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause)
|
|||
static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
||||
{
|
||||
int ret;
|
||||
int rv;
|
||||
|
||||
struct sess_state *sess_data = NULL;
|
||||
struct timespec ts;
|
||||
|
@ -612,11 +613,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
|||
unsigned long dur;
|
||||
int error = 0;
|
||||
int new;
|
||||
int result_code = 0;
|
||||
int exp_result_code = 0;
|
||||
|
||||
smf_event_t *e = NULL;
|
||||
smf_sess_t *sess = NULL;
|
||||
ogs_gtp_xact_t *xact = NULL;
|
||||
ogs_diam_s6b_message_t *s6b_message = NULL;
|
||||
|
||||
ogs_debug("[Session-Termination-Answer]");
|
||||
|
||||
|
@ -638,9 +638,11 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
|||
ogs_debug(" Retrieve its data: [%s]", sess_data->s6b_sid);
|
||||
|
||||
sess = sess_data->sess;
|
||||
ogs_assert(sess);
|
||||
xact = sess_data->xact;
|
||||
ogs_assert(xact);
|
||||
|
||||
s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t));
|
||||
ogs_assert(s6b_message);
|
||||
/* Set Session Termination Command */
|
||||
s6b_message->cmd_code = OGS_DIAM_S6B_CMD_SESSION_TERMINATION;
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
||||
|
@ -648,9 +650,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
|||
if (avp) {
|
||||
ret = fd_msg_avp_hdr(avp, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
result_code = hdr->avp_value->i32;
|
||||
if (result_code != ER_DIAMETER_SUCCESS) {
|
||||
ogs_error("Result Code: %d", result_code);
|
||||
s6b_message->result_code = hdr->avp_value->i32;
|
||||
s6b_message->err = &s6b_message->result_code;
|
||||
if (s6b_message->result_code != ER_DIAMETER_SUCCESS) {
|
||||
ogs_error("Result Code: %d", s6b_message->result_code);
|
||||
error++;
|
||||
}
|
||||
} else {
|
||||
|
@ -665,8 +668,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
|||
if (avpch1) {
|
||||
ret = fd_msg_avp_hdr(avpch1, &hdr);
|
||||
ogs_assert(ret == 0);
|
||||
exp_result_code = hdr->avp_value->i32;
|
||||
ogs_error("Experimental Result Code: %d", exp_result_code);
|
||||
s6b_message->result_code = hdr->avp_value->i32;
|
||||
s6b_message->exp_err = &s6b_message->result_code;
|
||||
ogs_error("Experimental Result Code: %d",
|
||||
s6b_message->result_code);
|
||||
}
|
||||
} else {
|
||||
ogs_error("no Result-Code");
|
||||
|
@ -700,8 +705,21 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
|
|||
}
|
||||
|
||||
if (!error) {
|
||||
smf_gx_send_ccr(sess, xact,
|
||||
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
e = smf_event_new(SMF_EVT_S6B_MESSAGE);
|
||||
ogs_assert(e);
|
||||
|
||||
e->sess = sess;
|
||||
e->s6b_message = s6b_message;
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_free(s6b_message);
|
||||
smf_event_free(e);
|
||||
} else {
|
||||
ogs_pollset_notify(ogs_app()->pollset);
|
||||
}
|
||||
} else {
|
||||
ogs_free(s6b_message);
|
||||
}
|
||||
|
||||
/* Free the message */
|
||||
|
|
|
@ -62,6 +62,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
ogs_diam_gx_message_t *gx_message = NULL;
|
||||
ogs_diam_gy_message_t *gy_message = NULL;
|
||||
ogs_diam_s6b_message_t *s6b_message = NULL;
|
||||
|
||||
ogs_pfcp_node_t *pfcp_node = NULL;
|
||||
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
||||
|
@ -145,8 +146,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE:
|
||||
smf_s5c_handle_delete_session_request(
|
||||
sess, gtp_xact, >p2_message.delete_session_request);
|
||||
if (!sess) {
|
||||
ogs_gtp2_send_error_message(gtp_xact, 0,
|
||||
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE,
|
||||
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
e->sess = sess;
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE:
|
||||
smf_s5c_handle_modify_bearer_request(
|
||||
|
@ -161,8 +168,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
sess, gtp_xact, >p2_message.update_bearer_response);
|
||||
break;
|
||||
case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE:
|
||||
smf_s5c_handle_delete_bearer_response(
|
||||
sess, gtp_xact, >p2_message.delete_bearer_response);
|
||||
if (!sess) {
|
||||
/* TODO: NACK the message */
|
||||
break;
|
||||
}
|
||||
e->sess = sess;
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE:
|
||||
smf_s5c_handle_bearer_resource_command(
|
||||
|
@ -230,8 +241,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE:
|
||||
smf_gn_handle_delete_pdp_context_request(
|
||||
sess, gtp_xact, >p1_message.delete_pdp_context_request);
|
||||
if (!sess) {
|
||||
ogs_gtp1_send_error_message(gtp_xact, 0,
|
||||
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE,
|
||||
OGS_GTP1_CAUSE_NON_EXISTENT);
|
||||
break;
|
||||
}
|
||||
e->sess = sess;
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE:
|
||||
smf_gn_handle_update_pdp_context_request(
|
||||
|
@ -258,16 +275,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
switch(gx_message->cmd_code) {
|
||||
case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL:
|
||||
gtp_xact = e->gtp_xact;
|
||||
ogs_assert(gtp_xact);
|
||||
|
||||
switch(gx_message->cc_request_type) {
|
||||
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
||||
smf_gx_handle_cca_termination_request(
|
||||
sess, gx_message, gtp_xact);
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Not implemented(%d)", gx_message->cc_request_type);
|
||||
|
@ -302,14 +315,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST:
|
||||
ogs_assert(e->pfcp_xact);
|
||||
smf_gy_handle_cca_update_request(
|
||||
sess, gy_message, e->pfcp_xact);
|
||||
ogs_assert(e->pfcp_xact);
|
||||
smf_gy_handle_cca_update_request(
|
||||
sess, gy_message, e->pfcp_xact);
|
||||
break;
|
||||
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
||||
ogs_assert(e->gtp_xact);
|
||||
smf_gy_handle_cca_termination_request(
|
||||
sess, gy_message, e->gtp_xact);
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Not implemented(%d)", gy_message->cc_request_type);
|
||||
|
@ -328,6 +339,25 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_free(gy_message);
|
||||
break;
|
||||
|
||||
case SMF_EVT_S6B_MESSAGE:
|
||||
ogs_assert(e);
|
||||
s6b_message = e->s6b_message;
|
||||
ogs_assert(s6b_message);
|
||||
sess = e->sess;
|
||||
ogs_assert(sess);
|
||||
|
||||
switch(s6b_message->cmd_code) {
|
||||
case OGS_DIAM_S6B_CMD_SESSION_TERMINATION:
|
||||
ogs_fsm_dispatch(&sess->sm, e);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Invalid type(%d)", s6b_message->cmd_code);
|
||||
break;
|
||||
}
|
||||
|
||||
ogs_free(s6b_message);
|
||||
break;
|
||||
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
ogs_assert(e);
|
||||
recvbuf = e->pkbuf;
|
||||
|
@ -716,9 +746,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
|
||||
ogs_error("[%s] State machine exception", smf_ue->supi);
|
||||
SMF_SESS_CLEAR(sess);
|
||||
} else if (OGS_FSM_CHECK(
|
||||
&sess->sm, smf_gsm_state_session_will_release)) {
|
||||
SMF_SESS_CLEAR(sess);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -43,13 +43,15 @@ void smf_nf_state_exception(ogs_fsm_t *s, smf_event_t *e);
|
|||
|
||||
void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_release_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_release_wait_auth(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e);
|
||||
|
||||
void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_pfcp_state_final(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e);
|
||||
|
|
Loading…
Reference in New Issue