pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32925 )
Change subject: gmm: Implement periodic RAU procedure ......................................................................
gmm: Implement periodic RAU procedure
Related: OS#5501 Change-Id: Ie7cba8a2fe3b97bebc558c957cc1bcbe3cc81dbc --- M include/osmocom/gprs/gmm/gmm_ms_fsm.h M include/osmocom/gprs/gmm/gmm_pdu.h M include/osmocom/gprs/gmm/gmm_private.h M src/gmm/gmm.c M src/gmm/gmm_ms_fsm.c M src/gmm/gmm_pdu.c M tests/gmm/Makefile.am M tests/gmm/gmm_prim_test.c M tests/gmm/gmm_prim_test.err M tests/gmm/gmm_prim_test.ok 10 files changed, 571 insertions(+), 15 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/gmm/gmm_ms_fsm.h b/include/osmocom/gprs/gmm/gmm_ms_fsm.h index 078c535..1ebc53c 100644 --- a/include/osmocom/gprs/gmm/gmm_ms_fsm.h +++ b/include/osmocom/gprs/gmm/gmm_ms_fsm.h @@ -5,6 +5,20 @@
struct gprs_gmm_entity;
+/* Update type 10.5.5.18 */ +enum gprs_gmm_upd_type { + GPRS_GMM_UPD_TYPE_RA = 0, + GPRS_GMM_UPD_TYPE_COMBINED_RA_LA = 1, + GPRS_GMM_UPD_TYPE_COMBINED_RA_LA_IMSI = 2, + GPRS_GMM_UPD_TYPE_PERIODIC = 3, + /* others: reserved */ +}; +extern const struct value_string gprs_gmm_upd_type_names[]; +static inline const char *gprs_gmm_upd_type_name(enum gprs_gmm_upd_type val) +{ + return get_value_string(gprs_gmm_upd_type_names, val); +} + /* 3GPP TS 24.008 § 4.1.3.1 GMM states in the MS */ enum gprs_gmm_ms_fsm_states { GPRS_GMM_MS_ST_NULL, /* 4.1.3.1.1.1 */ @@ -58,12 +72,20 @@ enum osmo_gprs_gmm_detach_poweroff_type poweroff_type; };
+/* Info about last initiated RAU: */ +struct gprs_gmm_ms_fsm_rau_ctx { + enum gprs_gmm_upd_type type; + /* Retransmission of RAU REQUEST (4.7.5.1.5) */ + uint8_t req_attempts; +}; + struct gprs_gmm_ms_fsm_ctx { struct osmo_fsm_inst *fi; struct gprs_gmm_entity *gmme;
struct gprs_gmm_ms_fsm_attach_ctx attach; struct gprs_gmm_ms_fsm_detach_ctx detach; + struct gprs_gmm_ms_fsm_rau_ctx rau; };
int gprs_gmm_ms_fsm_init(void); @@ -81,3 +103,5 @@ enum osmo_gprs_gmm_detach_ms_type detach_type, enum osmo_gprs_gmm_detach_poweroff_type poweroff_type);
+int gprs_gmm_ms_fsm_ctx_request_rau(struct gprs_gmm_ms_fsm_ctx *ctx, + enum gprs_gmm_upd_type rau_type); diff --git a/include/osmocom/gprs/gmm/gmm_pdu.h b/include/osmocom/gprs/gmm/gmm_pdu.h index 323b2c7..a0a840f 100644 --- a/include/osmocom/gprs/gmm/gmm_pdu.h +++ b/include/osmocom/gprs/gmm/gmm_pdu.h @@ -5,6 +5,7 @@ #include <osmocom/gsm/tlv.h>
struct gprs_gmm_entity; +enum gprs_gmm_upd_type;
#define GPRS_GMM_ALLOC_SIZE 2048 #define GPRS_GMM_ALLOC_HEADROOM 256 @@ -36,3 +37,9 @@ enum osmo_gprs_gmm_detach_ms_type detach_type, enum osmo_gprs_gmm_detach_poweroff_type poweroff_type, struct msgb *msg); + +int gprs_gmm_build_rau_req(struct gprs_gmm_entity *gmme, + enum gprs_gmm_upd_type rau_type, + struct msgb *msg); + +int gprs_gmm_build_rau_compl(struct gprs_gmm_entity *gmme, struct msgb *msg); diff --git a/include/osmocom/gprs/gmm/gmm_private.h b/include/osmocom/gprs/gmm/gmm_private.h index daa967f..d93f724 100644 --- a/include/osmocom/gprs/gmm/gmm_private.h +++ b/include/osmocom/gprs/gmm/gmm_private.h @@ -126,6 +126,7 @@ int gprs_gmm_tx_detach_req(struct gprs_gmm_entity *gmme, enum osmo_gprs_gmm_detach_ms_type detach_type, enum osmo_gprs_gmm_detach_poweroff_type poweroff_type); +int gprs_gmm_tx_rau_req(struct gprs_gmm_entity *gmme, enum gprs_gmm_upd_type rau_type); int gprs_gmm_tx_ciph_auth_resp(const struct gprs_gmm_entity *gmme, const uint8_t *sres);
int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause); diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c index 6184a01..38ebc98 100644 --- a/src/gmm/gmm.c +++ b/src/gmm/gmm.c @@ -78,6 +78,14 @@ { 0 } /* empty item at the end */ };
+const struct value_string gprs_gmm_upd_type_names[] = { + { GPRS_GMM_UPD_TYPE_RA, "RA updating" }, + { GPRS_GMM_UPD_TYPE_COMBINED_RA_LA, "Combined RA/LA updating" }, + { GPRS_GMM_UPD_TYPE_COMBINED_RA_LA_IMSI, "Combined RA/LA updating with IMSI attac" }, + { GPRS_GMM_UPD_TYPE_PERIODIC, "Periodic updating" }, + { 0, NULL } +}; + static void t3314_ready_timer_cb(void *data); static void t3312_periodic_rau_timer_cb(void *data);
@@ -296,7 +304,7 @@ { if (gmme->t3314_assigned_sec == 0) return; - LOGGMME(gmme, LOGL_INFO, "READY timer started\n"); + LOGGMME(gmme, LOGL_INFO, "READY timer started (expires in %lu seconds)\n", gmme->t3314_assigned_sec); osmo_timer_schedule(&gmme->t3314, gmme->t3314_assigned_sec, 0);
/* "Timer T3312 is stopped and shall be set to its initial value @@ -341,14 +349,11 @@ /* 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) + if (gmme->t3312_assigned_sec == 0) return;
- LOGGMME(gmme, LOGL_INFO, "T3312 started\n"); - osmo_timer_schedule(&gmme->t3312, t3312_sec, 0); + LOGGMME(gmme, LOGL_INFO, "T3312 started (expires in %lu seconds)\n", gmme->t3312_assigned_sec); + osmo_timer_schedule(&gmme->t3312, gmme->t3312_assigned_sec, 0); }
/* T3312 (Periodic RAU) is stopped: */ @@ -380,6 +385,8 @@ * routing area updating procedure when it returns to state * GMM-REGISTERED.NORMAL-SERVICE." */ + gprs_gmm_ms_fsm_ctx_request_rau(&gmme->ms_fsm, GPRS_GMM_UPD_TYPE_PERIODIC); + }
int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause) @@ -641,6 +648,71 @@ return rc; }
+/* Tx GMM Routing area update request, 9.4.14 */ +int gprs_gmm_tx_rau_req(struct gprs_gmm_entity *gmme, + enum gprs_gmm_upd_type rau_type) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM RAU REQUEST\n"); + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->tlli, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_rau_req(gmme, rau_type, msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params.*; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + + return rc; +} + +/* Tx GMM Routing area update complete, 9.4.16 */ +static int gprs_gmm_tx_rau_compl(struct gprs_gmm_entity *gmme) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM RAU COMPL\n"); + + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->tlli, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_rau_compl(gmme, msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params.*; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + if (rc < 0) + return rc; + return rc; +} + static int gprs_gmm_rx_att_ack(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) { struct gsm48_attach_ack *aa; @@ -815,6 +887,130 @@ return -EINVAL; /* TODO: what to do on error? */ }
+/* Rx Routing area update accept, 9.4.15 */ +static int gprs_gmm_rx_rau_acc(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + struct gsm48_ra_upd_ack *raack; + struct tlv_parsed tp; + int rc; + int periodic_rau_sec; + + if (len < sizeof(*gh) + sizeof(*raack)) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM RAU ACCEPT with wrong size %u\n", len); + goto rejected; + } + + raack = (struct gsm48_ra_upd_ack *)&gh->data[0]; + LOGGMME(gmme, LOGL_INFO, "Rx GMM RAU ACCEPT upd_result=0x%02x\n", raack->upd_result); + + /* TODO: check raack->upd_result */ + + periodic_rau_sec = gprs_gmm_gprs_tmr_to_secs(raack->ra_upd_timer); + 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 *)&raack->ra_id); + + if (len > sizeof(*gh) + sizeof(*raack)) { + rc = gprs_gmm_tlv_parse(&tp, &raack->data[0], + len - (sizeof(*gh) + sizeof(*raack))); + if (rc < 0) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM RAU ACCEPT: failed to parse TLVs %d\n", rc); + goto rejected; + } + + /* 10.5.5.8 P-TMSI signature */ + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PTMSI_SIG)) { + const uint8_t *ptmsi_sig = TLVP_VAL(&tp, GSM48_IE_GMM_PTMSI_SIG); + gmme->ptmsi_sig = (ptmsi_sig[0] << 8) | (ptmsi_sig[1] << 4) | ptmsi_sig[2]; + } else { + gmme->ptmsi_sig = GSM_RESERVED_TMSI; + } + + /* 10.5.1.4 Allocated P-TMSI */ + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) { + struct osmo_mobile_identity mi; + if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&tp, GSM48_IE_GMM_ALLOC_PTMSI), + TLVP_LEN(&tp, GSM48_IE_GMM_ALLOC_PTMSI), false) + || mi.type != GSM_MI_TYPE_TMSI) { + LOGGMME(gmme, LOGL_ERROR, "Cannot decode P-TMSI\n"); + goto rejected; + } + gmme->old_ptmsi = gmme->ptmsi; + gmme->ptmsi = mi.tmsi; + /* TS 24.008 4.7.1.4.1:"Upon receipt of the assigned P-TMSI, the MS + * shall derive the local TLLI from this P-TMSI and shall use it for + * addressing at lower layers": */ + gmme->old_tlli = gmme->tlli; + gmme->tlli = gprs_tmsi2tlli(gmme->ptmsi, TLLI_LOCAL); + } + /* FIXME! what to do it PTMSI changes? probably need to update other layers... Check GPRS ATTACH ACCEPT func */ + + /* 10.5.1.4 MS identity */ + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV)) { + struct osmo_mobile_identity mi; + if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&tp, GSM48_IE_GMM_IMEISV), + TLVP_LEN(&tp, GSM48_IE_GMM_IMEISV), false) + || mi.type != GSM_MI_TYPE_IMEISV) { + LOGGMME(gmme, LOGL_ERROR, "Cannot decode IMEISV\n"); + goto rejected; + } + /* TODO: */ + } + + /* 10.5.5.11 List of Receive N-PDU Numbers: TODO */ + + /* 10.5.7.3 Negotiated READY timer value */ + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_TIMER_READY)) { + int secs = gprs_gmm_gprs_tmr_to_secs(*TLVP_VAL(&tp, GSM48_IE_GMM_TIMER_READY)); + gmme->t3314_assigned_sec = secs >= 0 ? secs : 0; + } else { + /* Apply the requested value: */ + 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) { + 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); + } + + /* 10.5.5.14 GMM cause: TODO */ + + /* 10.5.7.4 T3302 value */ + if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_TIMER_T3302, 1)) + gmme->t3302 = *TLVP_VAL(&tp, GSM48_IE_GMM_TIMER_T3302); + + /* 10.5.1.13 Equivalent PLMNs: TODO */ + /* 10.5.7.1 PDP context status: TODO */ + + /* TODO: lots more Optional IEs */ + } + + /* Submit LLGMM-ASSIGN-REQ as per TS 24.007 Annex C.1 */ + rc = gprs_gmm_submit_llgmm_assing_req(gmme); + if (rc < 0) + goto rejected; + + /* Submit GMMRR-ASSIGN-REQ as per TS 24.007 Annex C.1 */ + rc = gprs_gmm_submit_gmmrr_assing_req(gmme); + if (rc < 0) + goto rejected; + + rc = gprs_gmm_tx_rau_compl(gmme); + if (rc < 0) + goto rejected; + + rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_RAU_ACCEPTED, NULL); + + return rc; + +rejected: + return -EINVAL; /* TODO: what to do on error? */ +} + /* Rx GMM Identity Request, 9.2.10 */ static int gprs_gmm_rx_id_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) { @@ -916,6 +1112,9 @@ case GSM48_MT_GMM_DETACH_ACK: rc = gprs_gmm_rx_detach_accept(gmme, gh, len); break; + case GSM48_MT_GMM_RA_UPD_ACK: + rc = gprs_gmm_rx_rau_acc(gmme, gh, len); + break; case GSM48_MT_GMM_ID_REQ: rc = gprs_gmm_rx_id_req(gmme, gh, len); break; diff --git a/src/gmm/gmm_ms_fsm.c b/src/gmm/gmm_ms_fsm.c index 889d82a..a6714ff 100644 --- a/src/gmm/gmm_ms_fsm.c +++ b/src/gmm/gmm_ms_fsm.c @@ -35,7 +35,7 @@ [GPRS_GMM_MS_ST_REGISTERED_INITIATED] = { .T = 3310 }, [GPRS_GMM_MS_ST_REGISTERED] = {}, [GPRS_GMM_MS_ST_DEREGISTERED_INITIATED] = {}, - [GPRS_GMM_MS_ST_RAU_INITIATED] = {}, + [GPRS_GMM_MS_ST_RAU_INITIATED] = { .T = 3330 }, [GPRS_GMM_MS_ST_SR_INITIATED] = {},
}; @@ -59,6 +59,19 @@ ctx->attach.with_imsi); }
+static int reinit_rau_proc(struct gprs_gmm_ms_fsm_ctx *ctx) +{ + unsigned long val_sec; + + OSMO_ASSERT(ctx->fi->state == GPRS_GMM_MS_ST_RAU_INITIATED); + + /* Rearm T3330 */ + OSMO_ASSERT(ctx->fi->T == 3330); + val_sec = osmo_tdef_get(g_gmm_ctx->T_defs, ctx->fi->T, OSMO_TDEF_S, -1); + osmo_timer_schedule(&ctx->fi->timer, val_sec, 0); + return gprs_gmm_tx_rau_req(ctx->gmme, ctx->rau.type); +} + static void st_gmm_ms_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { @@ -168,11 +181,24 @@
static void st_gmm_ms_registered(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv; + struct osmo_gprs_llc_prim *llc_prim_tx; + int rc; + switch (event) { case GPRS_GMM_MS_EV_SR_REQUESTED: gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); break; case GPRS_GMM_MS_EV_RAU_REQUESTED: + /* TS 24.007 C.15: submit LLGMM-SUSPEND-REQ */ + llc_prim_tx = osmo_gprs_llc_prim_alloc_llgm_suspend_req(ctx->gmme->tlli); + OSMO_ASSERT(llc_prim_tx); + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim_tx); + /* Transmit RAU Requested to SGSN: */ + rc = gprs_gmm_tx_rau_req(ctx->gmme, + ctx->rau.type); + if (rc < 0) + return; gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_RAU_INITIATED); break; case GPRS_GMM_MS_EV_DETACH_REQUESTED: @@ -200,6 +226,9 @@
static void st_gmm_ms_rau_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv; + struct osmo_gprs_llc_prim *llc_prim_tx; + switch (event) { case GPRS_GMM_MS_EV_RAU_REJECTED: // causes #13, #15, #25 @@ -208,6 +237,10 @@ //mm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED_INITIATED); break; case GPRS_GMM_MS_EV_RAU_ACCEPTED: + /* TS 24.007 C.15: submit LLGM-RESUME-REQ */ + llc_prim_tx = osmo_gprs_llc_prim_alloc_llgm_resume_req(ctx->gmme->tlli); + OSMO_ASSERT(llc_prim_tx); + gprs_gmm_prim_call_llc_down_cb(llc_prim_tx); gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); break; default: @@ -347,7 +380,7 @@
switch (fi->T) { case 3310: - /* TS 23.008 clause 4.7.3.1.5 c) */ + /* TS 24.008 clause 4.7.3.1.5 c) */ ctx->attach.req_attempts++; LOGPFSML(ctx->fi, LOGL_INFO, "T3310 timeout attempts=%u\n", ctx->attach.req_attempts); OSMO_ASSERT(fi->state == GPRS_GMM_MS_ST_REGISTERED_INITIATED); @@ -360,6 +393,20 @@ } reinit_attach_proc(ctx); break; + case 3330: + /* TS 24.008 clause 4.7.5.1.5 c) */ + ctx->rau.req_attempts++; + LOGPFSML(ctx->fi, LOGL_INFO, "T3330 timeout attempts=%u\n", ctx->rau.req_attempts); + OSMO_ASSERT(fi->state == GPRS_GMM_MS_ST_RAU_INITIATED); + if (ctx->rau.req_attempts == 4) { + /* "On the fifth expiry of timer T3330, the MS shall + * abort the GPRS attach procedure" */ + LOGPFSML(ctx->fi, LOGL_NOTICE, "GPRS RAU procedure failure (T3330 timeout attempts=%u)\n", ctx->rau.req_attempts); + osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_LOW_LVL_FAIL, NULL); + return 0; + } + reinit_rau_proc(ctx); + break; default: OSMO_ASSERT(0); } @@ -449,3 +496,14 @@ rc = gprs_gmm_tx_detach_req(ctx->gmme, detach_type, poweroff_type); return rc; } + +int gprs_gmm_ms_fsm_ctx_request_rau(struct gprs_gmm_ms_fsm_ctx *ctx, + enum gprs_gmm_upd_type rau_type) +{ + int rc = 0; + + ctx->rau.type = rau_type; + rc = osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_RAU_REQUESTED, NULL); + + return rc; +} diff --git a/src/gmm/gmm_pdu.c b/src/gmm/gmm_pdu.c index c6c8118..ae0baef 100644 --- a/src/gmm/gmm_pdu.c +++ b/src/gmm/gmm_pdu.c @@ -151,6 +151,26 @@ }, };
+static int encode_ms_net_cap(struct gprs_gmm_entity *gmme, struct msgb *msg) +{ + int rc; + uint8_t *l; /* len */ + struct bitvec bv = { + .data = msg->tail, + .data_len = GSM_MACBLOCK_LEN, + }; + + msgb_put_u8(msg, GSM48_IE_GMM_MS_NET_CAPA); + + l = msgb_put(msg, 1); /* len */ + + /* TODO: we hardcode a MS Net Cap for now. We may want to pass it from the app at some point: */ + rc = bitvec_unhex(&bv, "e5e0"); + *l = OSMO_BYTES_FOR_BITS(bv.cur_bit); + msgb_put(msg, *l); + return rc; +} + static int encode_ms_ra_acc_cap(struct gprs_gmm_entity *gmme, struct msgb *msg) { int rc; @@ -264,6 +284,68 @@ return 0; }
+/* Chapter 9.4.14: Routing area update request */ +int gprs_gmm_build_rau_req(struct gprs_gmm_entity *gmme, + enum gprs_gmm_upd_type rau_type, + struct msgb *msg) +{ + struct gsm48_hdr *gh; + uint8_t byte, cksn; + int rc; + struct gsm48_ra_id *raid_enc; + unsigned long t3314_sec; + uint8_t ptmsi_type_native = 1; /* Table 10.5.5.29.1 */ + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_RA_UPD_REQ; + + /* 10.5.5.18 Update type */ + cksn = gmme->auth_ciph.req.key_seq; + byte = (cksn << 4) | (((uint8_t)rau_type) & 0x07); + msgb_put_u8(msg, byte); + + /* Old routing area identification 0.5.5.15 */ + raid_enc = (struct gsm48_ra_id *)msgb_put(msg, sizeof(struct gsm48_ra_id)); + gsm48_encode_ra(raid_enc, &gmme->ra); + + /* MS Radio Access capability 10.5.5.12a */ + rc = encode_ms_ra_acc_cap(gmme, msg); + if (rc < 0) + return -EINVAL; + + /* 10.5.5.8 Old P-TMSI signature: */ + if (gmme->ptmsi_sig != GSM_RESERVED_TMSI) { + uint8_t ptmsi_sig[3] = { gmme->ptmsi_sig >> 16, gmme->ptmsi_sig >> 8, gmme->ptmsi_sig }; + msgb_tv_fixed_put(msg, GSM48_IE_GMM_PTMSI_SIG, sizeof(ptmsi_sig), ptmsi_sig); + } + + /* 10.5.7.3 Requested READY timer value */ + t3314_sec = osmo_tdef_get(g_gmm_ctx->T_defs, 3314, OSMO_TDEF_S, -1); + msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY, gprs_gmm_secs_to_gprs_tmr_floor(t3314_sec)); + + /* DRX parameter 10.5.5.6 */ + memcpy(msgb_put(msg, sizeof(drx_param_def)), + &drx_param_def, + sizeof(drx_param_def)); + + /* 9.4.14.6 MS network capability */ + rc = encode_ms_net_cap(gmme, msg); + if (rc < 0) + return -EINVAL; + + /* 9.4.14.7 PDP context status */ + /* TODO: implement. Table 9.4.14/3GPP TS 24.00 states it is optional (O) but 9.4.14.7 states: + * "This IE shall be included by the MS." */ + + /* 9.4.14.17 P-TMSI type */ + /* Table 9.4.14/3GPP TS 24.00 states it is optional (O) but 9.4.14.17 states: + * "This IE shall be included by the MS." */ + msgb_v_put(msg, (GSM48_IE_GMM_PTMSI_TYPE << 4) | (ptmsi_type_native & 0x01)); + + return 0; +} + /* 9.2.11 Identity response */ int gprs_gmm_build_identity_resp(struct gprs_gmm_entity *gmme, uint8_t mi_type, @@ -394,3 +476,15 @@ /* TODO: optional fields: P-TMSI signature 10.5.5.8a */ return 0; } + +int gprs_gmm_build_rau_compl(struct gprs_gmm_entity *gmme, struct msgb *msg) +{ + struct gsm48_hdr *gh; + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_RA_UPD_COMPL; + + /* TODO: Add optional IEs */ + return 0; +} diff --git a/tests/gmm/Makefile.am b/tests/gmm/Makefile.am index d066c5e..83517e5 100644 --- a/tests/gmm/Makefile.am +++ b/tests/gmm/Makefile.am @@ -38,10 +38,13 @@ $(NULL)
# libosmo-gprs-llc.a is used below to access non-exported private symbols used in the test: +# libosmo-gprs-rlcmac.a is used below to access non-exported private symbols used in the test: gmm_prim_test_SOURCES = gmm_prim_test.c gmm_prim_test_LDADD = \ $(top_builddir)/src/gmm/libosmo-gprs-gmm.la \ $(top_builddir)/src/llc/.libs/libosmo-gprs-llc.a \ + $(top_builddir)/src/rlcmac/.libs/libosmo-gprs-rlcmac.a \ + $(top_builddir)/src/csn1/libosmo-csn1.la \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(NULL) diff --git a/tests/gmm/gmm_prim_test.c b/tests/gmm/gmm_prim_test.c index b403829..7eefc73 100644 --- a/tests/gmm/gmm_prim_test.c +++ b/tests/gmm/gmm_prim_test.c @@ -28,7 +28,11 @@ #include <osmocom/core/utils.h> #include <osmocom/core/fsm.h> #include <osmocom/core/msgb.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/timer_compat.h> +#include <osmocom/core/select.h>
+#include <osmocom/gprs/rlcmac/rlcmac_private.h> #include <osmocom/gprs/llc/llc_prim.h> #include <osmocom/gprs/llc/llc_private.h> #include <osmocom/gprs/gmm/gmm.h> @@ -133,6 +137,46 @@ 0xea, 0x71, 0x1b, 0x41 };
+/* +GSM A-I/F DTAP - Routing Area Update Accept + Protocol Discriminator: GPRS mobility management messages (8) + .... 1000 = Protocol discriminator: GPRS mobility management messages (0x8) + 0000 .... = Skip Indicator: No indication of selected PLMN (0) + DTAP GPRS Mobility Management Message Type: Routing Area Update Accept (0x09) + Force to Standby + .... 0... = Spare bit(s): 0 + .... .000 = Force to standby: Force to standby not indicated (0) + Update Result + .000 .... = Update Result: RA updated (0) + GPRS Timer - Periodic RA update timer + GPRS Timer: 10 sec + 000. .... = Unit: value is incremented in multiples of 2 seconds (0) + ...0 0101 = Timer value: 5 + Routing Area Identification - RAI: 234-70-5-0 + Routing area identification: 234-70-5-0 + Mobile Country Code (MCC): United Kingdom (234) + Mobile Network Code (MNC): AMSUK Limited (70) + Location Area Code (LAC): 0x0005 (5) + Routing Area Code (RAC): 0x00 (0) + Mobile Identity - Allocated P-TMSI - TMSI/P-TMSI (0xec999002) + Element ID: 0x18 + Length: 5 + 1111 .... = Unused: 0xf + .... 0... = Odd/even indication: Even number of identity digits + .... .100 = Mobile Identity Type: TMSI/P-TMSI/M-TMSI (4) + TMSI/P-TMSI/M-TMSI/5G-TMSI: 3969486850 (0xec999002) + GPRS Timer - Negotiated Ready Timer + Element ID: 0x17 + GPRS Timer: 10 sec + 000. .... = Unit: value is incremented in multiples of 2 seconds (0) + ...0 0101 = Timer value: 5 +*/ +static uint8_t pdu_gmm_rau_acc[] = { +0x08, 0x09, 0x00, 0x05, 0x32, 0xf4, 0x07, 0x00, +0x05, 0x00, 0x18, 0x05, 0xf4, 0xec, 0x99, 0x90, +0x02, 0x17, 0x05 +}; + static uint8_t pdu_gmm_detach_acc[] = { 0x08, 0x06, 0x00 }; @@ -145,6 +189,42 @@ return 0; }
+#define clock_debug(fmt, args...) \ + do { \ + struct timespec ts; \ + struct timeval tv; \ + osmo_clock_gettime(CLOCK_MONOTONIC, &ts); \ + osmo_gettimeofday(&tv, NULL); \ + fprintf(stdout, "sys={%lu.%06lu}, mono={%lu.%06lu}: " fmt "\n", \ + tv.tv_sec, tv.tv_usec, ts.tv_sec, ts.tv_nsec/1000, ##args); \ + } while (0) + +static void clock_override_enable(bool enable) +{ + osmo_gettimeofday_override = enable; + osmo_clock_override_enable(CLOCK_MONOTONIC, enable); +} + +static void clock_override_set(long sec, long usec) +{ + struct timespec *mono; + osmo_gettimeofday_override_time.tv_sec = sec; + osmo_gettimeofday_override_time.tv_usec = usec; + mono = osmo_clock_override_gettimespec(CLOCK_MONOTONIC); + mono->tv_sec = sec; + mono->tv_nsec = usec*1000; + + clock_debug("clock_override_set"); +} + +static void clock_override_add_debug(long sec, long usec, bool dbg) +{ + osmo_gettimeofday_override_add(sec, usec); + osmo_clock_override_add(CLOCK_MONOTONIC, sec, usec*1000); + if (dbg) + clock_debug("clock_override_add"); +} +#define clock_override_add(sec, usec) clock_override_add_debug(sec, usec, true)
int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data) { @@ -252,6 +332,7 @@ int test_gmm_prim_llc_down_cb(struct osmo_gprs_llc_prim *llc_prim, void *user_data) { const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim); + struct osmo_gprs_gmm_prim *gmm_prim_tx;
switch (llc_prim->oph.sap) { case OSMO_GPRS_LLC_SAP_LLGMM: @@ -269,6 +350,15 @@ printf("%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", __func__, pdu_name, llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LL_UNITDATA, PRIM_OP_REQUEST): + /* Immediately notify GMM that it was transmitted over the air: */ + gmm_prim_tx = (struct osmo_gprs_gmm_prim *)gprs_rlcmac_prim_alloc_gmmrr_llc_transmitted_ind(llc_prim->ll.tlli); + gmm_prim_tx->oph.sap = OSMO_GPRS_GMM_SAP_GMMRR; + gmm_prim_tx->oph.primitive = OSMO_GPRS_GMM_GMMRR_LLC_TRANSMITTED; + osmo_gprs_gmm_prim_lower_up(gmm_prim_tx); + break; + } break; default: printf("%s(): Unexpected Rx %s\n", __func__, pdu_name); @@ -286,12 +376,15 @@ uint32_t ptmsi = 0x00001234; uint32_t ptmsi_sig = 0x556677; uint32_t rand_tlli = 0x80001234; + uint32_t tlli; char *imsi = "1234567890"; char *imei = "42342342342342"; char *imeisv = "4234234234234275";
printf("==== %s() [start] ====\n", __func__);
+ clock_override_set(0, 0); + rc = osmo_gprs_gmm_init(OSMO_GPRS_GMM_LOCATION_MS); OSMO_ASSERT(rc == 0); osmo_gprs_gmm_enable_gprs(true); @@ -338,9 +431,31 @@ OSMO_ASSERT(llc_prim); rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim); OSMO_ASSERT(rc == 0); + /* update the used ptmsi to align with what was assigned from the network: */ + ptmsi = 0xea711b41; + tlli = gprs_tmsi2tlli(ptmsi, TLLI_LOCAL); /* As a result, MS answers GMM Attach Complete */ /* As a result, MS submits GMMREG ATTACH.cnf */
+ /* Wait for READY timer to expire: */ + clock_override_add(44, 0); /* 44: See GMM Attach Accept (pdu_gmm_att_acc) feed above */ + clock_debug("Expect T3314 (READY) timeout"); + osmo_select_main(0); + + clock_override_add(10*60, 0); /* 44: See GMM Attach Accept (pdu_gmm_att_acc) feed above */ + clock_debug("Expect T3312 (periodic RAU) timeout"); + osmo_select_main(0); + + /* Network sends GMM RAU Accept */ + llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_rau_acc, sizeof(pdu_gmm_rau_acc)); + OSMO_ASSERT(llc_prim); + rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim); + OSMO_ASSERT(rc == 0); + /* update the used ptmsi to align with what was assigned from the network: */ + ptmsi = 0xea711b41; + tlli = gprs_tmsi2tlli(ptmsi, TLLI_LOCAL); + /* As a result, MS answers GMM RAU Complete */ + /* ... */
/* DETACH */ @@ -353,7 +468,7 @@ OSMO_ASSERT(rc == 0);
/* Network sends GMM Detach Accept */ - llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(rand_tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_detach_acc, sizeof(pdu_gmm_detach_acc)); + llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_detach_acc, sizeof(pdu_gmm_detach_acc)); OSMO_ASSERT(llc_prim); rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim); OSMO_ASSERT(rc == 0); @@ -379,6 +494,8 @@
printf("==== %s() [start] ====\n", __func__);
+ clock_override_set(0, 0); + rc = osmo_gprs_gmm_init(OSMO_GPRS_GMM_LOCATION_MS); OSMO_ASSERT(rc == 0); osmo_gprs_gmm_enable_gprs(true); @@ -460,6 +577,8 @@ log_set_print_level(osmo_stderr_target, 1); log_set_use_color(osmo_stderr_target, 0);
+ clock_override_enable(true); + test_gmm_prim_ms_gmmreg(); test_gmm_prim_ms_gmmsm();
diff --git a/tests/gmm/gmm_prim_test.err b/tests/gmm/gmm_prim_test.err index 7aca515..6720d69 100644 --- a/tests/gmm/gmm_prim_test.err +++ b/tests/gmm/gmm_prim_test.err @@ -4,28 +4,50 @@ DLGLOBAL INFO GMM_MS{Null}: state_chg to Deregistered DLGLOBAL INFO GMM_MS{Deregistered}: Received Event ATTACH_REQUESTED DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM ATTACH REQUEST (new TLLI=0x80001234) +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO GMM_MS{Deregistered}: state_chg to RegisteredInitiated DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM IDENTITY REQUEST mi_type=IMEI DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM IDENTITY RESPONSE +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM AUTHENTICATION AND CIPHERING REQUEST DLGLOBAL INFO Rx from upper layers: GMMREG-SIM_AUTH.response DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM GMM AUTHENTICATION AND CIPHERING RESPONSE +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM ATTACH ACCEPT DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Tx GMM ATTACH COMPL +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) READY timer started (expires in 44 seconds) DLGLOBAL INFO GMM_MS{RegisteredInitiated}: Received Event ATTACH_ACCEPTED DLGLOBAL INFO GMM_MS{RegisteredInitiated}: state_chg to Registered +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) READY timer expired +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) T3312 started (expires in 600 seconds) +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) T3312 Periodic RAU timer expired +DLGLOBAL INFO GMM_MS{Registered}: Received Event RAU_REQUESTED +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Tx GMM RAU REQUEST +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) READY timer started (expires in 44 seconds) +DLGLOBAL INFO GMM_MS{Registered}: state_chg to RAUInitidated +DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Rx GMM RAU ACCEPT upd_result=0x00 +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ec999002) Tx GMM RAU COMPL +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ec999002) READY timer started (expires in 10 seconds) +DLGLOBAL INFO GMM_MS{RAUInitidated}: Received Event RAU_ACCEPTED +DLGLOBAL INFO GMM_MS{RAUInitidated}: state_chg to Registered DLGLOBAL INFO Rx from upper layers: GMMREG-DETACH.request DLGLOBAL INFO GMM_MS{Registered}: Received Event DETACH_REQUESTED DLGLOBAL INFO GMM_MS{Registered}: state_chg to DeregisteredInitiated -DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Tx GMM DETACH REQUEST (MO) +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ec999002) Tx GMM DETACH REQUEST (MO) +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ec999002) READY timer started (expires in 10 seconds) DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication -DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Rx GMM DETACH ACCEPT (MO) force_standby_indicated=false +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ec999002) Rx GMM DETACH ACCEPT (MO) force_standby_indicated=false DLGLOBAL INFO GMM_MS{DeregisteredInitiated}: Received Event DETACH_ACCEPTED DLGLOBAL INFO GMM_MS{DeregisteredInitiated}: state_chg to Deregistered -DLGLOBAL DEBUG GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ffffffff) free() +DLGLOBAL DEBUG GMME(IMSI-1234567890:PTMSI-ec999002:TLLI-ffffffff) free() DLGLOBAL INFO GMM_MS{Deregistered}: Deallocated DLGLOBAL INFO Rx from upper layers: GMMSM-ESTABLISH.request DLGLOBAL INFO GMM_MS{Null}: Allocated @@ -33,18 +55,25 @@ DLGLOBAL INFO GMM_MS{Null}: state_chg to Deregistered DLGLOBAL INFO GMM_MS{Deregistered}: Received Event ATTACH_REQUESTED DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM ATTACH REQUEST (new TLLI=0x80001234) +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO GMM_MS{Deregistered}: state_chg to RegisteredInitiated DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM IDENTITY REQUEST mi_type=IMEI DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM IDENTITY RESPONSE +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM AUTHENTICATION AND CIPHERING REQUEST DLGLOBAL INFO Rx from upper layers: GMMREG-SIM_AUTH.response DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Tx GMM GMM AUTHENTICATION AND CIPHERING RESPONSE +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-00001234:TLLI-80001234) Rx GMM ATTACH ACCEPT DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) Tx GMM ATTACH COMPL +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) READY timer started (expires in 44 seconds) DLGLOBAL INFO GMM_MS{RegisteredInitiated}: Received Event ATTACH_ACCEPTED DLGLOBAL INFO GMM_MS{RegisteredInitiated}: state_chg to Registered DLGLOBAL INFO Rx from upper layers: GMMSM-UNITDATA.request +DLGLOBAL INFO Rx from lower layers: GMRR-LLC_TRANSMITTED.indication +DLGLOBAL INFO GMME(IMSI-1234567890:PTMSI-ea711b41:TLLI-ea711b41) READY timer started (expires in 44 seconds) DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication diff --git a/tests/gmm/gmm_prim_test.ok b/tests/gmm/gmm_prim_test.ok index 068876b..870d58f 100644 --- a/tests/gmm/gmm_prim_test.ok +++ b/tests/gmm/gmm_prim_test.ok @@ -1,4 +1,5 @@ ==== test_gmm_prim_ms_gmmreg() [start] ==== +sys={0.000000}, mono={0.000000}: clock_override_set test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x80001234 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 12 34 00 f0 00 00 00 00 00 19 55 66 77 17 16 e1 ] test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x80001234 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ] test_gmm_prim_up_cb(): Rx GMMREG-SIM_AUTH.indication ac_ref_nr=2 key_seq=0 rand=e2 a6 f3 f8 bb 9e a7 01 e0 ce 4f 33 64 a9 91 75 @@ -8,11 +9,22 @@ test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request old_tlli=0x80001234 new_tlli=0xea711b41 test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 03 ] test_gmm_prim_up_cb(): Rx GMMREG-ATTACH.confirm accepted=1 allocated_ptmsi=0xea711b41 allocated_ptmsi_sig=0xffffffff -test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 05 20 0a 00 05 f4 ea 71 1b 41 ] -test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request old_TLLI=0xea711b41 new_TLLI=0xffffffff +sys={44.000000}, mono={44.000000}: clock_override_add +sys={44.000000}, mono={44.000000}: Expect T3314 (READY) timeout +sys={644.000000}, mono={644.000000}: clock_override_add +sys={644.000000}, mono={644.000000}: Expect T3312 (periodic RAU) timeout +test_gmm_prim_llc_down_cb(): Rx LLGMM-SUSPEND.request TLLI=0xea711b41 +test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 08 03 32 f4 07 00 05 00 00 17 16 0a 00 e5 02 00 00 e1 ] +test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request old_TLLI=0xea711b41 new_TLLI=0xec999002 +test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request old_tlli=0xea711b41 new_tlli=0xec999002 +test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xec999002 SAPI=GMM l3=[08 0a ] +test_gmm_prim_llc_down_cb(): Rx LLGMM-RESUME.request TLLI=0xec999002 +test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xec999002 SAPI=GMM l3=[08 05 20 0a 00 05 f4 ec 99 90 02 ] +test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request old_TLLI=0xec999002 new_TLLI=0xffffffff test_gmm_prim_up_cb(): Rx GMMREG-DETACH.confirm detach_type='GPRS detach' ==== test_gmm_prim_ms_gmmreg() [end] ==== ==== test_gmm_prim_ms_gmmsm() [start] ==== +sys={0.000000}, mono={0.000000}: clock_override_set test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x80001234 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 12 34 00 f0 00 00 00 00 00 19 55 66 77 17 16 e1 ] test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x80001234 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ] test_gmm_prim_up_cb(): Rx GMMREG-SIM_AUTH.indication ac_ref_nr=2 key_seq=0 rand=e2 a6 f3 f8 bb 9e a7 01 e0 ce 4f 33 64 a9 91 75