Skip to content

Commit

Permalink
[smf] add timeouts for Diameter (Gx/Gy) messages (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
spencersevilla authored and Spencer Sevilla committed Feb 6, 2023
1 parent 540b3eb commit fb4b31d
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/app/ogs-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ static void app_context_prepare(void)
self.time.message.sbi_duration = ogs_time_from_sec(10);
self.time.message.gtp_duration = ogs_time_from_sec(10);
self.time.message.pfcp_duration = ogs_time_from_sec(10);
self.time.message.diameter_timeout = ogs_time_from_sec(3);

#define PFCP_N1_RESPONSE_RETRY_COUNT 3
#define GTP_N3_RESPONSE_RETRY_COUNT 3
Expand Down Expand Up @@ -567,6 +568,13 @@ int ogs_app_context_parse_config(void)
self.time.message.gtp.n3_response_rcount = atoi(v);
regenerate_all_timer_duration();
}
} else if (!strcmp(msg_key, "diameter_timeout")) {
const char *v = ogs_yaml_iter_value(&msg_iter);
if (v) {
self.time.message.diameter_timeout =
ogs_time_from_msec(atoll(v));
regenerate_all_timer_duration();
}
} else
ogs_warn("unknown key `%s`", msg_key);
}
Expand Down
1 change: 1 addition & 0 deletions lib/app/ogs-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ typedef struct ogs_app_context_s {
ogs_time_t sbi_duration;
ogs_time_t gtp_duration;
ogs_time_t pfcp_duration;
ogs_time_t diameter_timeout;

struct {
ogs_time_t client_wait_duration;
Expand Down
3 changes: 3 additions & 0 deletions src/smf/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ typedef struct smf_sess_s {
ogs_pfcp_node_t *pfcp_node;
bool pfcp_established;

ogs_timer_t *timer_gx_cca;
ogs_timer_t *timer_gy_cca;

smf_ue_t *smf_ue;
} smf_sess_t;

Expand Down
1 change: 1 addition & 0 deletions src/smf/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef enum {
SMF_EVT_GN_MESSAGE,
SMF_EVT_GX_MESSAGE,
SMF_EVT_GY_MESSAGE,
SMF_EVT_DIAMETER_TIMER,

SMF_EVT_N4_MESSAGE,
SMF_EVT_N4_TIMER,
Expand Down
111 changes: 111 additions & 0 deletions src/smf/gsm-sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ static uint8_t gtp_cause_from_diameter(uint8_t gtp_version,
switch (dia_err) {
case OGS_DIAM_UNKNOWN_SESSION_ID:
return OGS_GTP1_CAUSE_APN_ACCESS_DENIED;
case ER_DIAMETER_UNABLE_TO_DELIVER:
return OGS_GTP1_CAUSE_USER_AUTHENTICATION_FAILED;
}
break;
case 2:
switch (dia_err) {
case OGS_DIAM_UNKNOWN_SESSION_ID:
return OGS_GTP2_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION;
case ER_DIAMETER_UNABLE_TO_DELIVER:
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
}
break;
}
Expand Down Expand Up @@ -104,13 +108,21 @@ static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e)
}

sess->sm_data.gx_ccr_init_in_flight = true;
sess->timer_gx_cca = ogs_timer_add(ogs_app()->timer_mgr,
smf_timer_gx_no_cca, e);
ogs_assert(sess->timer_gx_cca);
ogs_timer_start(sess->timer_gx_cca, ogs_app()->time.message.diameter_timeout);
smf_gx_send_ccr(sess, e->gtp_xact,
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_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_init_in_flight = true;
sess->timer_gy_cca = ogs_timer_add(ogs_app()->timer_mgr,
smf_timer_gy_no_cca, e);
ogs_assert(sess->timer_gy_cca);
ogs_timer_start(sess->timer_gy_cca, ogs_app()->time.message.diameter_timeout);
smf_gy_send_ccr(sess, e->gtp_xact,
OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST);
}
Expand Down Expand Up @@ -141,13 +153,20 @@ static bool send_ccr_termination_req_gx_gy_s6b(smf_sess_t *sess, smf_event_t *e)
}

