gmm: Implement P-TMSI Reallocation Cmd/Compl

Change-Id: I1bf8bf5f4299db7b026fed2e2c21c07f15690942
This commit is contained in:
Pau Espin 2023-05-25 17:31:20 +02:00
parent 9cf485e45b
commit 489499caa9
4 changed files with 146 additions and 14 deletions

View File

@ -25,6 +25,7 @@ int gprs_gmm_build_attach_req(struct gprs_gmm_entity *gmme,
struct msgb *msg);
int gprs_gmm_build_attach_compl(struct gprs_gmm_entity *gmme, struct msgb *msg);
int gprs_gmm_build_ptmsi_realloc_compl(struct gprs_gmm_entity *gmme, struct msgb *msg);
int gprs_gmm_build_identity_resp(struct gprs_gmm_entity *gmme,
uint8_t mi_type,

View File

@ -480,6 +480,17 @@ int gprs_gmm_submit_llgmm_assing_req(const struct gprs_gmm_entity *gmme)
return rc;
}
static void gprs_gmm_gmme_update_allocated_ptmsi(struct gprs_gmm_entity *gmme, uint32_t new_ptmsi)
{
gmme->old_ptmsi = gmme->ptmsi;
gmme->ptmsi = new_ptmsi;
/* 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);
}
/* Tx Identity Response, 9.2.11 */
static int gprs_gmm_tx_id_resp(struct gprs_gmm_entity *gmme,
uint8_t mi_type)
@ -650,6 +661,39 @@ int gprs_gmm_tx_detach_req(struct gprs_gmm_entity *gmme,
return rc;
}
/* Tx GMM Atach Complete, 9.4.3 */
static int gprs_gmm_tx_ptmsi_realloc_compl(struct gprs_gmm_entity *gmme)
{
struct osmo_gprs_llc_prim *llc_prim;
int rc;
struct msgb *msg;
LOGGMME(gmme, LOGL_INFO, "Tx P-TMSI REALLOCATION 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_ptmsi_realloc_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;
}
/* 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)
@ -777,13 +821,7 @@ static int gprs_gmm_rx_att_ack(struct gprs_gmm_entity *gmme, struct gsm48_hdr *g
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);
gprs_gmm_gmme_update_allocated_ptmsi(gmme, mi.tmsi);
}
if (TLVP_PRES_LEN(&tp, GSM48_IE_GMM_TIMER_T3302, 1))
@ -938,13 +976,7 @@ static int gprs_gmm_rx_rau_acc(struct gprs_gmm_entity *gmme, struct gsm48_hdr *g
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);
gprs_gmm_gmme_update_allocated_ptmsi(gmme, mi.tmsi);
}
/* FIXME! what to do it PTMSI changes? probably need to update other layers... Check GPRS ATTACH ACCEPT func */
@ -1034,6 +1066,75 @@ static int gprs_gmm_rx_id_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh
return gprs_gmm_tx_id_resp(gmme, id_type);
}
/* Rx GMM P-TMSI reallocation command, 9.4.7 */
static int gprs_gmm_rx_ptmsi_realloc_cmd(struct gprs_gmm_entity *gmme, const struct gsm48_hdr *gh, unsigned int len)
{
const uint8_t *buf = &gh->data[0];
uint8_t mi_len;
struct osmo_mobile_identity mi;
bool force_standby_indicated;
struct tlv_parsed tp;
int rc;
if (len != 15) {
LOGGMME(gmme, LOGL_ERROR, "Rx GMM P-TMSI REALLOCATION COMMAND with wrong size %u\n", len);
goto rejected;
}
mi_len = *buf;
if (mi_len != 5)
goto rejected;
buf++;
if (osmo_mobile_identity_decode(&mi, buf, mi_len, false) || mi.type != GSM_MI_TYPE_TMSI) {
LOGGMME(gmme, LOGL_ERROR, "Rx GMM P-TMSI REALLOCATION COMMAND: Cannot decode P-TMSI\n");
goto rejected;
}
gprs_gmm_gmme_update_allocated_ptmsi(gmme, mi.tmsi);
buf += mi_len;
gsm48_parse_ra(&gmme->ra, (const uint8_t *)buf);
buf += 6;
force_standby_indicated = (*buf >> 4) == 0x01;
if (force_standby_indicated)
gprs_gmm_gmme_ready_timer_stop(gmme);
buf++;
/* Optional: */
if (len > (buf - (uint8_t *)gh)) {
rc = gprs_gmm_tlv_parse(&tp, buf, len - (buf - (uint8_t *)gh));
if (rc < 0) {
LOGGMME(gmme, LOGL_ERROR, "Rx GMM P-TMSI REALLOCATION COMMAND: 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;
}
/* TODO: 10.5.5.35 DCN-ID */
}
/* 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;
return gprs_gmm_tx_ptmsi_realloc_compl(gmme);
rejected:
return -EINVAL; /* TODO: what to do on error? */
}
/* Rx GMM Authentication and ciphering request, 9.4.9 */
static int gprs_gmm_rx_auth_ciph_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len)
{
@ -1120,6 +1221,9 @@ int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int
case GSM48_MT_GMM_ID_REQ:
rc = gprs_gmm_rx_id_req(gmme, gh, len);
break;
case GSM48_MT_GMM_PTMSI_REALL_CMD:
rc = gprs_gmm_rx_ptmsi_realloc_cmd(gmme, gh, len);
break;
case GSM48_MT_GMM_AUTH_CIPH_REQ:
rc = gprs_gmm_rx_auth_ciph_req(gmme, gh, len);
break;

View File

@ -284,6 +284,17 @@ int gprs_gmm_build_attach_compl(struct gprs_gmm_entity *gmme, struct msgb *msg)
return 0;
}
/* 9.4.8 P-TMSI reallocation complete */
int gprs_gmm_build_ptmsi_realloc_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_PTMSI_REALL_COMPL;
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,

View File

@ -464,6 +464,22 @@ static void test_gmm_prim_ms_gmmreg(void)
rc = osmo_gprs_gmm_prim_lower_up(gmm_prim);
OSMO_ASSERT(rc == 0);
/* ... */
/* Test Network sends P-TMSI Reallocation Cmd */
#if 0
/* TODO: find a pcap with a P-TMSI Reallocation Cmd */
llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_ptmsi_realloc_cmd, sizeof(pdu_gmm_ptmsi_realloc_cmd));
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 P-TMSI Reallocation Complete */
#endif
/* ... */
/* DETACH */