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 committed Jan 20, 2024
1 parent d47d5ab commit 1ab26c6
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 2 deletions.
9 changes: 8 additions & 1 deletion lib/app/ogs-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ static int local_conf_prepare(void)
local_conf.time.message.sbi_set = false;
local_conf.time.message.gtp_set = false;
local_conf.time.message.pfcp_set = false;

local_conf.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 @@ -647,6 +647,13 @@ int ogs_app_parse_local_conf(const char *local)
local_conf.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) {
local_conf.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-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct ogs_local_conf_s {
ogs_time_t sbi_duration;
ogs_time_t gtp_duration;
ogs_time_t pfcp_duration;
ogs_time_t diameter_timeout;
bool sbi_set;
bool gtp_set;
bool pfcp_set;
Expand Down
3 changes: 3 additions & 0 deletions src/smf/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,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;

bool n1_released;
Expand Down
3 changes: 2 additions & 1 deletion src/smf/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ 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,
SMF_EVT_N4_NO_HEARTBEAT,
Expand Down
112 changes: 112 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_local_conf()->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_local_conf()->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_local_conf()->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_local_conf()->time.message.diameter_timeout);
smf_gy_send_ccr(sess, e->gtp_xact,
OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST);
}
Expand Down Expand Up @@ -227,6 +246,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_local_conf()->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 @@ -353,6 +376,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 @@ -372,12 +399,37 @@ 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->h.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 @@ -1432,6 +1484,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 @@ -1451,6 +1506,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 @@ -1470,6 +1528,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->h.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 @@ -1881,6 +1960,15 @@ void smf_gsm_state_epc_session_will_release(ogs_fsm_t *s, smf_event_t *e)

switch (e->h.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 @@ -1910,6 +1998,15 @@ void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)

switch (e->h.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 @@ -1925,4 +2022,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 @@ -357,6 +357,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
24 changes: 24 additions & 0 deletions src/smf/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,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 All @@ -64,6 +65,19 @@ static void timer_send_event(int timer_id, void *data)
e->h.timer_id = timer_id;
e->pfcp_node = 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->h.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 All @@ -87,3 +101,13 @@ void smf_timer_pfcp_no_heartbeat(void *data)
{
timer_send_event(SMF_TIMER_PFCP_NO_HEARTBEAT, 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 @@ -33,6 +33,8 @@ typedef enum {
SMF_TIMER_PFCP_ASSOCIATION,
SMF_TIMER_PFCP_NO_HEARTBEAT,
SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE,
SMF_TIMER_GX_CCA,
SMF_TIMER_GY_CCA,

MAX_NUM_OF_SMF_TIMER,

Expand All @@ -42,6 +44,8 @@ const char *smf_timer_get_name(int timer_id);

void smf_timer_pfcp_association(void *data);
void smf_timer_pfcp_no_heartbeat(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 1ab26c6

Please sign in to comment.