rlcmac: Submit GMMRR-PAGE.ind upon rx of Paging Request Type 1/2
Change-Id: I64db4277b5c54870a258d63c554f470011bcc989
This commit is contained in:
parent
7bbdcc4414
commit
9cf485e45b
|
@ -86,9 +86,13 @@ extern struct gprs_rlcmac_ctx *g_rlcmac_ctx;
|
|||
|
||||
/* 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_req1(const struct gsm48_paging1 *pag);
|
||||
int gprs_rlcmac_handle_ccch_pag_req2(const 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);
|
||||
|
|
|
@ -134,7 +134,6 @@ int osmo_gprs_rlcmac_set_codel_params(bool use, unsigned int interval_msec)
|
|||
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 @@ struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli)
|
|||
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,203 @@ int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia, uint32_t fn)
|
|||
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_req1(const struct gsm48_paging1 *pag)
|
||||
{
|
||||
uint8_t len;
|
||||
const 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");
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
len = *buf;
|
||||
buf++;
|
||||
|
||||
if (GSM_MACBLOCK_LEN < (buf - (uint8_t *)pag) + 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:
|
||||
break; /* MI2 not present */
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* TS 44.018 9.1.23 "Paging request type 2" */
|
||||
int gprs_rlcmac_handle_ccch_pag_req2(const struct gsm48_paging2 *pag)
|
||||
{
|
||||
uint8_t len;
|
||||
const 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");
|
||||
|
||||
/* 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;
|
||||
|
|
|
@ -559,7 +559,6 @@ static int rlcmac_prim_handle_l1ctl_pdch_data_ind(struct osmo_gprs_rlcmac_prim *
|
|||
|
||||
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 @@ static int rlcmac_prim_handle_l1ctl_ccch_data_ind(struct osmo_gprs_rlcmac_prim *
|
|||
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_req1((const struct gsm48_paging1 *)rlcmac_prim->l1ctl.ccch_data_ind.data);
|
||||
break;
|
||||
case GSM48_MT_RR_PAG_REQ_2:
|
||||
rc = gprs_rlcmac_handle_ccch_pag_req2((const 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;
|
||||
|
|
|
@ -186,6 +186,45 @@ static uint8_t ccch_imm_ass_pkt_dl_tbf[] = {
|
|||
0x2b, 0x2b, 0x2b, 0x2b
|
||||
};
|
||||
|
||||
/*
|
||||
GSM CCCH - Paging Request Type 1
|
||||
L2 Pseudo Length
|
||||
0011 00.. = L2 Pseudo Length value: 12
|
||||
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
||||
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
||||
0000 .... = Skip Indicator: No indication of selected PLMN (0)
|
||||
Message Type: Paging Request Type 1
|
||||
Page Mode
|
||||
.... 0000 = Page Mode: Normal paging (0)
|
||||
Channel Needed
|
||||
..00 .... = Channel 1: Any channel (0)
|
||||
00.. .... = Channel 2: Any channel (0)
|
||||
Mobile Identity - Mobile Identity 1 - IMSI (262420000000423)
|
||||
Length: 8
|
||||
0010 .... = Identity Digit 1: 2
|
||||
.... 1... = Odd/even indication: Odd number of identity digits
|
||||
.... .001 = Mobile Identity Type: IMSI (1)
|
||||
IMSI: 262420000000423
|
||||
[Association IMSI: 262420000000423]
|
||||
Mobile Country Code (MCC): Germany (262)
|
||||
Mobile Network Code (MNC): Vodafone GmbH (42)
|
||||
P1 Rest Octets
|
||||
L... .... = NLN(PCH): Not Present
|
||||
.L.. .... = Priority 1: Not Present
|
||||
..L. .... = Priority 2: Not Present
|
||||
...L .... = Group Call Information: Not Present
|
||||
.... H... = Packet Page Indication 1: For GPRS
|
||||
.... .H.. = Packet Page Indication 2: For GPRS
|
||||
Padding Bits: default padding
|
||||
|
||||
*/
|
||||
static uint8_t ccch_pag_req_1[] = {
|
||||
0x31, 0x06, 0x21, 0x00, 0x08, 0x29, 0x26, 0x24, 0x00, 0x00,
|
||||
0x00, 0x40, 0x32, 0x27, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
|
||||
0x2b, 0x2b, 0x2b, 0x2b
|
||||
};
|
||||
|
||||
|
||||
#define clock_debug(fmt, args...) \
|
||||
do { \
|
||||
struct timespec ts; \
|
||||
|
@ -1029,6 +1068,38 @@ static void test_dl_tbf_ccch_assign_requests_ul_tbf_pacch(void)
|
|||
cleanup_test();
|
||||
}
|
||||
|
||||
/* SGSN->PCU->BTS --PCH--> MS containing "Paging Request Type 1" asking for PS services.
|
||||
* RLCMAC will send GMMRR-PAGE.ind to GMM layer, which is in charge of orchestrating the response. */
|
||||
static void test_ccch_pag_req1(void)
|
||||
{
|
||||
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
||||
int rc;
|
||||
|
||||
printf("=== %s start ===\n", __func__);
|
||||
prepare_test();
|
||||
uint32_t ptmsi = 0x00001234;
|
||||
char *imsi = "262420000000423";
|
||||
uint32_t tlli = 0x0000001;
|
||||
|
||||
/* Notify RLCMAC about our TLLI */
|
||||
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_gmmrr_assign_req(GPRS_RLCMAC_TLLI_UNASSIGNED, tlli);
|
||||
rlcmac_prim->gmmrr.assign_req.ptmsi = ptmsi;
|
||||
OSMO_STRLCPY_ARRAY(rlcmac_prim->gmmrr.assign_req.imsi, imsi);
|
||||
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
||||
|
||||
OSMO_ASSERT(sizeof(ccch_pag_req_1) == GSM_MACBLOCK_LEN);
|
||||
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_pag_req_1);
|
||||
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
/* Above prim is expected to trigger RLCMAC layer submitting GMMRR-Page.ind as here. */
|
||||
|
||||
/* Here GMM would start UL TBF through LLGM-TRIGGER.req(PAGE_RESPONSE),
|
||||
* and LLC in turn submits GRR-UNITDATA.req */
|
||||
|
||||
printf("=== %s end ===\n", __func__);
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
static const struct log_info_cat test_log_categories[] = { };
|
||||
static const struct log_info test_log_info = {
|
||||
.cat = test_log_categories,
|
||||
|
@ -1060,6 +1131,7 @@ int main(int argc, char *argv[])
|
|||
test_ul_tbf_request_another_ul_tbf();
|
||||
test_dl_tbf_ccch_assign();
|
||||
test_dl_tbf_ccch_assign_requests_ul_tbf_pacch();
|
||||
test_ccch_pag_req1();
|
||||
|
||||
talloc_free(tall_ctx);
|
||||
}
|
||||
|
|
|
@ -796,3 +796,10 @@ DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
|
|||
DLGLOBAL INFO UL_TBF{FINISHED}: Send L1CTL-CFG_UL_TBF.req ul_tbf_nr=0 (release)
|
||||
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
|
||||
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
|
||||
DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request
|
||||
DLGLOBAL INFO GMMRR-ASSIGN.req: creating new entity TLLI=0x00000001
|
||||
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Allocated
|
||||
DLGLOBAL DEBUG Rx from lower layers: L1CTL-CCCH_DATA.indication
|
||||
DLGLOBAL INFO Rx Paging Request Type 1
|
||||
DLGLOBAL NOTICE P1 Rest Octets: 74 remaining bits unhandled by decoder
|
||||
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
|
||||
|
|
|
@ -142,3 +142,7 @@ test_rlcmac_prim_up_cb(): Rx GMMRR-LLC_TRANSMITTED.indication TLLI=0x00000001
|
|||
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=47 ts=6 data_len=34 data=[00 06 00 39 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
|
||||
=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch end ===
|
||||
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
|
||||
=== test_ccch_pag_req1 start ===
|
||||
sys={0.000000}, mono={0.000000}: clock_override_set
|
||||
test_rlcmac_prim_up_cb(): Rx GMMRR-PAGE.indication TLLI=0x00000001
|
||||
=== test_ccch_pag_req1 end ===
|
||||
|
|
Loading…
Reference in New Issue