aboutsummaryrefslogtreecommitdiffstats
path: root/src/tbf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tbf.cpp')
-rw-r--r--src/tbf.cpp235
1 files changed, 149 insertions, 86 deletions
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 2afe2576..6f601aa2 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -38,7 +38,57 @@ extern "C" {
extern void *tall_pcu_ctx;
-static void tbf_timer_cb(void *_tbf);
+static void tbf_timer_tassign_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_assignment_timeout();
+}
+
+static void tbf_timer_t3169_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3169);
+}
+
+static void tbf_timer_t3191_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3191);
+}
+
+static void tbf_timer_t3193_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3193);
+}
+
+static void tbf_timer_t3195_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3195);
+}
+
+static void tbf_timer_t3197_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3197);
+}
+
+static void tbf_timer_t3199_cb(void *_tbf)
+{
+ struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
+ tbf->handle_timeout(GPRS_RLCMAC_T3199);
+}
+
+static void (*tbf_timer_cb[GPRS_RLCMAC_TMAX])(void *_tbf) = {
+ tbf_timer_tassign_cb,
+ tbf_timer_t3169_cb,
+ tbf_timer_t3191_cb,
+ tbf_timer_t3193_cb,
+ tbf_timer_t3195_cb,
+ tbf_timer_t3197_cb,
+ tbf_timer_t3199_cb,
+};
gprs_rlcmac_bts *gprs_rlcmac_tbf::bts_data() const
{
@@ -85,7 +135,7 @@ gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
tbf->ta = ta; /* use current TA */
tbf->set_state(GPRS_RLCMAC_ASSIGN);
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
- tbf_timer_start(tbf, 3169, bts->t3169, 0);
+ tbf_timer_start(tbf, GPRS_RLCMAC_T3169, bts->t3169, 0);
return tbf;
}
@@ -127,7 +177,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
"assignment message never gets transmitted. Please "
"be sure not to free in this state. PLEASE FIX!\n",
tbf_name(tbf));
- tbf->stop_timer();
+ tbf->stop_timers();
#warning "TODO: Could/Should generate bssgp_tx_llc_discarded"
tbf->m_llc.clear(tbf->bts);
tbf_unlink_pdch(tbf);
@@ -188,38 +238,58 @@ const char *gprs_rlcmac_tbf::tbf_state_name[] = {
"RELEASING",
};
-void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
+static const char *timer_no[GPRS_RLCMAC_TMAX] = {
+ "Tassign",
+ "T3169",
+ "T3191",
+ "T3193",
+ "T3195",
+ "T3197",
+ "T3199"
+};
+
+void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, enum gprs_rlcmac_tbf_timer_type type,
unsigned int seconds, unsigned int microseconds)
{
- if (!osmo_timer_pending(&tbf->timer))
- LOGP(DRLCMAC, LOGL_DEBUG, "%s starting timer %u.\n",
- tbf_name(tbf), T);
+ if (type < 0 || type > GPRS_RLCMAC_TMAX)
+ return;
+ if (!osmo_timer_pending(&tbf->timer[type]))
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s starting timer %s.\n",
+ tbf_name(tbf), timer_no[type]);
else
- LOGP(DRLCMAC, LOGL_DEBUG, "%s restarting timer %u "
- "while old timer %u pending \n",
- tbf_name(tbf), T, tbf->T);
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s restarting timer %s "
+ "while old timer pending \n",
+ tbf_name(tbf), timer_no[type]);
- tbf->T = T;
- tbf->num_T_exp = 0;
+ /* Running timers can be safely re-scheduled. */
+ tbf->timer[type].data = tbf;
+ tbf->timer[type].cb = tbf_timer_cb[type];
- /* Tunning timers can be safely re-scheduled. */
- tbf->timer.data = tbf;
- tbf->timer.cb = &tbf_timer_cb;
-
- osmo_timer_schedule(&tbf->timer, seconds, microseconds);
+ osmo_timer_schedule(&tbf->timer[type], seconds, microseconds);
}
void gprs_rlcmac_tbf::stop_t3191()
{
- return stop_timer();
+ return stop_timer(GPRS_RLCMAC_T3191);
+}
+
+void gprs_rlcmac_tbf::stop_timer(enum gprs_rlcmac_tbf_timer_type type)
+{
+ if (type < 0 || type > GPRS_RLCMAC_TMAX)
+ return;
+ if (osmo_timer_pending(&timer[type])) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s stopping timer %s.\n",
+ tbf_name(this), timer_no[type]);
+ osmo_timer_del(&timer[type]);
+ }
}
-void gprs_rlcmac_tbf::stop_timer()
+void gprs_rlcmac_tbf::stop_timers()
{
- if (osmo_timer_pending(&timer)) {
- LOGP(DRLCMAC, LOGL_DEBUG, "%s stopping timer %u.\n",
- tbf_name(this), T);
- osmo_timer_del(&timer);
+ unsigned int i;
+
+ for (i = 0; i < GPRS_RLCMAC_TMAX; i++) {
+ stop_timer((enum gprs_rlcmac_tbf_timer_type)i);
}
}
@@ -245,7 +315,7 @@ void gprs_rlcmac_tbf::poll_timeout()
LOGP(DRLCMAC, LOGL_NOTICE,
"- N3103 exceeded\n");
ul_tbf->set_state(GPRS_RLCMAC_RELEASING);
- tbf_timer_start(ul_tbf, 3169, ul_tbf->bts->bts_data()->t3169, 0);
+ tbf_timer_start(ul_tbf, GPRS_RLCMAC_T3169, ul_tbf->bts->bts_data()->t3169, 0);
return;
}
/* reschedule UL ack */
@@ -264,7 +334,7 @@ void gprs_rlcmac_tbf::poll_timeout()
if (n3105 == bts_data()->n3105) {
LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
set_state(GPRS_RLCMAC_RELEASING);
- tbf_timer_start(this, 3195, bts_data()->t3195, 0);
+ tbf_timer_start(this, GPRS_RLCMAC_T3195, bts_data()->t3195, 0);
return;
}
/* reschedule UL assignment */
@@ -282,7 +352,7 @@ void gprs_rlcmac_tbf::poll_timeout()
if (n3105 == bts->bts_data()->n3105) {
LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
set_state(GPRS_RLCMAC_RELEASING);
- tbf_timer_start(this, 3195, bts_data()->t3195, 0);
+ tbf_timer_start(this, GPRS_RLCMAC_T3195, bts_data()->t3195, 0);
return;
}
/* reschedule DL assignment */
@@ -300,7 +370,7 @@ void gprs_rlcmac_tbf::poll_timeout()
if (dl_tbf->n3105 == dl_tbf->bts->bts_data()->n3105) {
LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
dl_tbf->set_state(GPRS_RLCMAC_RELEASING);
- tbf_timer_start(dl_tbf, 3195, dl_tbf->bts_data()->t3195, 0);
+ tbf_timer_start(dl_tbf, GPRS_RLCMAC_T3195, dl_tbf->bts_data()->t3195, 0);
return;
}
/* resend IMM.ASS on CCCH on timeout */
@@ -430,69 +500,62 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
return tbf;
}
-static void tbf_timer_cb(void *_tbf)
+void gprs_rlcmac_tbf::handle_assignment_timeout()
{
- struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf;
- tbf->handle_timeout();
-}
+ if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) {
+ if (state_is(GPRS_RLCMAC_ASSIGN)) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "%s releasing due to "
+ "PACCH assignment timeout.\n", tbf_name(this));
+ tbf_free(this);
+ return;
+ } else
+ LOGP(DRLCMAC, LOGL_ERROR, "Error: %s is not "
+ "in assign state\n", tbf_name(this));
+ }
+ if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
+ gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ dl_tbf->m_wait_confirm = 0;
+ if (dl_tbf->state_is(GPRS_RLCMAC_ASSIGN)) {
+ tbf_assign_control_ts(dl_tbf);
+
+ if (!dl_tbf->upgrade_to_multislot) {
+ /* change state to FLOW, so scheduler
+ * will start transmission */
+ dl_tbf->set_state(GPRS_RLCMAC_FLOW);
+ return;
+ }
-void gprs_rlcmac_tbf::handle_timeout()
-{
- LOGP(DRLCMAC, LOGL_DEBUG, "%s timer %u expired.\n",
- tbf_name(this), T);
+ /* This tbf can be upgraded to use multiple DL
+ * timeslots and now that there is already one
+ * slot assigned send another DL assignment via
+ * PDCH. */
- num_T_exp++;
+ /* keep to flags */
+ dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+ dl_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
- switch (T) {
- case 0: /* assignment */
- if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) {
- if (state_is(GPRS_RLCMAC_ASSIGN)) {
- LOGP(DRLCMAC, LOGL_NOTICE, "%s releasing due to "
- "PACCH assignment timeout.\n", tbf_name(this));
- tbf_free(this);
- return;
- } else
- LOGP(DRLCMAC, LOGL_ERROR, "Error: %s is not "
- "in assign state\n", tbf_name(this));
- }
- if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
- gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
- dl_tbf->m_wait_confirm = 0;
- if (dl_tbf->state_is(GPRS_RLCMAC_ASSIGN)) {
- tbf_assign_control_ts(dl_tbf);
-
- if (!dl_tbf->upgrade_to_multislot) {
- /* change state to FLOW, so scheduler
- * will start transmission */
- dl_tbf->set_state(GPRS_RLCMAC_FLOW);
- break;
- }
-
- /* This tbf can be upgraded to use multiple DL
- * timeslots and now that there is already one
- * slot assigned send another DL assignment via
- * PDCH. */
-
- /* keep to flags */
- dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
- dl_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
-
- dl_tbf->update();
-
- dl_tbf->bts->trigger_dl_ass(dl_tbf, dl_tbf, NULL);
- } else
- LOGP(DRLCMAC, LOGL_NOTICE, "%s Continue flow after "
- "IMM.ASS confirm\n", tbf_name(dl_tbf));
- }
- break;
- case 3169:
- case 3191:
- case 3195:
- LOGP(DRLCMAC, LOGL_NOTICE, "%s T%d timeout during "
- "transsmission\n", tbf_name(this), T);
+ dl_tbf->update();
+
+ dl_tbf->bts->trigger_dl_ass(dl_tbf, dl_tbf, NULL);
+ } else
+ LOGP(DRLCMAC, LOGL_NOTICE, "%s Continue flow after "
+ "IMM.ASS confirm\n", tbf_name(dl_tbf));
+ }
+}
+void gprs_rlcmac_tbf::handle_timeout(enum gprs_rlcmac_tbf_timer_type type)
+{
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s timer %s expired.\n",
+ tbf_name(this), timer_no[type]);
+
+ switch (type) {
+ case GPRS_RLCMAC_T3169:
+ case GPRS_RLCMAC_T3191:
+ case GPRS_RLCMAC_T3195:
+ LOGP(DRLCMAC, LOGL_NOTICE, "%s %s timeout during "
+ "transsmission\n", tbf_name(this), timer_no[type]);
rlcmac_diag();
/* fall through */
- case 3193:
+ case GPRS_RLCMAC_T3193:
LOGP(DRLCMAC, LOGL_DEBUG,
"%s will be freed due to timeout\n", tbf_name(this));
/* free TBF */
@@ -501,7 +564,7 @@ void gprs_rlcmac_tbf::handle_timeout()
break;
default:
LOGP(DRLCMAC, LOGL_ERROR,
- "%s timer expired in unknown mode: %u\n", tbf_name(this), T);
+ "%s timer expired in unknown mode: %s\n", tbf_name(this), timer_no[type]);
}
}
@@ -606,7 +669,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
new_dl_tbf->set_state(GPRS_RLCMAC_FLOW);
tbf_assign_control_ts(new_dl_tbf);
/* stop pending assignment timer */
- new_dl_tbf->stop_timer();
+ new_dl_tbf->stop_timer(GPRS_RLCMAC_TASSIGN);
}