LAPD: Moved timer handling into seperate functions

This commit is contained in:
Andreas Eversberg 2011-09-27 09:40:25 +02:00 committed by Harald Welte
parent af48bed556
commit 742fc79d58
1 changed files with 87 additions and 72 deletions

View File

@ -106,6 +106,11 @@
#define SBIT(a) (1 << a)
#define ALL_STATES 0xffffffff
static void lapd_t200_cb(void *data);
static void lapd_t203_cb(void *data);
static int lapd_send_i(struct lapd_msg_ctx *lctx, int line);
static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
/* UTILITY FUNCTIONS */
struct msgb *lapd_msgb_alloc(int length, const char *name)
@ -186,6 +191,38 @@ const char *lapd_state_names[] = {
};
static void lapd_start_t200(struct lapd_datalink *dl)
{
if (osmo_timer_pending(&dl->t200))
return;
LOGP(DLLAPD, LOGL_INFO, "start T200\n");
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
}
static void lapd_start_t203(struct lapd_datalink *dl)
{
if (osmo_timer_pending(&dl->t203))
return;
LOGP(DLLAPD, LOGL_INFO, "start T203\n");
osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
}
static void lapd_stop_t200(struct lapd_datalink *dl)
{
if (!osmo_timer_pending(&dl->t200))
return;
LOGP(DLLAPD, LOGL_INFO, "stop T200\n");
osmo_timer_del(&dl->t200);
}
static void lapd_stop_t203(struct lapd_datalink *dl)
{
if (!osmo_timer_pending(&dl->t203))
return;
LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
osmo_timer_del(&dl->t203);
}
static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
{
LOGP(DLLAPD, LOGL_INFO, "new state %s -> %s\n",
@ -193,10 +230,7 @@ static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
if (state != LAPD_STATE_MF_EST && dl->state == LAPD_STATE_MF_EST) {
/* stop T203 on leaving MF EST state, if running */
if (osmo_timer_pending(&dl->t203)) {
LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
osmo_timer_del(&dl->t203);
}
lapd_stop_t203(dl);
/* remove content res. (network side) on leaving MF EST state */
if (dl->cont_res) {
msgb_free(dl->cont_res);
@ -206,19 +240,12 @@ static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
/* start T203 on entering MF EST state, if enabled */
if ((dl->t203_sec || dl->t203_usec)
&& state == LAPD_STATE_MF_EST && dl->state != LAPD_STATE_MF_EST) {
LOGP(DLLAPD, LOGL_INFO, "start T203\n");
osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
}
&& state == LAPD_STATE_MF_EST && dl->state != LAPD_STATE_MF_EST)
lapd_start_t203(dl);
dl->state = state;
}
static void lapd_t200_cb(void *data);
static void lapd_t203_cb(void *data);
static int lapd_send_i(struct lapd_msg_ctx *lctx, int line);
static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
static void *tall_lapd_ctx = NULL;
/* init datalink instance and allocate history */
@ -288,9 +315,9 @@ void lapd_dl_reset(struct lapd_datalink *dl)
msgb_free(dl->rcv_buffer);
dl->rcv_buffer = NULL;
}
/* reset Timers */
osmo_timer_del(&dl->t200);
osmo_timer_del(&dl->t203);
/* stop Timers */
lapd_stop_t200(dl);
lapd_stop_t203(dl);
}
/* reset and de-allocate history buffer */
@ -519,7 +546,7 @@ static void lapd_t200_cb(void *data)
{
struct lapd_datalink *dl = data;
LOGP(DLLAPD, LOGL_INFO, "lapd_t200_cb(%p) state=%d\n", dl,
LOGP(DLLAPD, LOGL_INFO, "Timeout T200 (%p) state=%d\n", dl,
(int) dl->state);
switch (dl->state) {
@ -546,7 +573,7 @@ static void lapd_t200_cb(void *data)
/* increment re-transmission counter */
dl->retrans_ctr++;
/* restart T200 (PH-READY-TO-SEND) */
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
break;
case LAPD_STATE_DISC_SENT:
/* 5.4.4.3 */
@ -570,7 +597,7 @@ static void lapd_t200_cb(void *data)
/* increment re-transmission counter */
dl->retrans_ctr++;
/* restart T200 (PH-READY-TO-SEND) */
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
break;
case LAPD_STATE_MF_EST:
/* 5.5.7 */
@ -625,8 +652,7 @@ static void lapd_t200_cb(void *data)
}
}
/* restart T200 (PH-READY-TO-SEND) */
osmo_timer_schedule(&dl->t200, dl->t200_sec,
dl->t200_usec);
lapd_start_t200(dl);
} else {
/* send MDL ERROR INIDCATION to L3 */
mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
@ -649,7 +675,7 @@ static void lapd_t203_cb(void *data)
{
struct lapd_datalink *dl = data;
LOGP(DLLAPD, LOGL_INFO, "lapd_t203_cb(%p) state=%d\n", dl,
LOGP(DLLAPD, LOGL_INFO, "Timeout T203 (%p) state=%d\n", dl,
(int) dl->state);
if (dl->state != LAPD_STATE_MF_EST) {
@ -673,7 +699,7 @@ static void lapd_t203_cb(void *data)
lapd_send_rnr(&dl->lctx, 1, 1);
}
/* start T200 */
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
}
/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
@ -708,9 +734,8 @@ static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
* or an REJ with an N(R) equal to V(A). */
if ((!rej && nr != dl->v_ack)
|| (rej && nr == dl->v_ack)) {
LOGP(DLLAPD, LOGL_INFO, "reset t200\n");
t200_reset = 1;
osmo_timer_del(&dl->t200);
lapd_stop_t200(dl);
/* 5.5.3.1 Note 1 + 2 imply timer recovery cond. */
}
/* 5.7.4: N(R) sequence error
@ -727,31 +752,26 @@ static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
/* V(A) shall be set to the value of N(R) */
dl->v_ack = nr;
/* If T200 has been reset by the receipt of an I, RR or RNR frame,
/* If T200 has been stopped by the receipt of an I, RR or RNR frame,
* and if there are outstanding I frames, restart T200 */
if (t200_reset && !rej) {
if (dl->tx_hist[sub_mod(dl->v_send, 1, dl->range_hist)].msg) {
LOGP(DLLAPD, LOGL_INFO, "start T200, due to unacked I "
"frame(s)\n");
t200_start = 1;
osmo_timer_schedule(&dl->t200, dl->t200_sec,
dl->t200_usec);
lapd_start_t200(dl);
}
}
/* This also does a restart, when I or S frame is received */
/* Stop T203, if running */
if (osmo_timer_pending(&dl->t203)) {
osmo_timer_del(&dl->t203);
LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
}
lapd_stop_t203(dl);
/* Start T203, if T200 is not running in MF EST state, if enabled */
if (!osmo_timer_pending(&dl->t200)
&& (dl->t203_sec || dl->t203_usec)
&& (dl->state == LAPD_STATE_MF_EST)) {
LOGP(DLLAPD, LOGL_INFO, "start T203\n");
osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
lapd_start_t203(dl);
}
}
@ -827,8 +847,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
case LAPD_STATE_DISC_SENT:
/* 5.4.6.2 send DM with F=P */
lapd_send_dm(lctx);
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
msgb_free(msg);
return send_dl_simple(prim, op, lctx);
default:
@ -934,8 +954,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
}
break;
case LAPD_STATE_DISC_SENT:
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* go to idle state */
lapd_dl_flush_tx(dl);
lapd_dl_flush_send(dl);
@ -951,8 +971,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
msgb_free(msg);
return 0;
}
/* reset T200 */
osmo_timer_del(&dl->t200);
/* stop timer T200 */
lapd_stop_t200(dl);
/* go to idle state */
lapd_dl_newstate(dl, LAPD_STATE_IDLE);
rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);
@ -1033,8 +1053,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
LOGP(DLLAPD, LOGL_INFO, "DISC in SABM state\n");
/* 5.4.6.2 send DM with F=P */
lapd_send_dm(lctx);
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* go to idle state */
lapd_dl_newstate(dl, LAPD_STATE_IDLE);
msgb_free(msg);
@ -1056,8 +1076,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
}
/* send UA response */
lapd_send_ua(lctx, length, msg->l3h);
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* enter idle state, keep tx-buffer with UA response */
lapd_dl_newstate(dl, LAPD_STATE_IDLE);
/* send notification to L3 */
@ -1106,8 +1126,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
return 0;
case LAPD_STATE_DISC_SENT:
LOGP(DLLAPD, LOGL_INFO, "UA in disconnect state\n");
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* go to idle state */
lapd_dl_flush_tx(dl);
lapd_dl_flush_send(dl);
@ -1124,8 +1144,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
return 0;
}
LOGP(DLLAPD, LOGL_INFO, "UA in SABM state\n");
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* compare UA with SABME if contention resolution is applied */
if (dl->tx_hist[0].msg->len) {
if (length != (dl->tx_hist[0].msg->len)
@ -1250,8 +1270,8 @@ static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
"we leave that state\n");
/* V(S) to the N(R) in the RR frame */
dl->v_send = lctx->n_recv;
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* 5.5.7 Clear timer recovery condition */
lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
}
@ -1315,8 +1335,8 @@ static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
dl->peer_busy = 0;
/* V(S) and V(A) to the N(R) in the REJ frame */
dl->v_send = dl->v_ack = lctx->n_recv;
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* 5.5.3.2 */
if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
if (!dl->own_busy && !dl->seq_err_cond) {
@ -1358,8 +1378,8 @@ static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
dl->peer_busy = 0;
/* V(S) and V(A) to the N(R) in the REJ frame */
dl->v_send = dl->v_ack = lctx->n_recv;
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* stop Timer T200 */
lapd_stop_t200(dl);
/* 5.5.7 Clear timer recovery condition */
lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
} else {
@ -1682,7 +1702,7 @@ static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
/* Tramsmit and start T200 */
dl->send_ph_data_req(&nctx, msg);
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
return 0;
}
@ -1840,12 +1860,10 @@ static int lapd_send_i(struct lapd_msg_ctx *lctx, int line)
* frame, when the PH-READY-TO-SEND primitive is received from the
* physical layer., it shall be set. */
if (!osmo_timer_pending(&dl->t200)) {
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
/* reset Timer T203, if running */
if (osmo_timer_pending(&dl->t203)) {
LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
osmo_timer_del(&dl->t203);
}
/* stop Timer T203, if running */
lapd_stop_t203(dl);
/* start Timer T200 */
lapd_start_t200(dl);
}
dl->send_ph_data_req(&nctx, msg);
@ -1873,12 +1891,9 @@ static int lapd_susp_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
/* Clear transmit buffer, but keep send buffer */
lapd_dl_flush_tx(dl);
/* Stop timers */
if (osmo_timer_pending(&dl->t203)) {
LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
osmo_timer_del(&dl->t203);
}
osmo_timer_del(&dl->t200);
/* Stop timers (there is no state change, so we must stop all timers */
lapd_stop_t200(dl);
lapd_stop_t203(dl);
msgb_free(msg);
@ -1946,7 +1961,7 @@ static int lapd_res_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
/* Tramsmit and start T200 */
dl->send_ph_data_req(&nctx, msg);
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
return 0;
}
@ -1962,9 +1977,9 @@ static int lapd_rel_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
if (dp->u.rel_req.mode) {
LOGP(DLLAPD, LOGL_INFO, "perform local release\n");
msgb_free(msg);
/* reset Timer T200 */
osmo_timer_del(&dl->t200);
/* enter idle state */
/* stop Timer T200 */
lapd_stop_t200(dl);
/* enter idle state, T203 is stopped here, if running */
lapd_dl_newstate(dl, LAPD_STATE_IDLE);
/* flush buffers */
lapd_dl_flush_tx(dl);
@ -2010,7 +2025,7 @@ static int lapd_rel_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
/* Tramsmit and start T200 */
dl->send_ph_data_req(&nctx, msg);
osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
lapd_start_t200(dl);
return 0;
}