pespin has submitted this change. ( 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(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
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)