lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/38486?usp=email )
Change subject: vlr: Add support for CS and PS timers ......................................................................
vlr: Add support for CS and PS timers
To prepare for PS support, add related PS timers and try to keep the code simple to support both domains. Use osmo_tdef_fsm_inst_state_chg() where possible because this way we can have a t_def pointer which we set at the start.
Change-Id: I364973b8d9e277ec5963343c0a83061e81a5baba --- M include/osmocom/vlr/vlr.h M src/libmsc/msc_vty.c M src/libvlr/vlr.c M src/libvlr/vlr_access_req_fsm.c M src/libvlr/vlr_access_req_fsm.h M src/libvlr/vlr_auth_fsm.c M src/libvlr/vlr_auth_fsm.h M src/libvlr/vlr_lu_fsm.c M src/libvlr/vlr_lu_fsm.h M tests/msc_vlr/msc_vlr_test_no_authen.c 10 files changed, 129 insertions(+), 41 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/86/38486/1
diff --git a/include/osmocom/vlr/vlr.h b/include/osmocom/vlr/vlr.h index 257dd09..ed6438b 100644 --- a/include/osmocom/vlr/vlr.h +++ b/include/osmocom/vlr/vlr.h @@ -421,7 +421,10 @@ bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn); bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei);
-unsigned long vlr_timer_secs(struct vlr_instance *vlr, int timer); +unsigned long vlr_timer_secs(struct vlr_instance *vlr, int cs_timer, int ps_timer); + +/* vlr_tdefs is pointing to msc_tdefs_vlr or sgsn_tdefs_vlr depending on the domain*/ +extern struct osmo_tdef *vlr_tdefs;
int vlr_subscr_changed(struct vlr_subscr *vsub); int vlr_subscr_purge(struct vlr_subscr *vsub) __attribute__((warn_unused_result)); diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index d9eec51..7e6b350 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -1048,7 +1048,7 @@ VTY_NEWLINE); }
- if (!vlr_timer_secs(vsub->vlr, 3212)) { + if (!vlr_timer_secs(vsub->vlr, 3212, 3312)) { MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s", VTY_NEWLINE); } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) { diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index 0575583..73e3a9f 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -200,14 +200,28 @@ { /* terminator */ } };
+/* 3GPP TS 24.008, table 11.2 Mobility management timers (network-side) */ +struct osmo_tdef sgsn_tdefs_vlr[] = { + { .T = 3312, .default_val = 60, .unit = OSMO_TDEF_M, .desc = "Subscriber expiration timeout" }, + { .T = 3350, .default_val = 6, .desc = "Attach/RAU Complete Reallocation procedure" }, + { .T = 3360, .default_val = 6, .desc = "Authentication procedure" }, + { .T = 3370, .default_val = 6, .desc = "Identification procedure" }, + { /* terminator */ } +}; + +struct osmo_tdef *vlr_tdefs; + /* This is just a wrapper around the osmo_tdef API. * TODO: we should start using osmo_tdef_fsm_inst_state_chg() */ -unsigned long vlr_timer_secs(struct vlr_instance *vlr, int timer) +unsigned long vlr_timer_secs(struct vlr_instance *vlr, int cs_timer, int ps_timer) { /* NOTE: since we usually do not need more than one instance of the VLR, * and since libosmocore's osmo_tdef API does not (yet) support dynamic * configuration, we always use the global instance of msc_tdefs_vlr. */ - return osmo_tdef_get(msc_tdefs_vlr, timer, OSMO_TDEF_S, 0); + if (vlr_is_cs(vlr)) + return osmo_tdef_get(vlr_tdefs, cs_timer, OSMO_TDEF_S, 0); + else + return osmo_tdef_get(vlr_tdefs, ps_timer, OSMO_TDEF_S, 0); }
/* return static buffer with printable name of VLR subscriber */ @@ -732,7 +746,7 @@
/* Mark the subscriber as inactive if it stopped to do periodical location updates. */ if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) { - vsub->expire_lu = now.tv_sec + vlr_timer_secs(vsub->vlr, 3212); + vsub->expire_lu = now.tv_sec + vlr_timer_secs(vsub->vlr, 3212, 3312); } else { LOGVLR(LOGL_ERROR, "%s: Could not enable Location Update expiry: unable to read current time\n", vlr_subscr_name(vsub)); @@ -749,7 +763,7 @@
/* Periodic location update might be disabled from the VTY, * so we shall not expire subscribers until explicit IMSI Detach. */ - if (!vlr_timer_secs(vlr, 3212)) + if (!vlr_timer_secs(vlr, 3212, 3312)) goto done;
if (llist_empty(&vlr->subscribers)) @@ -1551,16 +1565,23 @@
/* reset shared timer definitions */ osmo_tdefs_reset(msc_tdefs_vlr); + osmo_tdefs_reset(sgsn_tdefs_vlr);
/* osmo_auth_fsm.c */ - vlr_auth_fsm_init(); + vlr_auth_fsm_init(is_ps); + /* osmo_lu_fsm.c */ - vlr_lu_fsm_init(); + vlr_lu_fsm_init(is_ps); /* vlr_access_request_fsm.c */ - vlr_parq_fsm_init(); + vlr_parq_fsm_init(is_ps); /* vlr_sgs_fsm.c */ vlr_sgs_fsm_init();
+ if (is_ps) + vlr_tdefs = sgsn_tdefs_vlr; + else + vlr_tdefs = msc_tdefs_vlr; + return vlr;
err_statg: diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c index 910ee67..3b897cd 100644 --- a/src/libvlr/vlr_access_req_fsm.c +++ b/src/libvlr/vlr_access_req_fsm.c @@ -20,6 +20,7 @@ */
#include <osmocom/core/fsm.h> +#include <osmocom/core/tdef.h> #include <osmocom/gsm/gsup.h> #include <osmocom/gsm/gsm48.h> #include <osmocom/vlr/vlr.h> @@ -50,6 +51,18 @@ { 0, NULL } };
+struct osmo_tdef_state_timeout msc_parq_tdef_states[32] = { + [PR_ARQ_S_WAIT_CHECK_IMEI] = { .T = 3270 }, + [PR_ARQ_S_WAIT_OBTAIN_IMSI] = { .T = 3270 }, +}; + +struct osmo_tdef_state_timeout sgsn_parq_tdef_states[32] = { + [PR_ARQ_S_WAIT_CHECK_IMEI] = { .T = 3370 }, + [PR_ARQ_S_WAIT_OBTAIN_IMSI] = { .T = 3370 }, +}; + +struct osmo_tdef_state_timeout *parq_fsm_state_tdef; + struct proc_arq_priv { struct vlr_instance *vlr; struct vlr_subscr *vsub; @@ -201,8 +214,7 @@ if (0 /* IMEI check required */) { /* Chck_IMEI_VLR */ vlr->ops.tx_id_req(par->msc_conn_ref, GSM_MI_TYPE_IMEI); - osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CHECK_IMEI, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CHECK_IMEI, parq_fsm_state_tdef, vlr_tdefs, 0); } else _proc_arq_vlr_post_imei(fi); } @@ -404,8 +416,7 @@ /* TMSI was included, are we permitted to use it? */ if (vlr->cfg.parq_retrieve_imsi) { /* Obtain_IMSI_VLR */ - osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_OBTAIN_IMSI, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_OBTAIN_IMSI, parq_fsm_state_tdef, vlr_tdefs, 0); return; } else { /* Set User Error: Unidentified Subscriber */ @@ -803,8 +814,13 @@ }; #endif
-void vlr_parq_fsm_init(void) +void vlr_parq_fsm_init(bool is_ps) { + if (is_ps) + parq_fsm_state_tdef = sgsn_parq_tdef_states; + else + parq_fsm_state_tdef = msc_parq_tdef_states; + //OSMO_ASSERT(osmo_fsm_register(&upd_loc_child_vlr_fsm) == 0); OSMO_ASSERT(osmo_fsm_register(&proc_arq_vlr_fsm) == 0); } diff --git a/src/libvlr/vlr_access_req_fsm.h b/src/libvlr/vlr_access_req_fsm.h index d6cbabd..42b2c7e 100644 --- a/src/libvlr/vlr_access_req_fsm.h +++ b/src/libvlr/vlr_access_req_fsm.h @@ -16,5 +16,5 @@ PR_ARQ_S_DONE, };
-void vlr_parq_fsm_init(void); +void vlr_parq_fsm_init(bool is_ps); void vlr_parq_fsm_set_log_subsys(int log_level); diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c index 2405131..d00219b 100644 --- a/src/libvlr/vlr_auth_fsm.c +++ b/src/libvlr/vlr_auth_fsm.c @@ -21,6 +21,7 @@
#include <osmocom/core/fsm.h> +#include <osmocom/core/tdef.h> #include <osmocom/core/utils.h> #include <osmocom/gsm/gsup.h> #include <osmocom/vlr/vlr.h> @@ -41,6 +42,20 @@ { 0, NULL } };
+struct osmo_tdef_state_timeout msc_auth_tdef_states[32] = { + [VLR_SUB_AS_WAIT_RESP] = { .T = 3260 }, + [VLR_SUB_AS_WAIT_RESP_RESYNC] = { .T = 3260 }, + [VLR_SUB_AS_WAIT_ID_IMSI] = { .T = 3270 }, +}; + +struct osmo_tdef_state_timeout sgsn_auth_tdef_states[32] = { + [VLR_SUB_AS_WAIT_RESP] = { .T = 3360 }, + [VLR_SUB_AS_WAIT_RESP_RESYNC] = { .T = 3360 }, + [VLR_SUB_AS_WAIT_ID_IMSI] = { .T = 3370 }, +}; + +struct osmo_tdef_state_timeout *auth_fsm_state_tdef; + /* private state of the auth_fsm_instance */ struct auth_fsm_priv { struct vlr_subscr *vsub; @@ -344,8 +359,7 @@ GSM_29002_TIMER_M, 0); } else { /* go straight ahead with sending auth request */ - osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP, - vlr_timer_secs(vsub->vlr, 3260), 3260); + osmo_tdef_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP, auth_fsm_state_tdef, vlr_tdefs, 6); _vlr_subscr_authenticate(fi); } } @@ -398,8 +412,8 @@
return; pass: - osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP, - vlr_timer_secs(vsub->vlr, 3260), 3260); + osmo_tdef_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP, auth_fsm_state_tdef, vlr_tdefs, 0); + _vlr_subscr_authenticate(fi); }
@@ -421,9 +435,7 @@ if (!afp->by_imsi) { vlr->ops.tx_id_req(vsub->msc_conn_ref, GSM_MI_TYPE_IMSI); - osmo_fsm_inst_state_chg(fi, - VLR_SUB_AS_WAIT_ID_IMSI, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_ID_IMSI, auth_fsm_state_tdef, vlr_tdefs, 0); } else { auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_ILLEGAL_MS); } @@ -465,8 +477,7 @@ switch (event) { case VLR_AUTH_E_HLR_SAI_ACK: vlr_subscr_update_tuples(vsub, gsup); - osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP_RESYNC, - vlr_timer_secs(vsub->vlr, 3260), 3260); + osmo_tdef_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP_RESYNC, auth_fsm_state_tdef, vlr_tdefs, 0); _vlr_subscr_authenticate(fi); break; case VLR_AUTH_E_HLR_SAI_NACK: @@ -497,9 +508,7 @@ if (!afp->by_imsi) { vlr->ops.tx_id_req(vsub->msc_conn_ref, GSM_MI_TYPE_IMSI); - osmo_fsm_inst_state_chg(fi, - VLR_SUB_AS_WAIT_ID_IMSI, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_ID_IMSI, auth_fsm_state_tdef, vlr_tdefs, 0); } else { /* Result = Aborted */ auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_SYNCH_FAILURE); @@ -614,8 +623,13 @@ .cleanup = auth_fsm_cleanup, };
-void vlr_auth_fsm_init(void) +void vlr_auth_fsm_init(bool is_ps) { + if (is_ps) + auth_fsm_state_tdef = sgsn_auth_tdef_states; + else + auth_fsm_state_tdef = msc_auth_tdef_states; + OSMO_ASSERT(osmo_fsm_register(&vlr_auth_fsm) == 0); }
diff --git a/src/libvlr/vlr_auth_fsm.h b/src/libvlr/vlr_auth_fsm.h index 139f919..1cb25b6 100644 --- a/src/libvlr/vlr_auth_fsm.h +++ b/src/libvlr/vlr_auth_fsm.h @@ -37,6 +37,6 @@ bool is_r99, bool is_utran);
-void vlr_auth_fsm_init(void); +void vlr_auth_fsm_init(bool is_ps); void vlr_auth_fsm_set_log_subsys(int log_level); bool auth_try_reuse_tuple(struct vlr_subscr *vsub, uint8_t key_seq); diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index 2017cb8..fca8347 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -20,6 +20,7 @@ */
#include <osmocom/core/fsm.h> +#include <osmocom/core/tdef.h> #include <osmocom/gsm/gsm48.h> #include <osmocom/vlr/vlr.h>
@@ -328,6 +329,20 @@ { 0, NULL } };
+struct osmo_tdef_state_timeout msc_lu_compl_tdef_states[32] = { + [LU_COMPL_VLR_S_WAIT_IMEI] = { .T = 3270 }, + [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = { .T = 3270 }, + [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = { .T = 3250 }, +}; + +struct osmo_tdef_state_timeout sgsn_lu_compl_tdef_states[32] = { + [LU_COMPL_VLR_S_WAIT_IMEI] = { .T = 3370 }, + [LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = { .T = 3370 }, + [LU_COMPL_VLR_S_WAIT_TMSI_CNF] = { .T = 3350 }, +}; + +struct osmo_tdef_state_timeout *lu_compl_fsm_state_tdef; + struct lu_compl_vlr_priv { struct vlr_subscr *vsub; void *msc_conn_ref; @@ -431,8 +446,7 @@ return; }
- osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF, - vlr_timer_secs(vlr, 3250), 3250); + osmo_tdef_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF, lu_compl_fsm_state_tdef, vlr_tdefs, 6);
vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new, lcvp->lu_type); } @@ -455,11 +469,11 @@ /* If imeisv_early is enabled: IMEI already retrieved and checked (vlr_loc_upd_node1_pre), don't do it again. */ if (vlr->cfg.check_imei_rqd && !vlr->cfg.retrieve_imeisv_early) { /* Check IMEI VLR */ - osmo_fsm_inst_state_chg(fi, + osmo_tdef_fsm_inst_state_chg(fi, lcvp->assign_tmsi ? LU_COMPL_VLR_S_WAIT_IMEI_TMSI : LU_COMPL_VLR_S_WAIT_IMEI, - vlr_timer_secs(vlr, 3270), 3270); + lu_compl_fsm_state_tdef, vlr_tdefs, 6); vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI); return; } @@ -665,6 +679,20 @@ { 0, NULL } };
+struct osmo_tdef_state_timeout msc_lu_tdef_states[32] = { + [VLR_ULA_S_WAIT_IMEISV] = { .T = 3270 }, + [VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY] = { .T = 3270 }, + [VLR_ULA_S_WAIT_IMSI] = { .T = 3270 }, +}; + +struct osmo_tdef_state_timeout sgsn_lu_tdef_states[32] = { + [VLR_ULA_S_WAIT_IMEISV] = { .T = 3370 }, + [VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY] = { .T = 3370 }, + [VLR_ULA_S_WAIT_IMSI] = { .T = 3370 }, +}; + +struct osmo_tdef_state_timeout *lu_fsm_state_tdef; + struct lu_fsm_priv { struct vlr_instance *vlr; struct vlr_subscr *vsub; @@ -942,7 +970,7 @@ LOGPFSM(fi, "%s()\n", __func__);
if (vlr->cfg.check_imei_rqd && vlr->cfg.retrieve_imeisv_early) { - osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY, vlr_timer_secs(lfp->vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_CHECK_IMEI_EARLY, lu_fsm_state_tdef, vlr_tdefs, 0); vlr_subscr_tx_req_check_imei(lfp->vsub); } else { vlr_loc_upd_node1(fi); @@ -977,8 +1005,7 @@ OSMO_ASSERT(lfp->vsub);
/* Obtain_IMSI_VLR */ - osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI, lu_fsm_state_tdef, vlr_tdefs, 0); vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI); /* will continue at vlr_loc_upd_node1_pre() once IMSI arrives */ } @@ -1114,8 +1141,7 @@ _start_lu_main(fi); } else { vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMEISV); - osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV, - vlr_timer_secs(vlr, 3270), 3270); + osmo_tdef_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV, lu_fsm_state_tdef, vlr_tdefs, 0); } }
@@ -1587,8 +1613,16 @@ lu_fsm_failure(fi, gsm48_cause); }
-void vlr_lu_fsm_init(void) +void vlr_lu_fsm_init(bool is_ps) { + if (is_ps) { + lu_fsm_state_tdef = sgsn_lu_tdef_states; + lu_compl_fsm_state_tdef = sgsn_lu_compl_tdef_states; + } else { + lu_fsm_state_tdef = msc_lu_tdef_states; + lu_compl_fsm_state_tdef = msc_lu_compl_tdef_states; + } + OSMO_ASSERT(osmo_fsm_register(&vlr_lu_fsm) == 0); OSMO_ASSERT(osmo_fsm_register(&upd_hlr_vlr_fsm) == 0); OSMO_ASSERT(osmo_fsm_register(&sub_pres_vlr_fsm) == 0); diff --git a/src/libvlr/vlr_lu_fsm.h b/src/libvlr/vlr_lu_fsm.h index 86acd58..1eee75d 100644 --- a/src/libvlr/vlr_lu_fsm.h +++ b/src/libvlr/vlr_lu_fsm.h @@ -16,5 +16,5 @@ VLR_ULA_S_DONE };
-void vlr_lu_fsm_init(void); +void vlr_lu_fsm_init(bool is_ps); void vlr_lu_fsm_set_log_subsys(int log_subsys); diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.c b/tests/msc_vlr/msc_vlr_test_no_authen.c index 384a069..8d8b153 100644 --- a/tests/msc_vlr/msc_vlr_test_no_authen.c +++ b/tests/msc_vlr/msc_vlr_test_no_authen.c @@ -941,7 +941,7 @@ vlr_subscr_put(vsub, __func__);
/* Let T3212 (periodic Location update timer) expire */ - fake_time_passes(vlr_timer_secs(net->vlr, 3212) + 60 * 4, 0); + fake_time_passes(vlr_timer_secs(net->vlr, 3212, 3312) + 60 * 4, 0);
/* The subscriber should now be gone. */ vsub = vlr_subscr_find_by_imsi(net->vlr, imsi, __func__);