lynxis lazus submitted this change.

View Change

Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified daniel: Looks good to me, approved
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, 131 insertions(+), 43 deletions(-)

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..2b21f70 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -1048,9 +1048,9 @@
VTY_NEWLINE);
}

- if (!vlr_timer_secs(vsub->vlr, 3212)) {
- MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
- VTY_NEWLINE);
+ if (!vlr_timer_secs(vsub->vlr, 3212, 3312)) {
+ MSC_VTY_DUMP(vty, offset, "Expires: never (%s is disabled)%s",
+ vlr_is_cs(vsub->vlr) ? "T3212" : "T3312", VTY_NEWLINE);
} else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
MSC_VTY_DUMP(vty, offset, "Expires: never%s",
VTY_NEWLINE);
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index 32c2fbb..a3570f3 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 */
@@ -731,7 +745,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 {
LOGVSUBP(LOGL_ERROR, vsub,
"Could not enable Location Update expiry: unable to read current time\n");
@@ -748,7 +762,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))
@@ -1550,16 +1564,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..516f53d 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, -1);
} 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, -1);
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 aa031c3..b4ebd05 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, -1);
_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, -1);
+
_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, -1);
} 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, -1);
_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, -1);
} 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..96d1861 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, -1);

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, -1);
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, -1);
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, -1);
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, -1);
}
}

@@ -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__);

To view, visit change 38486. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I364973b8d9e277ec5963343c0a83061e81a5baba
Gerrit-Change-Number: 38486
Gerrit-PatchSet: 5
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann@sysmocom.de>
Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>