aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_bssgp_pcu.cpp28
-rw-r--r--src/gprs_rlcmac.cpp50
-rw-r--r--src/gprs_rlcmac.h3
-rw-r--r--src/pcu_l1_if.cpp4
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 "