aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_bssgp_pcu.cpp34
-rw-r--r--src/gprs_rlcmac.h2
-rw-r--r--src/gprs_rlcmac_data.cpp25
-rw-r--r--src/pcu_l1_if.cpp13
-rw-r--r--src/pcu_l1_if.h1
-rw-r--r--src/sysmo_l1_if.cpp17
6 files changed, 69 insertions, 23 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 74b24bbe..733d4e29 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -32,7 +32,7 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
struct bssgp_ud_hdr *budh;
int tfi;
uint32_t tlli;
- int i = 0;
+ int i, j;
uint8_t trx, ts;
uint8_t *data;
uint16_t len;
@@ -55,22 +55,30 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP TLLI=0x%08x Rx UL-UD IE_LLC_PDU too large\n", tlli);
return bssgp_tx_status(BSSGP_CAUSE_COND_IE_ERR, NULL, msg);
}
- LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x %s\n", tlli, osmo_hexdump(data, len));
- uint16_t imsi_len = 0;
- uint8_t *imsi;
+ /* read IMSI. if no IMSI exists, use first paging block (any paging),
+ * because during attachment the IMSI might not be known, so the MS
+ * will listen to all paging blocks. */
+ char imsi[16] = "000";
if (TLVP_PRESENT(tp, BSSGP_IE_IMSI))
{
- imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
- imsi = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_IMSI);
-
- LOGPC(DBSSGP, LOGL_DEBUG, " IMSI = ");
- for (i = 0; i < imsi_len; i++)
+ uint8_t imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
+ uint8_t *bcd_imsi = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_IMSI);
+ if ((bcd_imsi[0] & 0x08))
+ imsi_len = imsi_len * 2 - 1;
+ else
+ imsi_len = (imsi_len - 1) * 2;
+ for (i = 0, j = 0; j < imsi_len && j < 16; j++)
{
- LOGPC(DBSSGP, LOGL_DEBUG, "%02x", imsi[i]);
+ if (!(j & 1)) {
+ imsi[j] = (bcd_imsi[i] >> 4) + '0';
+ i++;
+ } else
+ imsi[j] = (bcd_imsi[i] & 0xf) + '0';
}
- LOGPC(DBSSGP, LOGL_DEBUG, "\n");
+ imsi[j] = '\0';
}
+ LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len);
/* check for existing TBF */
if ((tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
@@ -82,7 +90,7 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
tbf->llc_length = len;
memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset
rlc states */
- gprs_rlcmac_trigger_downlink_assignment(tbf, 1);
+ gprs_rlcmac_trigger_downlink_assignment(tbf, 1, NULL);
} else {
/* the TBF exists, so we must write it in the queue */
struct msgb *llc_msg = msgb_alloc(len, "llc_pdu_queue");
@@ -114,7 +122,7 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
* we don't use old_downlink, so the possible uplink is used
* to trigger downlink assignment. if there is no uplink,
* AGCH is used. */
- gprs_rlcmac_trigger_downlink_assignment(tbf, 0);
+ gprs_rlcmac_trigger_downlink_assignment(tbf, 0, imsi);
}
return 0;
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index c47d6d41..abb99808 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -252,7 +252,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
struct gprs_rlcmac_tbf *tbf, uint32_t fn);
void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf,
- uint8_t old_downlink);
+ uint8_t old_downlink, char *imsi);
int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
uint8_t ssn, uint8_t *rbb);
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index ea813c63..a87fef1b 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -263,6 +263,9 @@ puts("FIXME: UL request during UL request"); exit(0);
return 1;
}
+#ifdef DEBUG_DL_ASS_IDLE
+ char debug_imsi[16];
+#endif
void tbf_timer_cb(void *_tbf)
{
@@ -276,7 +279,7 @@ void tbf_timer_cb(void *_tbf)
switch (tbf->T) {
#ifdef DEBUG_DL_ASS_IDLE
case 1234:
- gprs_rlcmac_trigger_downlink_assignment(tbf, 0);
+ gprs_rlcmac_trigger_downlink_assignment(tbf, 0, debug_imsi);
break;
#endif
case 0: /* assignment */
@@ -1268,7 +1271,7 @@ int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final,
LOGP(DRLCMAC, LOGL_DEBUG, "Trigger dowlink assignment on PACCH, "
"because another LLC PDU has arrived in between\n");
memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset RLC states */
- gprs_rlcmac_trigger_downlink_assignment(tbf, 1);
+ gprs_rlcmac_trigger_downlink_assignment(tbf, 1, NULL);
return 0;
}
@@ -1334,25 +1337,27 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment(
return msg;
}
-static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll)
+static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll,
+ char *imsi)
{
- LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u TLLI: 0x%08x Immediate Assignment Downlink (AGCH)\n", tbf->tfi, tbf->tlli);
+ LOGP(DRLCMAC, LOGL_INFO, "TX: START TFI: %u TLLI: 0x%08x Immediate Assignment Downlink (PCH)\n", tbf->tfi, tbf->tlli);
bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
/* use request reference that has maximum distance to current time,
* so the assignment will not conflict with possible RACH requests. */
int plen = write_immediate_assignment(immediate_assignment, 1, 125, (tbf->pdch->last_rts_fn + 21216) % 2715648, tbf->ta, tbf->arfcn, tbf->ts, tbf->tsc, tbf->tfi, 0, tbf->tlli, poll, tbf->poll_fn);
- pcu_l1if_tx_agch(immediate_assignment, plen);
+ pcu_l1if_tx_pch(immediate_assignment, plen, imsi);
bitvec_free(immediate_assignment);
}
/* depending on the current TBF, we assign on PACCH or AGCH */
void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf,
- uint8_t old_downlink)
+ uint8_t old_downlink, char *imsi)
{
gprs_rlcmac_tbf *old_tbf;
#ifdef DEBUG_DL_ASS_IDLE
+ strncpy(debug_imsi, imsi);
LOGP(DRLCMAC, LOGL_ERROR, "**** DEBUGGING DOWNLINK ASSIGNMENT ****\n");
#endif
@@ -1384,9 +1389,13 @@ void gprs_rlcmac_trigger_downlink_assignment(gprs_rlcmac_tbf *tbf,
tbf_timer_start(tbf, 0, Tassign_pacch);
#endif
} else {
- LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on AGCH, no TBF exist\n", tbf->tfi);
+ LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for TBF=%d on PCH, no TBF exist (IMSI=%s)\n", tbf->tfi, imsi);
+ if (!imsi || strlen(imsi) < 3) {
+ LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n");
+ return;
+ }
/* send immediate assignment */
- gprs_rlcmac_downlink_assignment(tbf, 0);
+ gprs_rlcmac_downlink_assignment(tbf, 0, imsi);
/* change state */
tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
/* start timer */
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index f6ba7750..865a9118 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -120,7 +120,18 @@ void pcu_l1if_tx_agch(bitvec * block, int plen)
prim->id = GsmL1_PrimId_PhDataReq;
prim->u.phDataReq.sapi = GsmL1_Sapi_Agch;
bitvec_pack(block, prim->u.phDataReq.msgUnitParam.u8Buffer);
-#warning Please review, if OpenBTS requires AGCH frame without pseudo length:
+ prim->u.phDataReq.msgUnitParam.u8Size = 22;
+ osmo_wqueue_enqueue(&l1fh->udp_wq, msg);
+}
+
+void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi)
+{
+ struct msgb *msg = l1p_msgb_alloc();
+ GsmL1_Prim_t *prim = msgb_l1prim(msg);
+
+ prim->id = GsmL1_PrimId_PhDataReq;
+ prim->u.phDataReq.sapi = GsmL1_Sapi_Pch;
+ bitvec_pack(block, prim->u.phDataReq.msgUnitParam.u8Buffer);
prim->u.phDataReq.msgUnitParam.u8Size = 22;
osmo_wqueue_enqueue(&l1fh->udp_wq, msg);
}
diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h
index b8cc5c95..2aac5531 100644
--- a/src/pcu_l1_if.h
+++ b/src/pcu_l1_if.h
@@ -36,6 +36,7 @@ void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
void pcu_l1if_tx_ptcch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn,
uint32_t fn, uint8_t block_nr);
void pcu_l1if_tx_agch(bitvec * block, int len);
+void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi);
int pcu_l1if_open(void);
void pcu_l1if_close(void);
diff --git a/src/sysmo_l1_if.cpp b/src/sysmo_l1_if.cpp
index 6cce5543..ceb28d28 100644
--- a/src/sysmo_l1_if.cpp
+++ b/src/sysmo_l1_if.cpp
@@ -150,6 +150,23 @@ void pcu_l1if_tx_agch(bitvec * block, int plen)
pcu_tx_data_req(0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, 23);
}
+void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi)
+{
+ uint8_t data[23+3]; /* prefix PLEN */
+
+ /* paging group */
+ if (!imsi || strlen(imsi) < 3)
+ return;
+ imsi += strlen(imsi) - 3;
+ data[0] = imsi[0];
+ data[1] = imsi[1];
+ data[2] = imsi[2];
+
+ bitvec_pack(block, data + 3+1);
+ data[3] = (plen << 2) | 0x01;
+ pcu_tx_data_req(0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, 23+3);
+}
+
static void pcu_l1if_tx_bcch(uint8_t *data, int len)
{
pcu_tx_data_req(0, 0, PCU_IF_SAPI_BCCH, 0, 0, 0, data, len);