[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:
Pau Espin 2022-04-20 14:42:18 +02:00 committed by GitHub
parent 79de674fd8
commit 2de12e32f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 458 additions and 295 deletions

View File

@ -34,6 +34,14 @@ extern struct dict_object *ogs_diam_s6b_application;
extern struct dict_object *ogs_diam_s6b_mip6_feature_vector; 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); int ogs_diam_s6b_init(void);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -214,7 +214,13 @@ typedef struct smf_sess_s {
bool gx_ccr_init_in_flight; /* Waiting for Gx CCA */ bool gx_ccr_init_in_flight; /* Waiting for Gx CCA */
uint32_t gx_cca_init_err; /* Gx CCA RXed error code */ uint32_t gx_cca_init_err; /* Gx CCA RXed error code */
bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */ 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; } sm_data;
ogs_pfcp_sess_t pfcp; /* PFCP session context */ ogs_pfcp_sess_t pfcp; /* PFCP session context */

View File

@ -64,6 +64,8 @@ const char *smf_event_get_name(smf_event_t *e)
case SMF_EVT_S5C_MESSAGE: case SMF_EVT_S5C_MESSAGE:
return "SMF_EVT_S5C_MESSAGE"; return "SMF_EVT_S5C_MESSAGE";
case SMF_EVT_S6B_MESSAGE:
return "SMF_EVT_S6B_MESSAGE";
case SMF_EVT_GN_MESSAGE: case SMF_EVT_GN_MESSAGE:
return "SMF_EVT_GN_MESSAGE"; return "SMF_EVT_GN_MESSAGE";
case SMF_EVT_GX_MESSAGE: case SMF_EVT_GX_MESSAGE:

View File

