diff options
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 34 | ||||
-rw-r--r-- | src/gprs_rlcmac.h | 2 | ||||
-rw-r--r-- | src/gprs_rlcmac_data.cpp | 25 | ||||
-rw-r--r-- | src/pcu_l1_if.cpp | 13 | ||||
-rw-r--r-- | src/pcu_l1_if.h | 1 | ||||
-rw-r--r-- | src/sysmo_l1_if.cpp | 17 |
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); |