sess->sm_data.gx_ccr_term_in_flight = true;
sess->timer_gx_cca = ogs_timer_add(ogs_app()->timer_mgr, smf_timer_gx_no_cca, e);
ogs_assert(sess->timer_gx_cca);
ogs_timer_start(sess->timer_gx_cca, ogs_app()->time.message.diameter_timeout);
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;
sess->timer_gy_cca = ogs_timer_add(ogs_app()->timer_mgr,
smf_timer_gy_no_cca, e);
ogs_assert(sess->timer_gy_cca);
ogs_timer_start(sess->timer_gy_cca, ogs_app()->time.message.diameter_timeout);
smf_gy_send_ccr(sess, e->gtp_xact,
OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST);
}
Expand Down Expand Up @@ -284,6 +303,10 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
break;
case OGS_GTP2_RAT_TYPE_WLAN:
sess->timer_gx_cca = ogs_timer_add(ogs_app()->timer_mgr,
smf_timer_gx_no_cca, e);
ogs_assert(sess->timer_gx_cca);
ogs_timer_start(sess->timer_gx_cca, ogs_app()->time.message.diameter_timeout);
smf_s6b_send_aar(sess, e->gtp_xact);
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
break;
Expand Down Expand Up @@ -410,6 +433,10 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
diam_err = smf_gx_handle_cca_initial_request(sess,
gx_message, e->gtp_xact);
sess->sm_data.gx_ccr_init_in_flight = false;
ogs_timer_stop(sess->timer_gx_cca);
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;

sess->sm_data.gx_cca_init_err = diam_err;
goto test_can_proceed;
}
Expand All @@ -429,12 +456,36 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
diam_err = smf_gy_handle_cca_initial_request(sess,
gy_message, e->gtp_xact);
sess->sm_data.gy_ccr_init_in_flight = false;
ogs_timer_stop(sess->timer_gy_cca);
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
sess->sm_data.gy_cca_init_err = diam_err;
goto test_can_proceed;
}
break;
}
break;

case SMF_EVT_DIAMETER_TIMER:
switch(e->timer_id) {
case SMF_TIMER_GX_CCA:
ogs_error("Gx timeout waiting for CCA Init");
sess->sm_data.gx_ccr_init_in_flight = false;
ogs_timer_stop(sess->timer_gx_cca);
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
sess->sm_data.gx_cca_init_err = ER_DIAMETER_UNABLE_TO_DELIVER;
goto test_can_proceed;
case SMF_TIMER_GY_CCA:
ogs_error("Gy timeout waiting for CCA Init");
sess->sm_data.gy_ccr_init_in_flight = false;
ogs_timer_stop(sess->timer_gy_cca);
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
sess->sm_data.gy_cca_init_err = ER_DIAMETER_UNABLE_TO_DELIVER;
goto test_can_proceed;
}
break;
}
return;

Expand Down Expand Up @@ -1354,6 +1405,9 @@ void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e)
diam_err = smf_gx_handle_cca_termination_request(sess,
gx_message, e->gtp_xact);
sess->sm_data.gx_ccr_term_in_flight = false;
ogs_timer_stop(sess->timer_gx_cca);
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
sess->sm_data.gx_cca_term_err = diam_err;
goto test_can_proceed;
}
Expand All @@ -1373,6 +1427,9 @@ void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e)
diam_err = smf_gy_handle_cca_termination_request(sess,
gy_message, e->gtp_xact);
sess->sm_data.gy_ccr_term_in_flight = false;
ogs_timer_stop(sess->timer_gy_cca);
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
sess->sm_data.gy_cca_term_err = diam_err;
goto test_can_proceed;
}
Expand All @@ -1392,6 +1449,27 @@ void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e)
goto test_can_proceed;
}
break;

case SMF_EVT_DIAMETER_TIMER:
switch(e->timer_id) {
case SMF_TIMER_GX_CCA:
ogs_error("Gx timeout waiting for CCA Termination");
sess->sm_data.gx_ccr_term_in_flight = false;
ogs_timer_stop(sess->timer_gx_cca);
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
sess->sm_data.gx_cca_term_err = ER_DIAMETER_UNABLE_TO_DELIVER;
goto test_can_proceed;
case SMF_TIMER_GY_CCA:
ogs_error("Gy timeout waiting for CCA Termination");
sess->sm_data.gy_ccr_term_in_flight = false;
ogs_timer_stop(sess->timer_gy_cca);
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
sess->sm_data.gy_cca_term_err = ER_DIAMETER_UNABLE_TO_DELIVER;
goto test_can_proceed;
}
break;
}
return;