@ -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_pfcp_message_s ogs_pfcp_message_t;
typedef struct ogs_diam_gx_message_s ogs_diam_gx_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_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_sess_s smf_sess_t;
typedef struct smf_upf_s smf_upf_t; typedef struct smf_upf_s smf_upf_t;
typedef struct ogs_sbi_request_s ogs_sbi_request_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_BASE = OGS_FSM_USER_SIG,
SMF_EVT_S5C_MESSAGE, SMF_EVT_S5C_MESSAGE,
SMF_EVT_S6B_MESSAGE,
SMF_EVT_GN_MESSAGE, SMF_EVT_GN_MESSAGE,
SMF_EVT_GX_MESSAGE, SMF_EVT_GX_MESSAGE,
SMF_EVT_GY_MESSAGE, SMF_EVT_GY_MESSAGE,
@ -90,6 +92,7 @@ typedef struct smf_event_s {
union { union {
ogs_diam_gx_message_t *gx_message; ogs_diam_gx_message_t *gx_message;
ogs_diam_gy_message_t *gy_message; ogs_diam_gy_message_t *gy_message;
ogs_diam_s6b_message_t *s6b_message;
}; };
struct { struct {

View File

@ -239,39 +239,20 @@ uint8_t smf_gn_handle_create_pdp_context_request(
return cause_value; 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp1_delete_pdp_context_request_t *req) ogs_gtp1_delete_pdp_context_request_t *req)
{ {
uint8_t cause_value = 0;
ogs_debug("Delete PDP Context Request"); ogs_debug("Delete PDP Context Request");
ogs_assert(xact); if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
ogs_assert(req); ogs_error("No Gx Diameter Peer");
return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE;
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;
} }
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
smf_gx_send_ccr(sess, xact, return OGS_GTP1_CAUSE_REQUEST_ACCEPTED;
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
} }
void smf_gn_handle_update_pdp_context_request( void smf_gn_handle_update_pdp_context_request(

View File

@ -35,7 +35,7 @@ void smf_gn_handle_echo_response(
uint8_t smf_gn_handle_create_pdp_context_request( uint8_t smf_gn_handle_create_pdp_context_request(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp1_create_pdp_context_request_t *req); 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp1_delete_pdp_context_request_t *req); ogs_gtp1_delete_pdp_context_request_t *req);
void smf_gn_handle_update_pdp_context_request( void smf_gn_handle_update_pdp_context_request(

View File

@ -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); 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) static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e)
{ {
int use_gy = smf_use_gy_iface(); 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; 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) void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
{ {
ogs_assert(s); 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; smf_sess_t *sess = e->sess;
uint8_t gtp1_cause, gtp2_cause; uint8_t gtp1_cause, gtp2_cause;
smf_sm_debug(e);
switch (e->id) { switch (e->id) {
case OGS_FSM_ENTRY_SIG: case OGS_FSM_ENTRY_SIG:
/* reset state: */ /* 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; smf_sess_t *sess = e->sess;
uint32_t diam_err; uint32_t diam_err;
smf_sm_debug(e);
switch (e->id) { switch (e->id) {
case SMF_EVT_GX_MESSAGE: case SMF_EVT_GX_MESSAGE:
switch(e->gx_message->cmd_code) { 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; smf_sess_t *sess = e->sess;
uint8_t pfcp_cause, gtp_cause; uint8_t pfcp_cause, gtp_cause;
smf_sm_debug(e);
switch (e->id) { switch (e->id) {
case SMF_EVT_N4_MESSAGE: case SMF_EVT_N4_MESSAGE:
switch (e->pfcp_message->h.type) { 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; smf_n1_n2_message_transfer_param_t param;
uint8_t pfcp_cause; uint8_t pfcp_cause;
uint8_t gtp1_cause, gtp2_cause;
bool release;
int state = 0; 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: case OGS_FSM_EXIT_SIG:
break; 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: case SMF_EVT_N4_MESSAGE:
switch (e->pfcp_message->h.type) { switch (e->pfcp_message->h.type) {
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_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); ogs_assert(param.n2smbuf);
smf_namf_comm_send_n1_n2_message_transfer(sess, &param); smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
break; 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; 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) void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e)
{ {
smf_sess_t *sess = NULL; 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) { switch (e->id) {
case OGS_FSM_ENTRY_SIG: case OGS_FSM_ENTRY_SIG:
SMF_SESS_CLEAR(sess);
break; break;
case OGS_FSM_EXIT_SIG: case OGS_FSM_EXIT_SIG:

View File

@ -243,26 +243,18 @@ uint32_t smf_gx_handle_cca_initial_request(
return ER_DIAMETER_SUCCESS; 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, smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
ogs_gtp_xact_t *gtp_xact) ogs_gtp_xact_t *gtp_xact)
{ {
ogs_assert(sess); ogs_assert(sess);
ogs_assert(gx_message); ogs_assert(gx_message);
ogs_assert(gtp_xact);
ogs_debug("[SMF] Delete Session Response"); ogs_debug("[SMF] Delete Session Response");
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
/* return ER_DIAMETER_SUCCESS;
* << '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));
} }
void smf_gx_handle_re_auth_request( void smf_gx_handle_re_auth_request(

View File

@ -29,7 +29,7 @@ extern "C" {
uint32_t smf_gx_handle_cca_initial_request( uint32_t smf_gx_handle_cca_initial_request(
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message, smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
ogs_gtp_xact_t *gtp_xact); 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, smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
ogs_gtp_xact_t *gtp_xact); ogs_gtp_xact_t *gtp_xact);
void smf_gx_handle_re_auth_request( void smf_gx_handle_re_auth_request(

View File

@ -93,7 +93,6 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
uint32_t charing_id; uint32_t charing_id;
ogs_assert(xact);
ogs_assert(sess); ogs_assert(sess);
ogs_assert(sess->ipv4 || sess->ipv6); 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); ogs_debug(" CC-Request-Number[%d]", cc_request_number);
xact = sess_data->xact[cc_request_number]; xact = sess_data->xact[cc_request_number];
ogs_assert(xact);
sess = sess_data->sess; sess = sess_data->sess;
ogs_assert(sess); ogs_assert(sess);

View File

@ -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, smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_gtp_xact_t *gtp_xact) 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]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
if (gtp_xact) { return ER_DIAMETER_SUCCESS;
/*
* 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;
} }
void smf_gy_handle_re_auth_request( void smf_gy_handle_re_auth_request(

View File

@ -33,7 +33,7 @@ uint32_t smf_gy_handle_cca_initial_request(
void smf_gy_handle_cca_update_request( void smf_gy_handle_cca_update_request(
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_pfcp_xact_t *gtp_xact); 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, smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_gtp_xact_t *gtp_xact); ogs_gtp_xact_t *gtp_xact);
void smf_gy_handle_re_auth_request( void smf_gy_handle_re_auth_request(

View File

@ -693,7 +693,7 @@ void smf_5gc_n4_handle_session_deletion_response(
ogs_assert(stream); ogs_assert(stream);
ogs_assert(true == ogs_sbi_server_send_response(stream, response)); 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) { } else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) {
smf_n1_n2_message_transfer_param_t param; 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, smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_deletion_response_t *rsp) 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; smf_bearer_t *bearer = NULL;
unsigned int i; unsigned int i;
ogs_assert(sess);
ogs_assert(xact); ogs_assert(xact);
ogs_assert(rsp); ogs_assert(rsp);
ogs_debug("Session Deletion Response [epc]"); ogs_debug("Session Deletion Response [epc]");
gtp_xact = xact->assoc_xact;
ogs_pfcp_xact_commit(xact); ogs_pfcp_xact_commit(xact);
/* If !gtp_xact, set it to whatever valid, nothing is sent in the end anyway */ if (!rsp->cause.presence) {
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 {
ogs_error("No Cause"); ogs_error("No Cause");
cause_value = (gtp_xact->gtp_version == 1) ? return OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
OGS_GTP1_CAUSE_MANDATORY_IE_MISSING :
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
if (gtp_xact && ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8);
((gtp_version == 1 && cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) || return rsp->cause.u8;
(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;
} }
ogs_assert(sess); ogs_assert(sess);
@ -1124,48 +1091,7 @@ void smf_epc_n4_handle_session_deletion_response(
sess->gy.duration += use_rep->duration_measurement.u32; sess->gy.duration += use_rep->duration_measurement.u32;
} }
switch(smf_use_gy_iface()) { return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
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);
} }
void smf_n4_handle_session_report_request( void smf_n4_handle_session_report_request(

View File

@ -42,7 +42,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
void smf_epc_n4_handle_session_modification_response( void smf_epc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact, smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_modification_response_t *rsp); 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, smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_deletion_response_t *rsp); ogs_pfcp_session_deletion_response_t *rsp);

View File

@ -245,17 +245,9 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
break; break;
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
if (!message->h.seid_presence) { if (!message->h.seid_presence)
ogs_error("No SEID"); ogs_error("No SEID");
break; ogs_fsm_dispatch(&sess->sm, e);
}
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);
break; break;
case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE: case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE:

View File

@ -304,58 +304,31 @@ uint8_t smf_s5c_handle_create_session_request(
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_delete_session_request_t *req) ogs_gtp2_delete_session_request_t *req)
{ {
uint8_t cause_value = 0;
ogs_debug("Delete Session Request"); ogs_debug("Delete Session Request");
ogs_assert(xact); ogs_assert(xact);
ogs_assert(req); ogs_assert(req);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
ogs_error("No Gx Diameter Peer");
if (!sess) { return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
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 (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) {
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); ogs_error("No S6b Diameter Peer");
return; return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
}
} }
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
switch (sess->gtp_rat_type) { return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
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();
}
} }
void smf_s5c_handle_modify_bearer_request( void smf_s5c_handle_modify_bearer_request(
@ -664,7 +637,8 @@ void smf_s5c_handle_update_bearer_response(
OGS_GTP2_CAUSE_UNDEFINED_VALUE)); 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_delete_bearer_response_t *rsp) ogs_gtp2_delete_bearer_response_t *rsp)
{ {
@ -717,66 +691,64 @@ void smf_s5c_handle_delete_bearer_response(
ogs_error("No Cause"); ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
/* Release entire session: */
return true;
}
ogs_assert(OGS_OK == /*
smf_epc_pfcp_send_session_deletion_request( * 1. MME sends Bearer Resource Command to SGW/SMF.
sess, NULL)); * 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 { if (rsp->cause.presence) {
/* ogs_gtp2_cause_t *cause = rsp->cause.data;
* 1. MME sends Bearer Resource Command to SGW/SMF. ogs_assert(cause);
* 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) { cause_value = cause->value;
ogs_gtp2_cause_t *cause = rsp->cause.data; if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_assert(cause); if (rsp->bearer_contexts.cause.presence) {
cause = rsp->bearer_contexts.cause.data;
ogs_assert(cause);
cause_value = cause->value; 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;
}
} else { } else {
ogs_warn("GTP Failed [CAUSE:%d]", cause_value); ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
} else { } else {
ogs_error("No Cause"); ogs_warn("GTP Failed [CAUSE:%d]", cause_value);
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
} else {
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_error("No Cause");
sess->sgw_s5c_teid, sess->smf_n4_teid); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
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));
} }
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) static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp2_tft_t *tft, int i)

View File

@ -34,7 +34,7 @@ void smf_s5c_handle_echo_response(
uint8_t smf_s5c_handle_create_session_request( uint8_t smf_s5c_handle_create_session_request(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_create_session_request_t *req); 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_delete_session_request_t *req); ogs_gtp2_delete_session_request_t *req);
void smf_s5c_handle_modify_bearer_request( 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( void smf_s5c_handle_update_bearer_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_update_bearer_response_t *req); 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, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_delete_bearer_response_t *req); ogs_gtp2_delete_bearer_response_t *req);
void smf_s5c_handle_bearer_resource_command( void smf_s5c_handle_bearer_resource_command(

View File

@ -20,7 +20,7 @@
#include "fd-path.h" #include "fd-path.h"
static struct session_handler *smf_s6b_reg = NULL; 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 { struct sess_state {
smf_sess_t *sess; 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); 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) struct session *sess, void *opaque, enum disp_action *act)
{ {
/* This CB should never be called */ /* This CB should never be called */
ogs_warn("Unexpected message received!"); ogs_warn("Unexpected message received!");
return ENOTSUP; 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; smf_ue_t *smf_ue = NULL;
char *user_name = NULL; char *user_name = NULL;
ogs_assert(xact); //ogs_assert(xact);
ogs_assert(sess); ogs_assert(sess);
smf_ue = sess->smf_ue; smf_ue = sess->smf_ue;
ogs_assert(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) static void smf_s6b_sta_cb(void *data, struct msg **msg)
{ {
int ret; int ret;
int rv;
struct sess_state *sess_data = NULL; struct sess_state *sess_data = NULL;
struct timespec ts; struct timespec ts;
@ -612,11 +613,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
unsigned long dur; unsigned long dur;
int error = 0; int error = 0;
int new; int new;
int result_code = 0;
int exp_result_code = 0;
smf_event_t *e = NULL;
smf_sess_t *sess = 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]"); 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); ogs_debug(" Retrieve its data: [%s]", sess_data->s6b_sid);
sess = sess_data->sess; sess = sess_data->sess;
ogs_assert(sess);
xact = sess_data->xact; s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t));
ogs_assert(xact); ogs_assert(s6b_message);
/* Set Session Termination Command */
s6b_message->cmd_code = OGS_DIAM_S6B_CMD_SESSION_TERMINATION;
/* Value of Result Code */ /* Value of Result Code */
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); 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) { if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr); ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0); ogs_assert(ret == 0);
result_code = hdr->avp_value->i32; s6b_message->result_code = hdr->avp_value->i32;
if (result_code != ER_DIAMETER_SUCCESS) { s6b_message->err = &s6b_message->result_code;
ogs_error("Result Code: %d", result_code); if (s6b_message->result_code != ER_DIAMETER_SUCCESS) {
ogs_error("Result Code: %d", s6b_message->result_code);
error++; error++;
} }
} else { } else {
@ -665,8 +668,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
if (avpch1) { if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr); ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0); ogs_assert(ret == 0);
exp_result_code = hdr->avp_value->i32; s6b_message->result_code = hdr->avp_value->i32;
ogs_error("Experimental Result Code: %d", exp_result_code); s6b_message->exp_err = &s6b_message->result_code;
ogs_error("Experimental Result Code: %d",
s6b_message->result_code);
} }
} else { } else {
ogs_error("no Result-Code"); ogs_error("no Result-Code");
@ -700,8 +705,21 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg)
} }
if (!error) { if (!error) {
smf_gx_send_ccr(sess, xact, e = smf_event_new(SMF_EVT_S6B_MESSAGE);
OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST); 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 */ /* Free the message */

View File

@ -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_gx_message_t *gx_message = NULL;
ogs_diam_gy_message_t *gy_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_node_t *pfcp_node = NULL;
ogs_pfcp_xact_t *pfcp_xact = 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); ogs_fsm_dispatch(&sess->sm, e);
break; break;
case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE:
smf_s5c_handle_delete_session_request( if (!sess) {
sess, gtp_xact, &gtp2_message.delete_session_request); 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; break;
case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE:
smf_s5c_handle_modify_bearer_request( 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, &gtp2_message.update_bearer_response); sess, gtp_xact, &gtp2_message.update_bearer_response);
break; break;
case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE:
smf_s5c_handle_delete_bearer_response( if (!sess) {
sess, gtp_xact, &gtp2_message.delete_bearer_response); /* TODO: NACK the message */
break;
}
e->sess = sess;
ogs_fsm_dispatch(&sess->sm, e);
break; break;
case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE:
smf_s5c_handle_bearer_resource_command( 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); ogs_fsm_dispatch(&sess->sm, e);
break; break;
case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE: case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE:
smf_gn_handle_delete_pdp_context_request( if (!sess) {
sess, gtp_xact, &gtp1_message.delete_pdp_context_request); 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; break;
case OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE: case OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE:
smf_gn_handle_update_pdp_context_request( 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) { switch(gx_message->cmd_code) {
case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL: case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL:
gtp_xact = e->gtp_xact;
ogs_assert(gtp_xact);
switch(gx_message->cc_request_type) { switch(gx_message->cc_request_type) {
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST: case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
ogs_fsm_dispatch(&sess->sm, e); ogs_fsm_dispatch(&sess->sm, e);
break; break;
case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST: case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
smf_gx_handle_cca_termination_request( ogs_fsm_dispatch(&sess->sm, e);
sess, gx_message, gtp_xact);
break; break;
default: default:
ogs_error("Not implemented(%d)", gx_message->cc_request_type); 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); ogs_fsm_dispatch(&sess->sm, e);
break; break;
case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST: case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST:
ogs_assert(e->pfcp_xact); ogs_assert(e->pfcp_xact);
smf_gy_handle_cca_update_request( smf_gy_handle_cca_update_request(
sess, gy_message, e->pfcp_xact); sess, gy_message, e->pfcp_xact);
break; break;
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST: case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
ogs_assert(e->gtp_xact); ogs_fsm_dispatch(&sess->sm, e);
smf_gy_handle_cca_termination_request(
sess, gy_message, e->gtp_xact);
break; break;
default: default:
ogs_error("Not implemented(%d)", gy_message->cc_request_type); 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); ogs_free(gy_message);
break; 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: case SMF_EVT_N4_MESSAGE:
ogs_assert(e); ogs_assert(e);
recvbuf = e->pkbuf; 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)) { if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
ogs_error("[%s] State machine exception", smf_ue->supi); ogs_error("[%s] State machine exception", smf_ue->supi);
SMF_SESS_CLEAR(sess); SMF_SESS_CLEAR(sess);
} else if (OGS_FSM_CHECK(
&sess->sm, smf_gsm_state_session_will_release)) {
SMF_SESS_CLEAR(sess);
} }
break; break;

View File

@ -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_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_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_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_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_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_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_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_will_associate(ogs_fsm_t *s, smf_event_t *e);
void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e); void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e);