pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32985 )
Change subject: rlcmac: Submit GMMRR-PAGE.ind upon rx of Paging Request Type 1/2 ......................................................................
rlcmac: Submit GMMRR-PAGE.ind upon rx of Paging Request Type 1/2
Change-Id: I64db4277b5c54870a258d63c554f470011bcc989 --- M include/osmocom/gprs/rlcmac/rlcmac_private.h M src/rlcmac/rlcmac.c M src/rlcmac/rlcmac_prim.c 3 files changed, 243 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/85/32985/1
diff --git a/include/osmocom/gprs/rlcmac/rlcmac_private.h b/include/osmocom/gprs/rlcmac/rlcmac_private.h index e73d23e..5b09a4a 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac_private.h +++ b/include/osmocom/gprs/rlcmac/rlcmac_private.h @@ -86,9 +86,13 @@
/* rlcmac.c */ struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli); +struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_ptmsi(uint32_t ptmsi); +struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_imsi(const char *imsi); struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi); struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi); int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia, uint32_t fn); +int gprs_rlcmac_handle_ccch_pag_req_1(struct gsm48_paging1 *pag); +int gprs_rlcmac_handle_ccch_pag_req_2(struct gsm48_paging2 *pag); int gprs_rlcmac_handle_bcch_si13(const struct gsm48_system_information_type_13 *si13); int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim, enum gprs_rlcmac_coding_scheme cs); diff --git a/src/rlcmac/rlcmac.c b/src/rlcmac/rlcmac.c index 00b45ff..1fea6a5 100644 --- a/src/rlcmac/rlcmac.c +++ b/src/rlcmac/rlcmac.c @@ -134,7 +134,6 @@ struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli) { struct gprs_rlcmac_entity *gre; - llist_for_each_entry(gre, &g_rlcmac_ctx->gre_list, entry) { if (gre->tlli == tlli) return gre; @@ -142,6 +141,26 @@ return NULL; }
+struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_ptmsi(uint32_t ptmsi) +{ + struct gprs_rlcmac_entity *gre; + llist_for_each_entry(gre, &g_rlcmac_ctx->gre_list, entry) { + if (gre->ptmsi == ptmsi) + return gre; + } + return NULL; +} + +struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_imsi(const char *imsi) +{ + struct gprs_rlcmac_entity *gre; + llist_for_each_entry(gre, &g_rlcmac_ctx->gre_list, entry) { + if (strncmp(gre->imsi, imsi, ARRAY_SIZE(gre->imsi)) == 0) + return gre; + } + return NULL; +} + struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi) { struct gprs_rlcmac_entity *gre; @@ -304,6 +323,210 @@ return rc; }
+ +/* TS 44.018 3.3.2.1.1: +* It is used when sending paging information to a mobile station in packet idle mode, if PCCCH is not present in the cell. +* If the mobile station in packet idle mode is identified by its IMSI, it shall parse the message for a corresponding Packet +* Page Indication field: +* - if the Packet Page Indication field indicates a packet paging procedure, the mobile station shall proceed as +* specified in sub-clause 3.5.1.2. +* 3.5.1.2 "On receipt of a packet paging request": +* On the receipt of a paging request message, the RR sublayer of addressed mobile station indicates the receipt of a +* paging request to the MM sublayer, see 3GPP TS 24.007. +*/ +/* TS 44.018 9.1.22 "Paging request type 1" */ +int gprs_rlcmac_handle_ccch_pag_req_1(struct gsm48_paging1 *pag) +{ + uint8_t len; + uint8_t *buf = pag->data; + int rc; + struct osmo_mobile_identity mi1 = {}; /* GSM_MI_TYPE_NONE */ + struct osmo_mobile_identity mi2 = {}; /* GSM_MI_TYPE_NONE */ + P1_Rest_Octets_t p1ro = {}; + unsigned p1_rest_oct_len; + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + struct gprs_rlcmac_entity *gre; + + LOGRLCMAC(LOGL_INFO, "Rx Paging Request Type 1\n"); + + if (GSM_MACBLOCK_LEN < sizeof(*pag)) + return -EBADMSG; + + /* The L2 pseudo length of this message is the sum of lengths of all + * information elements present in the message except the P1 Rest Octets and L2 + * Pseudo Length information elements. */ + if (pag->l2_plen == GSM_MACBLOCK_LEN - sizeof(pag->l2_plen)) { + /* no P1 Rest Octets => no Packet Page Indication => Discard */ + return 0; + } + + if (GSM_MACBLOCK_LEN < sizeof(*pag) + 1) + return -EBADMSG; + len = *buf; + buf++; + + if (GSM_MACBLOCK_LEN < sizeof(*pag) + 1 + len) + return -EBADMSG; + + if ((rc = osmo_mobile_identity_decode(&mi1, buf, len, false)) < 0) + return rc; + buf += len; + + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + 1) { + /* No MI2 and no P1 Rest Octets => no Packet Page Indication => Discard */ + return 0; + } + + if (*buf == GSM48_IE_MOBILE_ID) { + buf++; + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + 1) + return -EBADMSG; + len = *buf; + buf++; + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + len) + return -EBADMSG; + if ((rc = osmo_mobile_identity_decode(&mi2, buf, len, false)) < 0) + return rc; + buf += len; + } + + p1_rest_oct_len = GSM_MACBLOCK_LEN - (buf - (uint8_t *)pag); + if (p1_rest_oct_len == 0) { + /*No P1 Rest Octets => no Packet Page Indication => Discard */ + return 0; + } + + rc = osmo_gprs_rlcmac_decode_p1ro(&p1ro, buf, p1_rest_oct_len); + if (rc != 0) { + LOGRLCMAC(LOGL_ERROR, "Failed to parse P1 Rest Octets\n"); + return rc; + } + + if (p1ro.Packet_Page_Indication_1 == 1) { /* for GPRS*/ + switch (mi1.type) { + case GSM_MI_TYPE_IMSI: + if ((gre = gprs_rlcmac_find_entity_by_imsi(mi1.imsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + case GSM_MI_TYPE_TMSI: + if ((gre = gprs_rlcmac_find_entity_by_ptmsi(mi1.tmsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + default: + return -EINVAL; + } + } + + if (p1ro.Packet_Page_Indication_2 == 1) { /* for GPRS*/ + switch (mi2.type) { + case GSM_MI_TYPE_IMSI: + if ((gre = gprs_rlcmac_find_entity_by_imsi(mi2.imsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + case GSM_MI_TYPE_TMSI: + if ((gre = gprs_rlcmac_find_entity_by_ptmsi(mi2.tmsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + default: + return -EINVAL; + } + } + + return rc; +} + +/* TS 44.018 9.1.23 "Paging request type 2" */ +int gprs_rlcmac_handle_ccch_pag_req_2(struct gsm48_paging2 *pag) +{ + uint8_t len; + uint8_t *buf = pag->data; + int rc; + struct osmo_mobile_identity mi3 = {}; /* GSM_MI_TYPE_NONE */ + P2_Rest_Octets_t p2ro = {}; + unsigned p2_rest_oct_len; + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + struct gprs_rlcmac_entity *gre; + + LOGRLCMAC(LOGL_INFO, "Rx Paging Request Type 2\n"); + + if (GSM_MACBLOCK_LEN < sizeof(*pag)) + return -EBADMSG; + + /* The L2 pseudo length of this message is the sum of lengths of all + * information elements present in the message except the P1 Rest Octets and L2 + * Pseudo Length information elements. */ + if (pag->l2_plen == GSM_MACBLOCK_LEN - sizeof(pag->l2_plen)) { + /* no P2 Rest Octets => no Packet Page Indication => Discard */ + return 0; + } + + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + 1) + return -EBADMSG; + + /* No MI3 => Discard */ + if (*buf != GSM48_IE_MOBILE_ID) + return 0; + + buf++; + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + 1) + return -EBADMSG; + len = *buf; + buf++; + if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + len) + return -EBADMSG; + if ((rc = osmo_mobile_identity_decode(&mi3, buf, len, false)) < 0) + return rc; + buf += len; + + p2_rest_oct_len = GSM_MACBLOCK_LEN - (buf - (uint8_t *)pag); + if (p2_rest_oct_len == 0) { + /*No P1 Rest Octets => no Packet Page Indication => Discard */ + return 0; + } + + rc = osmo_gprs_rlcmac_decode_p2ro(&p2ro, buf, p2_rest_oct_len); + if (rc != 0) { + LOGRLCMAC(LOGL_ERROR, "Failed to parse P2 Rest Octets\n"); + return rc; + } + + if (p2ro.Packet_Page_Indication_3 != 1) /* NOT for GPRS*/ + return 0; + + switch (mi3.type) { + case GSM_MI_TYPE_IMSI: + if ((gre = gprs_rlcmac_find_entity_by_imsi(mi3.imsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + case GSM_MI_TYPE_TMSI: + if ((gre = gprs_rlcmac_find_entity_by_ptmsi(mi3.tmsi))) { + /* TS 24.007 C.13: Submit GMMRR-PAGE.ind: */ + rlcmac_prim = gprs_rlcmac_prim_alloc_gmmrr_page_ind(gre->tlli); + rc = gprs_rlcmac_prim_call_up_cb(rlcmac_prim); + } + break; + default: + return -EINVAL; + } + + return rc; +} + int gprs_rlcmac_handle_bcch_si13(const struct gsm48_system_information_type_13 *si13) { int rc; diff --git a/src/rlcmac/rlcmac_prim.c b/src/rlcmac/rlcmac_prim.c index 6e2285b..35e804c 100644 --- a/src/rlcmac/rlcmac_prim.c +++ b/src/rlcmac/rlcmac_prim.c @@ -559,7 +559,6 @@
static int rlcmac_prim_handle_l1ctl_ccch_data_ind(struct osmo_gprs_rlcmac_prim *rlcmac_prim) { - /* TODO: check if it's IMM_ASS: */ int rc;
switch (rlcmac_prim->l1ctl.ccch_data_ind.data[2]) { @@ -567,6 +566,12 @@ rc = gprs_rlcmac_handle_ccch_imm_ass((struct gsm48_imm_ass *)rlcmac_prim->l1ctl.ccch_data_ind.data, rlcmac_prim->l1ctl.ccch_data_ind.fn); break; + case GSM48_MT_RR_PAG_REQ_1: + rc = gprs_rlcmac_handle_ccch_pag_req_1((struct gsm48_paging1 *)rlcmac_prim->l1ctl.ccch_data_ind.data); + break; + case GSM48_MT_RR_PAG_REQ_2: + rc = gprs_rlcmac_handle_ccch_pag_req_2((struct gsm48_paging2 *)rlcmac_prim->l1ctl.ccch_data_ind.data); + break; case GSM48_MT_RR_SYSINFO_13: rc = gprs_rlcmac_handle_bcch_si13((struct gsm48_system_information_type_13 *)rlcmac_prim->l1ctl.ccch_data_ind.data); break;