Expand Down Expand Up @@ -1620,6 +1698,15 @@ void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e)

switch (e->id) {
case OGS_FSM_ENTRY_SIG:
if (sess->timer_gx_cca) {
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
}
if (sess->timer_gy_cca) {
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
}

SMF_SESS_CLEAR(sess);
break;

Expand Down Expand Up @@ -1649,6 +1736,15 @@ void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)

switch (e->id) {
case OGS_FSM_ENTRY_SIG:
if (sess->timer_gx_cca) {
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
}
if (sess->timer_gy_cca) {
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
}

ogs_error("[%s:%d] State machine exception", smf_ue->supi, sess->psi);
SMF_SESS_CLEAR(sess);
break;
Expand All @@ -1664,4 +1760,19 @@ void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)

void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
ogs_assert(s);
ogs_assert(e);

sess = e->sess;
ogs_assert(sess);

if (sess->timer_gx_cca) {
ogs_timer_delete(sess->timer_gx_cca);
sess->timer_gx_cca = NULL;
}
if (sess->timer_gy_cca) {
ogs_timer_delete(sess->timer_gy_cca);
sess->timer_gy_cca = NULL;
}
}
9 changes: 9 additions & 0 deletions src/smf/smf-sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,15 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_free(gy_message);
break;

case SMF_EVT_DIAMETER_TIMER:
ogs_assert(e);
sess = e->sess;
if (sess) {
ogs_assert(OGS_FSM_STATE(&sess->sm));
ogs_fsm_dispatch(&sess->sm, e);
}
break;

case SMF_EVT_S6B_MESSAGE:
ogs_assert(e);
s6b_message = e->s6b_message;
Expand Down
22 changes: 22 additions & 0 deletions src/smf/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static void timer_send_event(int timer_id, void *data)
{
int rv;
smf_event_t *e = NULL;
smf_event_t *old_e = NULL;
ogs_assert(data);

switch (timer_id) {
Expand Down Expand Up @@ -84,6 +85,17 @@ static void timer_send_event(int timer_id, void *data)
e->timer_id = timer_id;
e->sbi.data = data;
break;
case SMF_TIMER_GX_CCA:
case SMF_TIMER_GY_CCA:
old_e = data;

e = smf_event_new(SMF_EVT_DIAMETER_TIMER);
ogs_assert(e);
e->timer_id = timer_id;
e->sess = old_e->sess;
e->gx_message = old_e->gx_message;
e->gtp_xact = old_e->gtp_xact;
break;
default:
ogs_fatal("Unknown timer id[%d]", timer_id);
ogs_assert_if_reached();
Expand Down Expand Up @@ -137,3 +149,13 @@ void smf_timer_sbi_client_wait_expire(void *data)
{
timer_send_event(SMF_TIMER_SBI_CLIENT_WAIT, data);
}

void smf_timer_gx_no_cca(void *data)
{
timer_send_event(SMF_TIMER_GX_CCA, data);
}

void smf_timer_gy_no_cca(void *data)
{
timer_send_event(SMF_TIMER_GY_CCA, data);
}
4 changes: 4 additions & 0 deletions src/smf/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ typedef enum {
SMF_TIMER_NF_INSTANCE_VALIDITY,
SMF_TIMER_SUBSCRIPTION_VALIDITY,
SMF_TIMER_SBI_CLIENT_WAIT,
SMF_TIMER_GX_CCA,
SMF_TIMER_GY_CCA,

MAX_NUM_OF_SMF_TIMER,

Expand All @@ -55,6 +57,8 @@ void smf_timer_nf_instance_no_heartbeat(void *data);
void smf_timer_nf_instance_validity(void *data);
void smf_timer_subscription_validity(void *data);
void smf_timer_sbi_client_wait_expire(void *data);
void smf_timer_gx_no_cca(void *data);
void smf_timer_gy_no_cca(void *data);

#ifdef __cplusplus
}
Expand Down

0 comments on commit fb4b31d

Please sign in to comment.