aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_rlcmac_data.cpp
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-09-27 09:23:24 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2012-09-27 09:23:24 +0200
commita9be1547b1b4459d64d92207da2a29e41fcb3ba2 (patch)
treeb05502667c99050b587eab0691b2b54b221aa769 /src/gprs_rlcmac_data.cpp
parent99a107dbeef03b2e80aff82023cdfc5c10109b5b (diff)
Use PCH confirm from BTS to start downlink packet flow
Since we don't know when the IMM.ASS message is sent on it's paging group on PCH, we will wait for confirm from BTS and start packet flow then.
Diffstat (limited to 'src/gprs_rlcmac_data.cpp')
-rw-r--r--src/gprs_rlcmac_data.cpp67
1 files changed, 60 insertions, 7 deletions
diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp
index dedf98a8..66d29c6d 100644
--- a/src/gprs_rlcmac_data.cpp
+++ b/src/gprs_rlcmac_data.cpp
@@ -73,6 +73,9 @@ struct rlc_li_field {
} __attribute__ ((packed));
}
+static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll,
+ char *imsi);
+
static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf)
{
if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
@@ -179,6 +182,16 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf)
tbf_timer_start(tbf, 3195, bts->t3195, 0);
return 0;
}
+ /* resend IMM.ASS on CCCH on timeout */
+ if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
+ && !(tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "Re-send dowlink assignment "
+ "for TBF=%d on PCH (IMSI=%s)\n", tbf->tfi,
+ tbf->dir.dl.imsi);
+ /* send immediate assignment */
+ gprs_rlcmac_downlink_assignment(tbf, 0, tbf->dir.dl.imsi);
+ tbf->dir.dl.wait_confirm = 1;
+ }
} else
LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
@@ -477,12 +490,13 @@ void tbf_timer_cb(void *_tbf)
}
if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
/* change state to FLOW, so scheduler will start transmission */
+ tbf->dir.dl.wait_confirm = 0;
if (tbf->state == GPRS_RLCMAC_ASSIGN) {
tbf_new_state(tbf, GPRS_RLCMAC_FLOW);
tbf_assign_control_ts(tbf);
} else
- LOGP(DRLCMAC, LOGL_ERROR, "Error: TBF is not "
- "in assign state\n");
+ LOGP(DRLCMAC, LOGL_NOTICE, "Continue flow after "
+ "IMM.ASS confirm\n");
}
break;
case 3169:
@@ -1621,7 +1635,8 @@ 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 */
- tbf->state_flags = 0;
+ tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep TO flags */
+ tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
tbf_update(tbf);
gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
@@ -1778,12 +1793,50 @@ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf,
/* change state */
tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
+ strncpy(tbf->dir.dl.imsi, imsi, sizeof(tbf->dir.dl.imsi));
/* send immediate assignment */
gprs_rlcmac_downlink_assignment(tbf, 0, imsi);
- /* send immediate assignment */
- gprs_rlcmac_downlink_assignment(tbf, 0, imsi);
- /* start timer */
+ tbf->dir.dl.wait_confirm = 1;
+ }
+}
+
+int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn)
+{
+ struct gprs_rlcmac_tbf *tbf;
+ uint8_t plen;
+ uint32_t tlli;
+
+ /* move to IA Rest Octets */
+ plen = data[0] >> 2;
+ data += 1 + plen;
+
+ if ((*data & 0xf0) != 0xd0) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but rest "
+ "octets do not start with bit sequence 'HH01' "
+ "(Packet Downlink Assignment)\n");
+ return -EINVAL;
+ }
+
+ /* get TLLI from downlink assignment */
+ tlli = (*data++) << 28;
+ tlli |= (*data++) << 20;
+ tlli |= (*data++) << 12;
+ tlli |= (*data++) << 4;
+ tlli |= (*data++) >> 4;
+
+ tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF);
+ if (!tbf) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
+ "does not exit\n", tlli);
+ return -EINVAL;
+ }
+
+ LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
+
+ if (tbf->dir.dl.wait_confirm) {
tbf_timer_start(tbf, 0, Tassign_agch);
}
- }
+
+ return 0;
+}