aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-07-18 18:04:41 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-07-19 19:02:27 +0200
commit70c6407f69e1df8a80db0a621dad5cfb38015003 (patch)
treec03f989fde5fb9f9f85d021622569b181bac8b4a
parenta8f90e5bc10a636f35790ac9ab98eae0680312c8 (diff)
gmm: Introduce GMMSM-Modify.ind primitive
TS 24.007 and TS 24.008 seem to lack providing an explicit way to pass information between GMM and SM (GMMSM interface) when a RAU process happens in GMM (rx RAU Accept). This lack of primitive can easily be spotted by looking at TS 24.007 Appending C.15, or even better, at the 3rd page of "C.16(cont’d)" around the "STOP Trams" timer, where the info is magically available in SM when being received at GMM. Change-Id: I81e207d44d88f18f0ee13fb413827606a6f830bc
-rw-r--r--include/osmocom/gprs/gmm/gmm_prim.h14
-rw-r--r--include/osmocom/gprs/gmm/gmm_private.h4
-rw-r--r--src/gmm/gmm.c42
-rw-r--r--src/gmm/gmm_prim.c11
-rw-r--r--tests/gmm/gmm_prim_test.c34
-rw-r--r--tests/gmm/gmm_prim_test.err16
-rw-r--r--tests/gmm/gmm_prim_test.ok13
7 files changed, 126 insertions, 8 deletions
diff --git a/include/osmocom/gprs/gmm/gmm_prim.h b/include/osmocom/gprs/gmm/gmm_prim.h
index b774ef8..e066a15 100644
--- a/include/osmocom/gprs/gmm/gmm_prim.h
+++ b/include/osmocom/gprs/gmm/gmm_prim.h
@@ -203,6 +203,7 @@ enum osmo_gprs_gmm_gmmsm_prim_type {
OSMO_GPRS_GMM_GMMSM_ESTABLISH, /* Req, Cnf/Rej */
OSMO_GPRS_GMM_GMMSM_RELEASE, /* Ind */
OSMO_GPRS_GMM_GMMSM_UNITDATA, /* Req, Ind */
+ OSMO_GPRS_GMM_GMMSM_MODIFY, /* Ind, osmocom extension */
};
extern const struct value_string osmo_gprs_gmm_gmmsm_prim_type_names[];
static inline const char *osmo_gprs_gmm_gmmsm_prim_type_name(enum osmo_gprs_gmm_gmmsm_prim_type val)
@@ -257,6 +258,19 @@ struct osmo_gprs_gmm_gmmsm_prim {
uint8_t *smpdu;
uint16_t smpdu_len;
} unitdata_ind;
+ /* OSMO_GPRS_GMM_GMMSM_MODIFY | Ind */
+ struct {
+ /* PLMNs MT-caps, attach-type. */
+ uint32_t allocated_ptmsi;
+ uint32_t allocated_ptmsi_sig;
+ uint32_t allocated_tlli;
+ struct gprs_ra_id rai;
+ bool pdp_ctx_status_present;
+ uint8_t pdp_ctx_status[2]; /* bitmask TS 24.008 10.5.7.1 */
+ bool rx_npdu_numbers_list_present;
+ uint8_t rx_npdu_numbers_list[17]; /* TS 24.008 10.5.5.11 */
+ uint8_t rx_npdu_numbers_list_len; /* bitmask TS 24.008 10.5.5.11 */
+ } modify_ind;
};
};
diff --git a/include/osmocom/gprs/gmm/gmm_private.h b/include/osmocom/gprs/gmm/gmm_private.h
index 46795c8..2abd583 100644
--- a/include/osmocom/gprs/gmm/gmm_private.h
+++ b/include/osmocom/gprs/gmm/gmm_private.h
@@ -66,6 +66,7 @@ struct gprs_gmm_entity {
uint8_t radio_prio; /* TS 24.008 10.5.7.2 */
struct gprs_ra_id ra; /* TS 24.008 10.5.5.15 (decoded) */
+ bool pdp_ctx_status_present;
uint8_t pdp_ctx_status[2]; /* TS 24.008 10.5.7.1 */
bool rx_npdu_numbers_list_present;
uint8_t rx_npdu_numbers_list[17]; /* TS 24.008 10.5.5.11 */
@@ -111,7 +112,7 @@ struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmrr_assign_req(uint32_t old_tll
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_establish_cnf(uint32_t id, uint8_t cause);
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_release_ind(uint32_t id);
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_unitdata_ind(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len);
-
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_modify_ind(uint32_t id);
/* gmm.c: */
struct gprs_gmm_entity *gprs_gmm_gmme_alloc(uint32_t ptmsi, const char *imsi);
void gprs_gmm_gmme_free(struct gprs_gmm_entity *gmme);
@@ -142,6 +143,7 @@ int gprs_gmm_tx_auth_ciph_fail(struct gprs_gmm_entity *gmme, enum gsm48_gmm_caus
int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause);
int gprs_gmm_submit_gmmsm_establish_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause);
int gprs_gmm_submit_gmmsm_release_ind(struct gprs_gmm_entity *gmme);
+int gprs_gmm_submit_gmmsm_modify_ind(struct gprs_gmm_entity *gmme);
int gprs_gmm_submit_llgmm_assing_req(const struct gprs_gmm_entity *gmme);
/* misc.c */
diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c
index 6eaf461..e3afc18 100644
--- a/src/gmm/gmm.c
+++ b/src/gmm/gmm.c
@@ -498,6 +498,30 @@ int gprs_gmm_submit_gmmsm_release_ind(struct gprs_gmm_entity *gmme)
return rc;
}
+/* Osmocom specific, see missing primitive in TS 24.007 Annex C.16 around "STOP
+ * Trams". It is used to propagate TLLI update to SM (and then to SNDCP). */
+int gprs_gmm_submit_gmmsm_modify_ind(struct gprs_gmm_entity *gmme)
+{
+ struct osmo_gprs_gmm_prim *gmm_prim;
+ int rc;
+
+ gmm_prim = gprs_gmm_prim_alloc_gmmsm_modify_ind(gmme->sess_id);
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi = gmme->ptmsi;
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi_sig = gmme->ptmsi_sig;
+ gmm_prim->gmmsm.modify_ind.allocated_tlli = gmme->tlli;
+ memcpy(&gmm_prim->gmmsm.modify_ind.rai, &gmme->ra, sizeof(gmme->ra));
+ gmm_prim->gmmsm.modify_ind.pdp_ctx_status_present = gmme->pdp_ctx_status_present;
+ if (gmm_prim->gmmsm.modify_ind.pdp_ctx_status_present)
+ memcpy(&gmm_prim->gmmsm.modify_ind.pdp_ctx_status, &gmme->pdp_ctx_status, sizeof(gmme->pdp_ctx_status));
+ gmm_prim->gmmsm.modify_ind.rx_npdu_numbers_list_present = gmme->rx_npdu_numbers_list_present;
+ gmm_prim->gmmsm.modify_ind.rx_npdu_numbers_list_len = gmme->rx_npdu_numbers_list_len;
+ if (gmme->rx_npdu_numbers_list_len > 0)
+ memcpy(&gmm_prim->gmmsm.modify_ind.rx_npdu_numbers_list, &gmme->rx_npdu_numbers_list, gmme->rx_npdu_numbers_list_len);
+
+ rc = gprs_gmm_prim_call_up_cb(gmm_prim);
+ return rc;
+}
+
static int gprs_gmm_submit_gmmrr_assing_req(struct gprs_gmm_entity *gmme)
{
struct osmo_gprs_gmm_prim *gmm_prim_tx;
@@ -1121,22 +1145,32 @@ static int gprs_gmm_rx_rau_acc(struct gprs_gmm_entity *gmme, struct gsm48_hdr *g
/* 10.5.1.13 Equivalent PLMNs: TODO */
/* 10.5.7.1 PDP context status: TODO */
- if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_PDP_CTX_STATUS, 2))
+ if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_PDP_CTX_STATUS, 2)) {
memcpy(gmme->pdp_ctx_status, TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS), 2);
-
+ gmme->pdp_ctx_status_present = true;
+ } else {
+ gmme->pdp_ctx_status_present = false;
+ }
/* TODO: lots more Optional IEs */
}
- /* Submit LLGMM-ASSIGN-REQ as per TS 24.007 Annex C.1 */
+ /* Submit LLGMM-ASSIGN-REQ as per TS 24.007 Annex C.15 */
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 */
+ /* Submit GMMRR-ASSIGN-REQ as per TS 24.007 Annex C.15 */
rc = gprs_gmm_submit_gmmrr_assing_req(gmme);
if (rc < 0)
goto rejected;
+ /* Submit GMMSM-MODIFY-REQ, see missing primitive in TS 24.007 Annex C.16 around "STOP Trams" */
+ if (gmme->sess_id != GPRS_GMM_SESS_ID_UNASSIGNED) {
+ rc = gprs_gmm_submit_gmmsm_modify_ind(gmme);
+ if (rc < 0)
+ goto rejected;
+ }
+
rc = gprs_gmm_tx_rau_compl(gmme);
if (rc < 0)
goto rejected;
diff --git a/src/gmm/gmm_prim.c b/src/gmm/gmm_prim.c
index 5a35ef2..3beaea8 100644
--- a/src/gmm/gmm_prim.c
+++ b/src/gmm/gmm_prim.c
@@ -64,6 +64,7 @@ const struct value_string osmo_gprs_gmm_gmmsm_prim_type_names[] = {
{ OSMO_GPRS_GMM_GMMSM_ESTABLISH, "ESTABLISH" },
{ OSMO_GPRS_GMM_GMMSM_RELEASE, "RELEASE" },
{ OSMO_GPRS_GMM_GMMSM_UNITDATA, "UNITDATA" },
+ { OSMO_GPRS_GMM_GMMSM_MODIFY, "MODIFY" },
{ 0, NULL }
};
@@ -318,6 +319,16 @@ struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_release_ind(uint32_t id)
return gmm_prim;
}
+/* Osmocom specific, see missing primitive in TS 24.007 Annex C.16 around "STOP
+ * Trams". It is used to propagate TLLI update to SM (and then to SNDCP). */
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_modify_ind(uint32_t id)
+{
+ struct osmo_gprs_gmm_prim *gmm_prim;
+ gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_MODIFY, PRIM_OP_INDICATION, 0);
+ gmm_prim->gmmsm.sess_id = id;
+ return gmm_prim;
+}
+
/* 3GPP TS 24.007 9.5.1.5 GMMSM-UNITDATA-REQ:*/
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len)
{
diff --git a/tests/gmm/gmm_prim_test.c b/tests/gmm/gmm_prim_test.c
index 2297518..c33bddc 100644
--- a/tests/gmm/gmm_prim_test.c
+++ b/tests/gmm/gmm_prim_test.c
@@ -237,10 +237,11 @@ int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_CONFIRM):
if (gmm_prim->gmmreg.attach_cnf.accepted) {
- printf("%s(): Rx %s accepted=%u allocated_ptmsi=0x%08x allocated_ptmsi_sig=0x%06x\n", __func__, pdu_name,
+ printf("%s(): Rx %s accepted=%u allocated_ptmsi=0x%08x allocated_ptmsi_sig=0x%06x allocated_tlli=0x%08x\n", __func__, pdu_name,
gmm_prim->gmmreg.attach_cnf.accepted,
gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi,
- gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi_sig);
+ gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi_sig,
+ gmm_prim->gmmreg.attach_cnf.acc.allocated_tlli);
} else {
printf("%s(): Rx %s accepted=%u rej_cause=%u\n", __func__, pdu_name,
gmm_prim->gmmreg.attach_cnf.accepted,
@@ -298,6 +299,13 @@ int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
printf("%s(): Rx %s sess_id=%u\n", __func__, pdu_name,
gmm_prim->gmmsm.sess_id);
break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_MODIFY, PRIM_OP_INDICATION):
+ printf("%s(): Rx %s sess_id=%u allocated_ptmsi=0x%08x allocated_ptmsi_sig=0x%06x allocated_tlli=0x%08x\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi,
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi_sig,
+ gmm_prim->gmmsm.modify_ind.allocated_tlli);
+ break;
default:
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
OSMO_ASSERT(0)
@@ -510,6 +518,7 @@ static void test_gmm_prim_ms_gmmsm(void)
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";
@@ -576,6 +585,27 @@ static void test_gmm_prim_ms_gmmsm(void)
OSMO_ASSERT(rc == 0);
/* As a result, GMM submits GMMSM-UNITDATA.ind */
+ /* Wait for READY timer to expire: */
+ clock_override_add(44, 0); /* 44: See GMM Attach Accept (pdu_gmm_att_acc) fed above */
+ clock_debug("Expect T3314 (READY) timeout");
+ osmo_select_main(0);
+
+ clock_override_add(10*60, 0); /* 10*60: See GMM Attach Accept (pdu_gmm_att_acc) fed 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(rand_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 = 0xec999002;
+ tlli = gprs_tmsi2tlli(ptmsi, TLLI_LOCAL);
+ (void)tlli;
+ /* As a result, GMM submits GMMSM-MODIFY.ind */
+ /* As a result, MS answers GMM RAU Complete */
+
/* DEACT: TODO */
printf("==== %s() [end] ====\n", __func__);
diff --git a/tests/gmm/gmm_prim_test.err b/tests/gmm/gmm_prim_test.err
index fa670cf..fa2d2a6 100644
--- a/tests/gmm/gmm_prim_test.err
+++ b/tests/gmm/gmm_prim_test.err
@@ -82,3 +82,19 @@ 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
+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) T3316 (Delete stored RAND & SRES timer) expired
+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
diff --git a/tests/gmm/gmm_prim_test.ok b/tests/gmm/gmm_prim_test.ok
index 6cf672a..62c58e3 100644
--- a/tests/gmm/gmm_prim_test.ok
+++ b/tests/gmm/gmm_prim_test.ok
@@ -8,7 +8,7 @@ test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x80001234 SAPI=GMM l3=
test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request old_TLLI=0x80001234 new_TLLI=0xea711b41
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_up_cb(): Rx GMMREG-ATTACH.confirm accepted=1 allocated_ptmsi=0xea711b41 allocated_ptmsi_sig=0xffffffff allocated_tlli=0xea711b41
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
@@ -37,4 +37,15 @@ test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=
test_gmm_prim_up_cb(): Rx GMMSM-ESTABLISH.confirm sess_id=1234 accepted
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[0a 28 29 30 ]
test_gmm_prim_up_cb(): Rx GMMSM-UNITDATA.indication sess_id=1234 sm_pdu=0a 28 29 30
+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_up_cb(): Rx GMMSM-MODIFY.indication sess_id=1234 allocated_ptmsi=0xec999002 allocated_ptmsi_sig=0xffffffff allocated_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_ms_gmmsm() [end] ====