summaryrefslogtreecommitdiffstats
path: root/src/gsm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsm')
-rw-r--r--src/gsm/lapd_core.c159
1 files changed, 87 insertions, 72 deletions
diff --git a/src/gsm/lapd_core.c b/src/gsm/lapd_core.c
index f7408e54..dcc21506 100644
--- a/src/gsm/lapd_core.c
+++ b/src/gsm/lapd_core.c
@@ -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;
}