From 8c3680dcc9819c337ab7629e86164b14017aab28 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 8 Oct 2012 12:30:56 +0200 Subject: Added paging PS support by Ivan Kluchnikov Original code: c7e7f6868b6f24346424dee904f4e76d3f216ff4 (The code was committed earlier, but got lost somehow.) I added IMSI, so the paging request is sent in correct paging group. Also I excluded rest octets from pseudo length. It is tested and it work. --- src/gprs_bssgp_pcu.cpp | 28 ++++++++++++++++++++++++++-- src/gprs_rlcmac.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gprs_rlcmac.h | 3 +++ src/pcu_l1_if.cpp | 4 +++- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index 81511ee2..bd28ea02 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -247,6 +247,28 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) return 0; } +int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp) +{ + char imsi[16]; + uint8_t *ptmsi = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_TMSI); + uint16_t ptmsi_len = TLVP_LEN(tp, BSSGP_IE_TMSI); + + LOGP(DBSSGP, LOGL_NOTICE, " P-TMSI = "); + for (int i = 0; i < ptmsi_len; i++) + { + LOGPC(DBSSGP, LOGL_NOTICE, "%02x", ptmsi[i]); + } + LOGPC(DBSSGP, LOGL_NOTICE, "\n"); + + if (parse_imsi(tp, imsi)) + { + LOGP(DBSSGP, LOGL_ERROR, "No IMSI\n"); + return -EINVAL; + } + + return gprs_rlcmac_paging_request(ptmsi, ptmsi_len, imsi); +} + /* Receive a BSSGP PDU from a BSS on a PTP BVCI */ int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx) { @@ -321,7 +343,8 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp bvc_timeout(NULL); break; case BSSGP_PDUT_PAGING_PS: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_PAGING_PS\n"); + LOGP(DBSSGP, LOGL_NOTICE, "RX: [SGSN->PCU] BSSGP_PDUT_PAGING_PS\n"); + gprs_bssgp_pcu_rx_paging_ps(msg, tp); break; case BSSGP_PDUT_PAGING_CS: LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_PAGING_CS\n"); @@ -390,7 +413,8 @@ int gprs_bssgp_pcu_rcvmsg(struct msgb *msg) if (!bctx && pdu_type != BSSGP_PDUT_BVC_RESET_ACK - && pdu_type != BSSGP_PDUT_BVC_UNBLOCK_ACK) + && pdu_type != BSSGP_PDUT_BVC_UNBLOCK_ACK + && pdu_type != BSSGP_PDUT_PAGING_PS) { LOGP(DBSSGP, LOGL_NOTICE, "NSEI=%u/BVCI=%u Rejecting PDU " "type %u for unknown BVCI\n", msgb_nsei(msg), ns_bvci, diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 1f981933..ff423d2c 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -1573,6 +1573,43 @@ void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi, block->u.Packet_Downlink_Assignment.Exist_AdditionsR99 = 0x0; // AdditionsR99 = off } +/* generate paging request */ +int write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi_len) +{ + unsigned wp = 0; + int plen; + + bitvec_write_field(dest, wp,0x0,4); // Skip Indicator + bitvec_write_field(dest, wp,0x6,4); // Protocol Discriminator + bitvec_write_field(dest, wp,0x21,8); // Paging Request Message Type + + bitvec_write_field(dest, wp,0x0,4); // Page Mode + bitvec_write_field(dest, wp,0x0,4); // Channel Needed + + // Mobile Identity + bitvec_write_field(dest, wp,ptmsi_len+1,8); // Mobile Identity length + bitvec_write_field(dest, wp,0xf,4); // unused + bitvec_write_field(dest, wp,0x4,4); // PTMSI type + for (int i = 0; i < ptmsi_len; i++) + { + bitvec_write_field(dest, wp,ptmsi[i],8); // PTMSI + } + if ((wp % 8)) { + LOGP(DRLCMACUL, LOGL_ERROR, "Length of PAG.REQ without rest " + "octets is not multiple of 8 bits, PLEASE FIX!\n"); + exit (0); + } + plen = wp / 8; + bitvec_write_field(dest, wp,0x0,1); // "L" NLN(PCH) = off + bitvec_write_field(dest, wp,0x0,1); // "L" Priority1 = off + bitvec_write_field(dest, wp,0x1,1); // "L" Priority2 = off + bitvec_write_field(dest, wp,0x0,1); // "L" Group Call information = off + bitvec_write_field(dest, wp,0x0,1); // "H" Packet Page Indication 1 = packet paging procedure + bitvec_write_field(dest, wp,0x1,1); // "H" Packet Page Indication 2 = packet paging procedure + + return plen; +} + /* generate uplink ack */ void write_packet_uplink_ack(RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf, uint8_t final) @@ -1700,3 +1737,16 @@ int gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf) return 0; } + +int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, + const char *imsi) +{ + LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Paging Request (CCCH)\n"); + bitvec *paging_request = bitvec_alloc(23); + bitvec_unhex(paging_request, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); + int plen = write_paging_request(paging_request, ptmsi, ptmsi_len); + pcu_l1if_tx_pch(paging_request, plen, (char *)imsi); + bitvec_free(paging_request); + + return 0; +} diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index dbbd6739..b26f58b5 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -363,6 +363,9 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, uint8_t ssn, uint8_t *rbb); +int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len, + const char *imsi); + unsigned write_packet_paging_request(bitvec * dest); unsigned write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t len, diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 14981820..3ebe90ba 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -203,7 +203,9 @@ static int pcu_rx_data_cnf(struct gsm_pcu_if_data *data_cnf) switch (data_cnf->sapi) { case PCU_IF_SAPI_PCH: - rc = gprs_rlcmac_imm_ass_cnf(data_cnf->data, data_cnf->fn); + if (data_cnf->data[2] == 0x3f) + rc = gprs_rlcmac_imm_ass_cnf(data_cnf->data, + data_cnf->fn); break; default: LOGP(DL1IF, LOGL_ERROR, "Received PCU data confirm with " -- cgit v1.2.3