pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-gprs/+/32910 )
Change subject: gmm: Initial implementation of T3312
......................................................................
gmm: Initial implementation of T3312
The RAU procedure triggered by T3312 expiration will be implemented
in a follow-up patch.
Change-Id: If1ca164b7a6c7f7750e2e2f0812d6fde828ed4a4
---
M include/osmocom/gprs/gmm/gmm_private.h
M src/gmm/gmm.c
M src/gmm/gmm_ms_fsm.c
3 files changed, 86 insertions(+), 10 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/10/32910/1
diff --git a/include/osmocom/gprs/gmm/gmm_private.h
b/include/osmocom/gprs/gmm/gmm_private.h
index 0ae4df4..daa967f 100644
--- a/include/osmocom/gprs/gmm/gmm_private.h
+++ b/include/osmocom/gprs/gmm/gmm_private.h
@@ -66,7 +66,6 @@
char imei[GSM23003_IMEI_NUM_DIGITS + 1];
char imeisv[GSM23003_IMEISV_NUM_DIGITS+1];
- uint8_t ra_upd_timer; /* TS 24.008 10.5.7.3 */
uint8_t radio_prio; /* TS 24.008 10.5.7.2 */
struct gprs_ra_id ra; /* TS 24.008 10.5.5.15 (decoded) */
@@ -87,6 +86,8 @@
/* READY timer, TS 24.008 4.7.2.1.1 */
struct osmo_timer_list t3314;
unsigned long t3314_assigned_sec; /* value assigned by the network */
+ struct osmo_timer_list t3312; /* periodic RAU, in seconds */
+ unsigned long t3312_assigned_sec; /* value assigned by the network */
};
/* gmm_prim.c: */
@@ -116,6 +117,8 @@
void gprs_gmm_gmme_ready_timer_start(struct gprs_gmm_entity *gmme);
void gprs_gmm_gmme_ready_timer_stop(struct gprs_gmm_entity *gmme);
bool gprs_gmm_gmme_ready_timer_running(const struct gprs_gmm_entity *gmme);
+void gprs_gmm_gmme_t3312_start(struct gprs_gmm_entity *gmme);
+void gprs_gmm_gmme_t3312_stop(struct gprs_gmm_entity *gmme);
int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len);
int gprs_gmm_tx_att_req(struct gprs_gmm_entity *gmme,
enum osmo_gprs_gmm_attach_type attach_type,
diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c
index 5a3b0c0..6184a01 100644
--- a/src/gmm/gmm.c
+++ b/src/gmm/gmm.c
@@ -79,6 +79,7 @@
};
static void t3314_ready_timer_cb(void *data);
+static void t3312_periodic_rau_timer_cb(void *data);
static void gprs_gmm_ctx_free(void)
{
@@ -176,6 +177,7 @@
gmme->t3346 = osmo_tdef_get(g_gmm_ctx->T_defs, 3346, OSMO_TDEF_S, -1);
osmo_timer_setup(&gmme->t3314, t3314_ready_timer_cb, gmme);
+ osmo_timer_setup(&gmme->t3312, t3312_periodic_rau_timer_cb, gmme);
llist_add(&gmme->list, &g_gmm_ctx->gmme_list);
@@ -190,6 +192,8 @@
LOGGMME(gmme, LOGL_DEBUG, "free()\n");
if (osmo_timer_pending(&gmme->t3314))
osmo_timer_del(&gmme->t3314);
+ if (osmo_timer_pending(&gmme->t3312))
+ osmo_timer_del(&gmme->t3312);
gprs_gmm_ms_fsm_ctx_release(&gmme->ms_fsm);
llist_del(&gmme->list);
talloc_free(gmme);
@@ -295,20 +299,23 @@
LOGGMME(gmme, LOGL_INFO, "READY timer started\n");
osmo_timer_schedule(&gmme->t3314, gmme->t3314_assigned_sec, 0);
- /* TODO: "Timer T3312 is stopped and shall be set to its initial value
- * for the next start when the READY timer is started." */
+ /* "Timer T3312 is stopped and shall be set to its initial value
+ * for the next start when the READY timer is started.": */
+ gprs_gmm_gmme_t3312_stop(gmme);
}
/* Ready timer is stopped: */
void gprs_gmm_gmme_ready_timer_stop(struct gprs_gmm_entity *gmme)
{
- /* TODO: "In A/Gb mode, the timer T3312 is reset and started with its
- * initial value, when the READY timer is stopped or expires."
- */
if (!osmo_timer_pending(&gmme->t3314))
return;
LOGGMME(gmme, LOGL_INFO, "READY timer stopped\n");
osmo_timer_del(&gmme->t3314);
+
+ /* "In A/Gb mode, the timer T3312 is reset and started with its
+ * initial value, when the READY timer is stopped or expires."
+ */
+ gprs_gmm_gmme_t3312_start(gmme);
}
bool gprs_gmm_gmme_ready_timer_running(const struct gprs_gmm_entity *gmme)
@@ -325,10 +332,54 @@
struct gprs_gmm_entity *gmme = (struct gprs_gmm_entity *)data;
LOGGMME(gmme, LOGL_INFO, "READY timer expired\n");
- /* TODO: "In A/Gb mode, the timer T3312 is reset and started with its
- *initial value, when the READY timer is stopped or expires."
+ /* "In A/Gb mode, the timer T3312 is reset and started with its
+ * initial value, when the READY timer is stopped or expires.":
*/
+ gprs_gmm_gmme_t3312_start(gmme);
+}
+/* T3312 (Periodic RAU) is started: */
+void gprs_gmm_gmme_t3312_start(struct gprs_gmm_entity *gmme)
+{
+ unsigned long t3312_sec;
+
+ t3312_sec = osmo_tdef_get(g_gmm_ctx->T_defs, 3312, OSMO_TDEF_S, -1);
+ if (t3312_sec == 0)
+ return;
+
+ LOGGMME(gmme, LOGL_INFO, "T3312 started\n");
+ osmo_timer_schedule(&gmme->t3312, t3312_sec, 0);
+}
+
+/* T3312 (Periodic RAU) is stopped: */
+void gprs_gmm_gmme_t3312_stop(struct gprs_gmm_entity *gmme)
+{
+ if (!osmo_timer_pending(&gmme->t3312))
+ return;
+
+ LOGGMME(gmme, LOGL_INFO, "T3312 stopped\n");
+ osmo_timer_del(&gmme->t3312);
+}
+
+/* T3312 (Periodic RAU) timer expiration: */
+static void t3312_periodic_rau_timer_cb(void *data)
+{
+ struct gprs_gmm_entity *gmme = (struct gprs_gmm_entity *)data;
+ LOGGMME(gmme, LOGL_INFO, "T3312 Periodic RAU timer expired\n");
+
+ /* TODO:
+ * - "Initiation of the Periodic RAU procedure if the MS is not
+ * attached for emergency bearer services or T3323 started under the
+ * conditions as specified in subclause 4.7.2.2.
+ * - Implicit detach from network if the MS is attached for emergency
+ * bearer services."
+ * - "If the MS is in a state other than GMM-REGISTERED.NORMAL-SERVICE
+ * when timer T3312 expires, the periodic routing area updating procedure
+ * is delayed until the MS returns to GMM-REGISTERED.NORMAL-SERVICE."
+ * "If timer T3323 expires, the MS shall memorize that it has to initiate a
+ * routing area updating procedure when it returns to state
+ * GMM-REGISTERED.NORMAL-SERVICE."
+ */
}
int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted,
uint8_t cause)
@@ -595,6 +646,7 @@
struct gsm48_attach_ack *aa;
struct tlv_parsed tp;
int rc;
+ int periodic_rau_sec;
if (len < sizeof(*gh) + sizeof(*aa)) {
LOGGMME(gmme, LOGL_ERROR, "Rx GMM ATTACH ACCEPT with wrong size %u\n", len);
@@ -604,8 +656,11 @@
LOGGMME(gmme, LOGL_INFO, "Rx GMM ATTACH ACCEPT\n");
aa = (struct gsm48_attach_ack *)&gh->data[0];
- gmme->ra_upd_timer = aa->ra_upd_timer;
+ periodic_rau_sec = gprs_gmm_gprs_tmr_to_secs(aa->ra_upd_timer);
gmme->radio_prio = aa->radio_prio;
+ gmme->t3312_assigned_sec = periodic_rau_sec >= 0 ? periodic_rau_sec : 0;
+ if (gmme->t3312_assigned_sec == 0)
+ gprs_gmm_gmme_t3312_stop(gmme);
gsm48_parse_ra(&gmme->ra, (const uint8_t *)&aa->ra_id);
if (len > sizeof(*gh) + sizeof(*aa)) {
@@ -632,8 +687,13 @@
gmme->t3314_assigned_sec = osmo_tdef_get(g_gmm_ctx->T_defs, 3314, OSMO_TDEF_S,
-1);
}
/* "If the negotiated READY timer value is set to zero, the READY timer shall be
stopped immediately": */
- if (gmme->t3314_assigned_sec == 0)
+ if (gmme->t3314_assigned_sec == 0) {
gprs_gmm_gmme_ready_timer_stop(gmme);
+ /* "If after a READY timer negotiation the READY timer
+ * value is set to zero, timer T3312 is reset and started
+ * with its initial value." */
+ gprs_gmm_gmme_t3312_start(gmme);
+ }
if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) {
struct osmo_mobile_identity mi;
diff --git a/src/gmm/gmm_ms_fsm.c b/src/gmm/gmm_ms_fsm.c
index fcaf0d6..889d82a 100644
--- a/src/gmm/gmm_ms_fsm.c
+++ b/src/gmm/gmm_ms_fsm.c
@@ -75,6 +75,7 @@
struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv;
memset(&ctx->attach, 0, sizeof(ctx->attach));
+ gprs_gmm_gmme_t3312_stop(ctx->gmme);
}
static void st_gmm_ms_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data)
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-gprs/+/32910
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: If1ca164b7a6c7f7750e2e2f0812d6fde828ed4a4
Gerrit-Change-Number: 32910
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newchange