TBF: unify timer handling

Use generic timer handling infrastracture to handle assignment/reject
internal timer. Rename timer array accordingly. Use defines with
explicit second/microsecond values to make it more readable.

Change-Id: I63fb7e6f0695383a83472c836a381a055f64690b
This commit is contained in:
Max 2017-12-20 18:05:29 +01:00 committed by Harald Welte
parent effdec6e13
commit b2de1f7888
4 changed files with 32 additions and 68 deletions

View File

@ -554,7 +554,7 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli); LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
if (dl_tbf->m_wait_confirm) if (dl_tbf->m_wait_confirm)
tbf_timer_start(dl_tbf, 0, Tassign_agch, "assignment (AGCH)"); dl_tbf->t_start(T0, 0, T_ASS_AGCH_USEC, "assignment (AGCH)", true);
return 0; return 0;
} }
@ -1041,7 +1041,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
} }
new_tbf->set_state(GPRS_RLCMAC_FLOW); new_tbf->set_state(GPRS_RLCMAC_FLOW);
/* stop pending assignment timer */ /* stop pending assignment timer */
new_tbf->stop_timer("control acked (DL-TBF)"); new_tbf->t_stop(T0, "control acked (DL-TBF)");
if ((new_tbf->state_flags & if ((new_tbf->state_flags &
(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) { (1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
new_tbf->state_flags &= new_tbf->state_flags &=

View File

@ -60,6 +60,7 @@ const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[] = {
}; };
static const struct value_string tbf_timers_names[] = { static const struct value_string tbf_timers_names[] = {
OSMO_VALUE_STRING(T0),
OSMO_VALUE_STRING(T3169), OSMO_VALUE_STRING(T3169),
OSMO_VALUE_STRING(T3191), OSMO_VALUE_STRING(T3191),
OSMO_VALUE_STRING(T3193), OSMO_VALUE_STRING(T3193),
@ -170,7 +171,6 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir) :
poll_fn(0), poll_fn(0),
poll_ts(0), poll_ts(0),
n3105(0), n3105(0),
T(0),
fT(0), fT(0),
num_fT_exp(0), num_fT_exp(0),
state(GPRS_RLCMAC_NULL), state(GPRS_RLCMAC_NULL),
@ -191,8 +191,7 @@ gprs_rlcmac_tbf::gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir) :
/* The classes of these members do not have proper constructors yet. /* The classes of these members do not have proper constructors yet.
* Just set them to 0 like talloc_zero did */ * Just set them to 0 like talloc_zero did */
memset(&pdch, 0, sizeof(pdch)); memset(&pdch, 0, sizeof(pdch));
memset(&timer, 0, sizeof(timer)); memset(&T, 0, sizeof(T));
memset(&T31, 0, sizeof(T31));
memset(&m_rlc, 0, sizeof(m_rlc)); memset(&m_rlc, 0, sizeof(m_rlc));
memset(&gsm_timer, 0, sizeof(gsm_timer)); memset(&gsm_timer, 0, sizeof(gsm_timer));
@ -472,7 +471,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
"be sure not to free in this state. PLEASE FIX!\n", "be sure not to free in this state. PLEASE FIX!\n",
get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, get_value_string(gprs_rlcmac_tbf_dl_ass_state_names,
tbf->dl_ass_state)); tbf->dl_ass_state));
tbf->stop_timer("freeing TBF");
tbf->stop_timers("freeing TBF"); tbf->stop_timers("freeing TBF");
/* TODO: Could/Should generate bssgp_tx_llc_discarded */ /* TODO: Could/Should generate bssgp_tx_llc_discarded */
tbf_unlink_pdch(tbf); tbf_unlink_pdch(tbf);
@ -538,27 +537,6 @@ const char *gprs_rlcmac_tbf::tbf_state_name[] = {
"RELEASING", "RELEASING",
}; };
void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
unsigned int seconds, unsigned int microseconds, const char *reason)
{
LOGPC(DRLCMAC, (T != tbf->T) ? LOGL_ERROR : LOGL_DEBUG,
"%s %sstarting timer T%u [%s] with %u sec. %u microsec.",
tbf_name(tbf), osmo_timer_pending(&tbf->timer) ? "re" : "", T, reason, seconds, microseconds);
if (T != tbf->T && osmo_timer_pending(&tbf->timer))
LOGPC(DRLCMAC, LOGL_ERROR, " while old timer T%u pending", tbf->T);
LOGPC(DRLCMAC, (T != tbf->T) ? LOGL_ERROR : LOGL_DEBUG, "\n");
tbf->T = T;
/* Tunning timers can be safely re-scheduled. */
tbf->timer.data = tbf;
tbf->timer.cb = &tbf_timer_cb;
osmo_timer_schedule(&tbf->timer, seconds, microseconds);
}
void gprs_rlcmac_tbf::t_stop(enum tbf_timers t, const char *reason) void gprs_rlcmac_tbf::t_stop(enum tbf_timers t, const char *reason)
{ {
if (t >= T_MAX) { if (t >= T_MAX) {
@ -579,10 +557,11 @@ bool gprs_rlcmac_tbf::timers_pending(enum tbf_timers t)
uint8_t i; uint8_t i;
if (t != T_MAX) if (t != T_MAX)
return osmo_timer_pending(&T31[t]); return osmo_timer_pending(&T[t]);
/* we don't start with T0 because it's internal timer which requires special handling */
for (i = T3169; i < T_MAX; i++) for (i = T3169; i < T_MAX; i++)
if (osmo_timer_pending(&T31[i])) if (osmo_timer_pending(&T[i]))
return true; return true;
return false; return false;
@ -591,19 +570,11 @@ bool gprs_rlcmac_tbf::timers_pending(enum tbf_timers t)
void gprs_rlcmac_tbf::stop_timers(const char *reason) void gprs_rlcmac_tbf::stop_timers(const char *reason)
{ {
uint8_t i; uint8_t i;
for (i = 0; i < T_MAX; i++) /* we start with T0 because timer reset does not require any special handling */
for (i = T0; i < T_MAX; i++)
t_stop((enum tbf_timers)i, reason); t_stop((enum tbf_timers)i, reason);
} }
void gprs_rlcmac_tbf::stop_timer(const char *reason)
{
if (osmo_timer_pending(&timer)) {
LOGPTBF(this, LOGL_DEBUG, "stopping timer T%u [%s]\n",
T, reason);
osmo_timer_del(&timer);
}
}
static inline void tbf_timeout_free(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t, bool run_diag) static inline void tbf_timeout_free(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t, bool run_diag)
{ {
LOGPTBF(tbf, LOGL_NOTICE, "%s timeout expired, freeing TBF\n", LOGPTBF(tbf, LOGL_NOTICE, "%s timeout expired, freeing TBF\n",
@ -629,33 +600,36 @@ void gprs_rlcmac_tbf::t_start(enum tbf_timers t, uint32_t sec, uint32_t microsec
get_value_string(tbf_timers_names, t), reason); get_value_string(tbf_timers_names, t), reason);
} }
if (!force && osmo_timer_pending(&T31[t])) if (!force && osmo_timer_pending(&T[t]))
return; return;
LOGPTBF(this, LOGL_DEBUG, "%sstarting timer %s [%s] with %u sec. %u microsec.\n", LOGPTBF(this, LOGL_DEBUG, "%sstarting timer %s [%s] with %u sec. %u microsec.\n",
osmo_timer_pending(&T31[t]) ? "re" : "", get_value_string(tbf_timers_names, t), reason, sec, microsec); osmo_timer_pending(&T[t]) ? "re" : "", get_value_string(tbf_timers_names, t), reason, sec, microsec);
T31[t].data = this; T[t].data = this;
switch(t) { switch(t) {
case T0:
T[t].cb = tbf_timer_cb;
break;
case T3169: case T3169:
T31[t].cb = cb_T3169; T[t].cb = cb_T3169;
break; break;
case T3191: case T3191:
T31[t].cb = cb_T3191; T[t].cb = cb_T3191;
break; break;
case T3193: case T3193:
T31[t].cb = cb_T3193; T[t].cb = cb_T3193;
break; break;
case T3195: case T3195:
T31[t].cb = cb_T3195; T[t].cb = cb_T3195;
break; break;
default: default:
LOGPTBF(this, LOGL_ERROR, "attempting to set callback for unknown timer %s [%s]\n", LOGPTBF(this, LOGL_ERROR, "attempting to set callback for unknown timer %s [%s]\n",
get_value_string(tbf_timers_names, t), reason); get_value_string(tbf_timers_names, t), reason);
} }
osmo_timer_schedule(&T31[t], sec, microsec); osmo_timer_schedule(&T[t], sec, microsec);
} }
int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts, int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
@ -1102,12 +1076,7 @@ static void tbf_timer_cb(void *_tbf)
void gprs_rlcmac_tbf::handle_timeout() void gprs_rlcmac_tbf::handle_timeout()
{ {
LOGPTBF(this, LOGL_DEBUG, "timer %u expired.\n", T); LOGPTBF(this, LOGL_DEBUG, "timer 0 expired.\n");
if (T) {
LOGPTBF(this, LOGL_ERROR, "%s timer expired in unknown mode: %u\n", T);
return;
}
/* assignment */ /* assignment */
if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) { if ((state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))) {
@ -1267,7 +1236,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
new_dl_tbf->set_state(GPRS_RLCMAC_FLOW); new_dl_tbf->set_state(GPRS_RLCMAC_FLOW);
tbf_assign_control_ts(new_dl_tbf); tbf_assign_control_ts(new_dl_tbf);
/* stop pending assignment timer */ /* stop pending assignment timer */
new_dl_tbf->stop_timer("assignment (DL-TBF)"); new_dl_tbf->t_stop(T0, "assignment (DL-TBF)");
} }
@ -1297,7 +1266,7 @@ struct msgb *gprs_rlcmac_tbf::create_packet_access_reject()
/* Start Tmr only if it is UL TBF */ /* Start Tmr only if it is UL TBF */
if (direction == GPRS_RLCMAC_UL_TBF) if (direction == GPRS_RLCMAC_UL_TBF)
tbf_timer_start(this, 0, Treject_pacch, "reject (PACCH)"); t_start(T0, 0, T_REJ_PACCH_USEC, "reject (PACCH)", true);
return msg; return msg;

View File

@ -39,9 +39,9 @@ class GprsMs;
* TBF instance * TBF instance
*/ */
#define Tassign_agch 0,200000 /* waiting after IMM.ASS confirm */ #define T_ASS_AGCH_USEC 200000 /* waiting after IMM.ASS confirm */
#define Tassign_pacch 2,0 /* timeout for pacch assigment */ #define T_ASS_PACCH_SEC 2 /* timeout for pacch assigment */
#define Treject_pacch 0,2000 /* timeout for tbf reject for PRR*/ #define T_REJ_PACCH_USEC 2000 /* timeout for tbf reject for PRR*/
enum gprs_rlcmac_tbf_state { enum gprs_rlcmac_tbf_state {
GPRS_RLCMAC_NULL = 0, /* new created TBF */ GPRS_RLCMAC_NULL = 0, /* new created TBF */
@ -139,6 +139,9 @@ enum tbf_egprs_ul_counters {
#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DRLCMACDL, level, "%s " fmt, tbf_name(tbf), ## args) #define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DRLCMACDL, level, "%s " fmt, tbf_name(tbf), ## args)
enum tbf_timers { enum tbf_timers {
/* internal assign/reject timer */
T0,
/* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */ /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
T3169, T3169,
@ -194,7 +197,6 @@ struct gprs_rlcmac_tbf {
int update(); int update();
void handle_timeout(); void handle_timeout();
void stop_timer(const char *reason);
void stop_timers(const char *reason); void stop_timers(const char *reason);
bool timers_pending(enum tbf_timers t); bool timers_pending(enum tbf_timers t);
void t_stop(enum tbf_timers t, const char *reason); void t_stop(enum tbf_timers t, const char *reason);
@ -267,9 +269,6 @@ struct gprs_rlcmac_tbf {
uint8_t n3105; /* N3105 counter */ uint8_t n3105; /* N3105 counter */
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
struct osmo_gsm_timer_list gsm_timer; struct osmo_gsm_timer_list gsm_timer;
unsigned int fT; /* fTxxxx number */ unsigned int fT; /* fTxxxx number */
unsigned int num_fT_exp; /* number of consecutive fT expirations */ unsigned int num_fT_exp; /* number of consecutive fT expirations */
@ -328,7 +327,7 @@ private:
LListHead<gprs_rlcmac_tbf> m_list; LListHead<gprs_rlcmac_tbf> m_list;
LListHead<gprs_rlcmac_tbf> m_ms_list; LListHead<gprs_rlcmac_tbf> m_ms_list;
bool m_egprs_enabled; bool m_egprs_enabled;
struct osmo_timer_list T31[T_MAX]; struct osmo_timer_list T[T_MAX];
mutable char m_name_buf[60]; mutable char m_name_buf[60];
}; };
@ -352,9 +351,6 @@ struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf); int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
unsigned int seconds, unsigned int microseconds, const char *reason);
inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
{ {
return state == rhs; return state == rhs;

View File

@ -484,7 +484,6 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf) void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf)
{ {
/* stop pending timer */ /* stop pending timer */
stop_timer("assignment (DL-TBF)");
stop_timers("assignment (DL-TBF)"); stop_timers("assignment (DL-TBF)");
/* check for downlink tbf: */ /* check for downlink tbf: */
@ -499,7 +498,7 @@ void gprs_rlcmac_dl_tbf::trigger_ass(struct gprs_rlcmac_tbf *old_tbf)
state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
/* start timer */ /* start timer */
tbf_timer_start(this, 0, Tassign_pacch, "assignment (PACCH)"); t_start(T0, T_ASS_PACCH_SEC, 0, "assignment (PACCH)", true);
} else { } else {
LOGPTBFDL(this, LOGL_DEBUG, "Send dowlink assignment on PCH, no TBF exist (IMSI=%s)\n", LOGPTBFDL(this, LOGL_DEBUG, "Send dowlink assignment on PCH, no TBF exist (IMSI=%s)\n",
imsi()); imsi());