aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.cpp54
-rw-r--r--src/tbf.cpp21
-rw-r--r--src/tbf.h10
-rw-r--r--src/tbf_dl.cpp33
4 files changed, 83 insertions, 35 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 86659621..b6600144 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -511,9 +511,12 @@ void BTS::trigger_dl_ass(
LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on "
"PACCH, because %s exists\n", tbf_name(old_tbf));
old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
+
+ old_tbf->set_new_tbf(dl_tbf);
+ old_tbf->was_releasing = old_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
+
/* use TA from old TBF */
dl_tbf->ta = old_tbf->ta;
- dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
/* change state */
dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
@@ -530,6 +533,7 @@ void BTS::trigger_dl_ass(
dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
dl_tbf->assign_imsi(imsi);
+ dl_tbf->set_new_tbf(dl_tbf);
/* send immediate assignment */
dl_tbf->bts->snd_dl_ass(dl_tbf, 0, imsi);
dl_tbf->m_wait_confirm = 1;
@@ -729,7 +733,7 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, in
void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, uint32_t fn)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_tbf *tbf, *new_tbf;
uint32_t tlli = 0;
tlli = packet->TLLI;
@@ -766,25 +770,27 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
/* reset N3105 */
tbf->n3105 = 0;
tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- if (tbf->direction == GPRS_RLCMAC_UL_TBF)
- tbf = bts()->dl_tbf_by_tlli(tbf->tlli());
-#warning "TBF is changing on the way... *sigh*"
- if (!tbf) {
+
+ new_tbf = tbf->new_tbf();
+ if (!new_tbf) {
LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- tbf->set_state(GPRS_RLCMAC_FLOW);
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ tbf_free(tbf);
+
+ new_tbf->set_state(GPRS_RLCMAC_FLOW);
/* stop pending assignment timer */
- tbf->stop_timer();
- if ((tbf->state_flags &
+ new_tbf->stop_timer();
+ if ((new_tbf->state_flags &
(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
- tbf->state_flags &=
+ new_tbf->state_flags &=
~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
- "assignment for %s\n", tbf_name(tbf));
+ "assignment for %s\n", tbf_name(new_tbf));
}
- tbf_assign_control_ts(tbf);
+ tbf_assign_control_ts(new_tbf);
return;
}
if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
@@ -792,23 +798,25 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
/* reset N3105 */
tbf->n3105 = 0;
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
-#warning "TBF is changing on the way... *sigh*"
- if (tbf->direction == GPRS_RLCMAC_DL_TBF)
- tbf = bts()->ul_tbf_by_tlli(tbf->tlli());
- if (!tbf) {
+
+ new_tbf = tbf->new_tbf();
+ if (!new_tbf) {
LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
"TBF is gone TLLI=0x%08x\n", tlli);
return;
}
- tbf->set_state(GPRS_RLCMAC_FLOW);
- if ((tbf->state_flags &
+ if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
+ tbf_free(tbf);
+
+ new_tbf->set_state(GPRS_RLCMAC_FLOW);
+ if ((new_tbf->state_flags &
(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
- tbf->state_flags &=
+ new_tbf->state_flags &=
~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
- "assignment for UL %s\n", tbf_name(tbf));
+ "assignment for UL %s\n", tbf_name(new_tbf));
}
- tbf_assign_control_ts(tbf);
+ tbf_assign_control_ts(new_tbf);
return;
}
LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
@@ -858,7 +866,7 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
if (ack_nack->Exist_Channel_Request_Description) {
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
"message, so we provide one:\n");
- tbf_alloc_ul(bts_data(), tbf->trx->trx_no, tbf->ms_class, tbf->tlli(), tbf->ta, tbf);
+ tbf->set_new_tbf(tbf_alloc_ul(bts_data(), tbf->trx->trx_no, tbf->ms_class, tbf->tlli(), tbf->ta, tbf));
/* schedule uplink assignment */
tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
}
@@ -920,6 +928,8 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request,
ul_tbf = tbf_alloc_ul(bts_data(), trx_no(), ms_class, tlli, ta, NULL);
if (!ul_tbf)
return;
+
+ ul_tbf->set_new_tbf(ul_tbf);
/* set control ts to current MS's TS, until assignment complete */
LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts_no);
ul_tbf->control_ts = ts_no;
diff --git a/src/tbf.cpp b/src/tbf.cpp
index ccf73627..2afe2576 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -51,6 +51,11 @@ void gprs_rlcmac_tbf::assign_imsi(const char *imsi)
m_imsi[sizeof(m_imsi) - 1] = '\0';
}
+void gprs_rlcmac_tbf::set_new_tbf(gprs_rlcmac_tbf *tbf)
+{
+ m_new_tbf = tbf;
+}
+
gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
int8_t use_trx, uint8_t ms_class,
uint32_t tlli, uint8_t ta, struct gprs_rlcmac_tbf *dl_tbf)
@@ -557,10 +562,10 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
"finished.\n");
return NULL;
}
- #warning "THIS should probably go over the IMSI too"
- new_dl_tbf = ul_tbf->bts->dl_tbf_by_tlli(m_tlli);
- } else
- new_dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ }
+
+ new_dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(m_new_tbf);
+ new_dl_tbf->was_releasing = was_releasing;
if (!new_dl_tbf) {
LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink "
"assignment at uplink %s, but there is no downlink "
@@ -625,13 +630,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
return NULL;
}
- /* on down TBF we get the uplink TBF to be assigned. */
-#warning "Probably want to find by IMSI too"
- if (direction == GPRS_RLCMAC_DL_TBF)
- new_tbf = bts->ul_tbf_by_tlli(m_tlli);
- else
- new_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
-
+ new_tbf = static_cast<gprs_rlcmac_ul_tbf *>(m_new_tbf);
if (!new_tbf) {
LOGP(DRLCMACUL, LOGL_ERROR, "We have a schedule for uplink "
"assignment at downlink %s, but there is no uplink "
diff --git a/src/tbf.h b/src/tbf.h
index c0f976d4..69f1f053 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -142,6 +142,9 @@ struct gprs_rlcmac_tbf {
const char *imsi() const;
void assign_imsi(const char *imsi);
+ void set_new_tbf(gprs_rlcmac_tbf *tbf);
+ gprs_rlcmac_tbf *new_tbf() const;
+
time_t created_ts() const;
/* attempt to make things a bit more fair */
@@ -165,6 +168,8 @@ struct gprs_rlcmac_tbf {
enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
+ gprs_rlcmac_tbf *m_new_tbf;
+
enum gprs_rlcmac_tbf_poll_state poll_state;
uint32_t poll_fn; /* frame number to poll */
@@ -289,6 +294,11 @@ inline const char *gprs_rlcmac_tbf::imsi() const
return m_imsi;
}
+inline gprs_rlcmac_tbf *gprs_rlcmac_tbf::new_tbf() const
+{
+ return m_new_tbf;
+}
+
inline time_t gprs_rlcmac_tbf::created_ts() const
{
return m_created_ts;
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 8abea201..a715af78 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -643,10 +643,39 @@ int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb
void gprs_rlcmac_dl_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
{
+ uint8_t trx;
+ struct gprs_rlcmac_dl_tbf *new_tbf;
+ int8_t tfi; /* must be signed */
+ int rc;
+ struct msgb *msg;
+
bts->tbf_reused();
- m_llc.put_frame(data, len);
+
+ tfi = bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx, this->trx->trx_no);
+ if (tfi < 0) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
+ /* FIXME: send reject */
+ return;
+ }
+ new_tbf = tbf_alloc_dl_tbf(bts->bts_data(), NULL, tfi, trx, ms_class, 0);
+ if (!new_tbf) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
+ /* FIXME: send reject */
+ return;
+ }
+
+ new_tbf->m_tlli = m_tlli;
+ new_tbf->m_tlli_valid = m_tlli_valid;
+ new_tbf->ta = ta;
+ new_tbf->assign_imsi(m_imsi);
+
+ /* Copy over all data to the new TBF */
+ new_tbf->m_llc.put_frame(data, len);
bts->llc_frame_sched();
+ while ((msg = m_llc.dequeue()))
+ new_tbf->m_llc.enqueue(msg);
+
/* reset rlc states */
m_tx_counter = 0;
m_wait_confirm = 0;
@@ -661,7 +690,7 @@ void gprs_rlcmac_dl_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
LOGP(DRLCMAC, LOGL_DEBUG, "%s Trigger dowlink assignment on PACCH, "
"because another LLC PDU has arrived in between\n",
tbf_name(this));
- bts->trigger_dl_ass(this, this, NULL);
+ bts->trigger_dl_ass(new_tbf, this, NULL);
}
bool gprs_rlcmac_dl_tbf::dl_window_stalled() const