Send downlink IMMEDIATE ASSIGNMENT on PCH and not on AGCH
The IMSI is used to define paging group on which it is sent. This is tested with MS that requires correct paging group.
This commit is contained in:
parent
88a214cc45
commit
e13fa2d569
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue