blob: cf25f3de0102a1497ca3e58e67a97bffe2d722d3 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file lapd_core.c
2 * LAPD core implementation */
3/*
Harald Welte00b2faf2020-05-02 19:56:36 +02004 * (C) 2010-2020 by Harald Welte <laforge@gnumonks.org>
rootaf48bed2011-09-26 11:23:06 +02005 * (C) 2010-2011 by Andreas Eversberg <jolly@eversberg.eu>
6 *
7 * All Rights Reserved
8 *
Harald Weltee08da972017-11-13 01:00:26 +09009 * SPDX-License-Identifier: GPL-2.0+
10 *
rootaf48bed2011-09-26 11:23:06 +020011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 *
25 */
26
27/*! \addtogroup lapd
28 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020029 *
30 * Osmocom LAPD core, used for Q.921, LAPDm and others.
31 *
rootaf48bed2011-09-26 11:23:06 +020032 * Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
33 *
34 * RX data is stored in the rcv_buffer (pointer). If the message is complete, it
35 * is removed from rcv_buffer pointer and forwarded to L3. If the RX data is
36 * received while there is an incomplete rcv_buffer, it is appended to it.
37 *
38 * TX data is stored in the send_queue first. When transmitting a frame,
39 * the first message in the send_queue is moved to the send_buffer. There it
40 * resides until all fragments are acknowledged. Fragments to be sent by I
41 * frames are stored in the tx_hist buffer for resend, if required. Also the
42 * current fragment is copied into the tx_queue. There it resides until it is
43 * forwarded to layer 1.
44 *
45 * In case we have SAPI 0, we only have a window size of 1, so the unack-
46 * nowledged message resides always in the send_buffer. In case of a suspend,
47 * it can be written back to the first position of the send_queue.
48 *
49 * The layer 1 normally sends a PH-READY-TO-SEND. But because we use
50 * asynchronous transfer between layer 1 and layer 2 (serial link), we must
51 * send a frame before layer 1 reaches the right timeslot to send it. So we
52 * move the tx_queue to layer 1 when there is not already a pending frame, and
53 * wait until acknowledge after the frame has been sent. If we receive an
54 * acknowledge, we can send the next frame from the buffer, if any.
55 *
56 * The moving of tx_queue to layer 1 may also trigger T200, if desired. Also it
57 * will trigger next I frame, if possible.
58 *
59 * T203 is optional. It will be stated when entering MF EST state. It will also
60 * be started when I or S frame is received in that state . It will be
61 * restarted in the lapd_acknowledge() function, in case outstanding frames
62 * will not trigger T200. It will be stoped, when T200 is started in MF EST
63 * state. It will also be stoped when leaving MF EST state.
64 *
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020065 * \file lapd_core.c
rootaf48bed2011-09-26 11:23:06 +020066 */
67
68/* Enable this to test content resolution on network side:
69 * - The first SABM is received, UA is dropped.
70 * - The phone repeats SABM, but it's content is wrong, so it is ignored
71 * - The phone repeats SABM again, content is right, so UA is sent.
72 */
73//#define TEST_CONTENT_RESOLUTION_NETWORK
74
75#include <stdio.h>
76#include <stdint.h>
77#include <string.h>
78#include <errno.h>
rootaf48bed2011-09-26 11:23:06 +020079
80#include <osmocom/core/logging.h>
81#include <osmocom/core/timer.h>
82#include <osmocom/core/msgb.h>
83#include <osmocom/core/utils.h>
84#include <osmocom/core/talloc.h>
85#include <osmocom/gsm/lapd_core.h>
Max2f0b0c92017-01-12 16:47:13 +010086#include <osmocom/gsm/rsl.h>
rootaf48bed2011-09-26 11:23:06 +020087
88/* TS 04.06 Table 4 / Section 3.8.1 */
89#define LAPD_U_SABM 0x7
90#define LAPD_U_SABME 0xf
91#define LAPD_U_DM 0x3
92#define LAPD_U_UI 0x0
93#define LAPD_U_DISC 0x8
94#define LAPD_U_UA 0xC
95#define LAPD_U_FRMR 0x11
96
97#define LAPD_S_RR 0x0
98#define LAPD_S_RNR 0x1
99#define LAPD_S_REJ 0x2
100
101#define CR_USER2NET_CMD 0
102#define CR_USER2NET_RESP 1
103#define CR_NET2USER_CMD 1
104#define CR_NET2USER_RESP 0
105
106#define LAPD_HEADROOM 56
Harald Welte8617d092020-07-03 19:28:53 +0200107#define LAPD_TAILROOM 16
rootaf48bed2011-09-26 11:23:06 +0200108
109#define SBIT(a) (1 << a)
110#define ALL_STATES 0xffffffff
111
Andreas Eversberg742fc792011-09-27 09:40:25 +0200112static void lapd_t200_cb(void *data);
113static void lapd_t203_cb(void *data);
114static int lapd_send_i(struct lapd_msg_ctx *lctx, int line);
115static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
116
rootaf48bed2011-09-26 11:23:06 +0200117/* UTILITY FUNCTIONS */
118
119struct msgb *lapd_msgb_alloc(int length, const char *name)
120{
121 /* adding space for padding, FIXME: add as an option */
122 if (length < 21)
123 length = 21;
Harald Welte8617d092020-07-03 19:28:53 +0200124 return msgb_alloc_headroom(length + LAPD_HEADROOM + LAPD_TAILROOM, LAPD_HEADROOM, name);
rootaf48bed2011-09-26 11:23:06 +0200125}
126
127static inline uint8_t do_mod(uint8_t x, uint8_t m)
128{
129 return x & (m - 1);
130}
131
132static inline uint8_t inc_mod(uint8_t x, uint8_t m)
133{
134 return (x + 1) & (m - 1);
135}
136
137static inline uint8_t add_mod(uint8_t x, uint8_t y, uint8_t m)
138{
139 return (x + y) & (m - 1);
140}
141
142static inline uint8_t sub_mod(uint8_t x, uint8_t y, uint8_t m)
143{
144 return (x - y) & (m - 1); /* handle negative results correctly */
145}
146
147static void lapd_dl_flush_send(struct lapd_datalink *dl)
148{
149 struct msgb *msg;
150
151 /* Flush send-queue */
152 while ((msg = msgb_dequeue(&dl->send_queue)))
153 msgb_free(msg);
154
155 /* Clear send-buffer */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200156 msgb_free(dl->send_buffer);
157 dl->send_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +0200158}
159
160static void lapd_dl_flush_hist(struct lapd_datalink *dl)
161{
162 unsigned int i;
163
Harald Weltef92e44c2016-08-01 00:24:19 +0200164 if (!dl->range_hist || !dl->tx_hist)
Harald Welte0ee90f82016-07-03 20:45:21 +0200165 return;
166
rootaf48bed2011-09-26 11:23:06 +0200167 for (i = 0; i < dl->range_hist; i++) {
168 if (dl->tx_hist[i].msg) {
169 msgb_free(dl->tx_hist[i].msg);
170 dl->tx_hist[i].msg = NULL;
171 }
172 }
173}
174
175static void lapd_dl_flush_tx(struct lapd_datalink *dl)
176{
177 struct msgb *msg;
178
179 while ((msg = msgb_dequeue(&dl->tx_queue)))
180 msgb_free(msg);
181 lapd_dl_flush_hist(dl);
182}
183
184/* Figure B.2/Q.921 */
Harald Weltec733d142017-03-15 10:20:51 +0100185const struct value_string lapd_state_names[] = {
186 OSMO_VALUE_STRING(LAPD_STATE_NULL),
187 OSMO_VALUE_STRING(LAPD_STATE_TEI_UNASS),
188 OSMO_VALUE_STRING(LAPD_STATE_ASS_TEI_WAIT),
189 OSMO_VALUE_STRING(LAPD_STATE_EST_TEI_WAIT),
190 OSMO_VALUE_STRING(LAPD_STATE_IDLE),
191 OSMO_VALUE_STRING(LAPD_STATE_SABM_SENT),
192 OSMO_VALUE_STRING(LAPD_STATE_DISC_SENT),
193 OSMO_VALUE_STRING(LAPD_STATE_MF_EST),
194 OSMO_VALUE_STRING(LAPD_STATE_TIMER_RECOV),
195 { 0, NULL }
rootaf48bed2011-09-26 11:23:06 +0200196};
197
Harald Weltec733d142017-03-15 10:20:51 +0100198static inline const char *lapd_state_name(enum lapd_state state)
199{
200 return get_value_string(lapd_state_names, state);
201}
202
Andreas Eversberg742fc792011-09-27 09:40:25 +0200203static void lapd_start_t200(struct lapd_datalink *dl)
204{
205 if (osmo_timer_pending(&dl->t200))
206 return;
Harald Welte00b2faf2020-05-02 19:56:36 +0200207 LOGDL(dl, LOGL_INFO, "start T200 (timeout=%d.%06ds)\n",
208 dl->t200_sec, dl->t200_usec);
Andreas Eversberg742fc792011-09-27 09:40:25 +0200209 osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
210}
211
212static void lapd_start_t203(struct lapd_datalink *dl)
213{
214 if (osmo_timer_pending(&dl->t203))
215 return;
Harald Welte00b2faf2020-05-02 19:56:36 +0200216 LOGDL(dl, LOGL_INFO, "start T203\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +0200217 osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
218}
219
220static void lapd_stop_t200(struct lapd_datalink *dl)
221{
222 if (!osmo_timer_pending(&dl->t200))
223 return;
Harald Welte00b2faf2020-05-02 19:56:36 +0200224 LOGDL(dl, LOGL_INFO, "stop T200\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +0200225 osmo_timer_del(&dl->t200);
226}
227
228static void lapd_stop_t203(struct lapd_datalink *dl)
229{
230 if (!osmo_timer_pending(&dl->t203))
231 return;
Harald Welte00b2faf2020-05-02 19:56:36 +0200232 LOGDL(dl, LOGL_INFO, "stop T203\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +0200233 osmo_timer_del(&dl->t203);
234}
235
rootaf48bed2011-09-26 11:23:06 +0200236static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
237{
Harald Welte00b2faf2020-05-02 19:56:36 +0200238 LOGDL(dl, LOGL_INFO, "new state %s -> %s\n",
239 lapd_state_name(dl->state), lapd_state_name(state));
rootaf48bed2011-09-26 11:23:06 +0200240
241 if (state != LAPD_STATE_MF_EST && dl->state == LAPD_STATE_MF_EST) {
242 /* stop T203 on leaving MF EST state, if running */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200243 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200244 /* remove content res. (network side) on leaving MF EST state */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200245 msgb_free(dl->cont_res);
246 dl->cont_res = NULL;
rootaf48bed2011-09-26 11:23:06 +0200247 }
248
249 /* start T203 on entering MF EST state, if enabled */
250 if ((dl->t203_sec || dl->t203_usec)
Andreas Eversberg742fc792011-09-27 09:40:25 +0200251 && state == LAPD_STATE_MF_EST && dl->state != LAPD_STATE_MF_EST)
252 lapd_start_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200253
254 dl->state = state;
255}
256
Harald Welte00b2faf2020-05-02 19:56:36 +0200257void *tall_lapd_ctx = NULL;
rootaf48bed2011-09-26 11:23:06 +0200258
Harald Welte00b2faf2020-05-02 19:56:36 +0200259/*! Initialize LAPD datalink instance and allocate history
260 * \param[in] dl caller-allocated datalink structure
261 * \param[in] k maximum number of unacknowledged frames
262 * \param[in] v_range range of sequence numbers
263 * \param[in] maxf maximum frame size (after defragmentation)
264 * \param[in] name human-readable name for this LAPD datalink */
265void lapd_dl_init2(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf,
266 const char *name)
rootaf48bed2011-09-26 11:23:06 +0200267{
268 int m;
269
270 memset(dl, 0, sizeof(*dl));
271 INIT_LLIST_HEAD(&dl->send_queue);
272 INIT_LLIST_HEAD(&dl->tx_queue);
273 dl->reestablish = 1;
274 dl->n200_est_rel = 3;
275 dl->n200 = 3;
276 dl->t200_sec = 1;
277 dl->t200_usec = 0;
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +0200278 osmo_timer_setup(&dl->t200, lapd_t200_cb, dl);
rootaf48bed2011-09-26 11:23:06 +0200279 dl->t203_sec = 10;
280 dl->t203_usec = 0;
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +0200281 osmo_timer_setup(&dl->t203, lapd_t203_cb, dl);
rootaf48bed2011-09-26 11:23:06 +0200282 dl->maxf = maxf;
283 if (k > v_range - 1)
284 k = v_range - 1;
285 dl->k = k;
286 dl->v_range = v_range;
287
288 /* Calculate modulo for history array:
289 * - The history range must be at least k+1.
290 * - The history range must be 2^x, where x is as low as possible.
291 */
292 k++;
293 for (m = 0x80; m; m >>= 1) {
294 if ((m & k)) {
295 if (k > m)
296 m <<= 1;
297 dl->range_hist = m;
298 break;
299 }
300 }
301
Harald Welte00b2faf2020-05-02 19:56:36 +0200302 if (!tall_lapd_ctx) {
303 tall_lapd_ctx = talloc_named_const(NULL, 1, "lapd context");
304 OSMO_ASSERT(tall_lapd_ctx);
305 }
306
307 talloc_free(dl->name);
308 if (name)
309 dl->name = talloc_strdup(tall_lapd_ctx, name);
310 else
311 dl->name = talloc_asprintf(tall_lapd_ctx, "dl=%p", dl);
312
313 LOGDL(dl, LOGL_INFO, "Init DL layer: sequence range = %d, k = %d, "
314 "history range = %d\n", dl->v_range, dl->k, dl->range_hist);
rootaf48bed2011-09-26 11:23:06 +0200315
316 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
317
Holger Hans Peter Freyther10f0bde2014-02-09 20:03:38 +0100318 dl->tx_hist = talloc_zero_array(tall_lapd_ctx,
319 struct lapd_history, dl->range_hist);
rootaf48bed2011-09-26 11:23:06 +0200320}
321
Harald Welte00b2faf2020-05-02 19:56:36 +0200322/*! Initialize LAPD datalink instance and allocate history
323 * \param[in] dl caller-allocated datalink structure
324 * \param[in] k maximum number of unacknowledged frames
325 * \param[in] v_range range of sequence numbers
326 * \param[in] maxf maximum frame size (after defragmentation) */
327void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf)
328{
329 lapd_dl_init2(dl, k, v_range, maxf, NULL);
330}
331
332void lapd_dl_set_name(struct lapd_datalink *dl, const char *name)
333{
334 if (!name)
335 return;
336 osmo_talloc_replace_string(tall_lapd_ctx, &dl->name, name);
337}
338
rootaf48bed2011-09-26 11:23:06 +0200339/* reset to IDLE state */
340void lapd_dl_reset(struct lapd_datalink *dl)
341{
Harald Welteef5b9b62020-06-07 22:29:53 +0200342 LOGDL(dl, LOGL_INFO, "Resetting LAPD instance\n");
Jean-Francois Dionne893979c2017-03-02 10:45:53 -0500343 /* enter idle state (and remove eventual cont_res) */
344 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
rootaf48bed2011-09-26 11:23:06 +0200345 /* flush buffer */
346 lapd_dl_flush_tx(dl);
347 lapd_dl_flush_send(dl);
348 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200349 msgb_free(dl->rcv_buffer);
350 dl->rcv_buffer = NULL;
Andreas Eversberg742fc792011-09-27 09:40:25 +0200351 /* stop Timers */
352 lapd_stop_t200(dl);
353 lapd_stop_t203(dl);
Jean-Francois Dionned78c9732017-03-06 14:33:20 -0500354 if (dl->state == LAPD_STATE_IDLE)
355 return;
Jean-Francois Dionned78c9732017-03-06 14:33:20 -0500356 /* enter idle state (and remove eventual cont_res) */
357 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
rootaf48bed2011-09-26 11:23:06 +0200358}
359
360/* reset and de-allocate history buffer */
361void lapd_dl_exit(struct lapd_datalink *dl)
362{
363 /* free all ressources except history buffer */
364 lapd_dl_reset(dl);
Ivan Kluchnikovb9759db2017-05-11 15:19:23 +0300365
366 /* enter null state */
367 lapd_dl_newstate(dl, LAPD_STATE_NULL);
368
rootaf48bed2011-09-26 11:23:06 +0200369 /* free history buffer list */
370 talloc_free(dl->tx_hist);
Holger Hans Peter Freytherf5a079f2013-05-08 18:42:39 +0200371 dl->tx_hist = NULL;
Harald Welte00b2faf2020-05-02 19:56:36 +0200372 talloc_free(dl->name);
373 dl->name = NULL;
rootaf48bed2011-09-26 11:23:06 +0200374}
375
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200376/*! Set the \ref lapdm_mode of a LAPDm entity */
rootaf48bed2011-09-26 11:23:06 +0200377int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode)
378{
379 switch (mode) {
380 case LAPD_MODE_USER:
381 dl->cr.loc2rem.cmd = CR_USER2NET_CMD;
382 dl->cr.loc2rem.resp = CR_USER2NET_RESP;
383 dl->cr.rem2loc.cmd = CR_NET2USER_CMD;
384 dl->cr.rem2loc.resp = CR_NET2USER_RESP;
385 break;
386 case LAPD_MODE_NETWORK:
387 dl->cr.loc2rem.cmd = CR_NET2USER_CMD;
388 dl->cr.loc2rem.resp = CR_NET2USER_RESP;
389 dl->cr.rem2loc.cmd = CR_USER2NET_CMD;
390 dl->cr.rem2loc.resp = CR_USER2NET_RESP;
391 break;
392 default:
393 return -EINVAL;
394 }
395 dl->mode = mode;
396
397 return 0;
398}
399
400/* send DL message with optional msgb */
401static int send_dl_l3(uint8_t prim, uint8_t op, struct lapd_msg_ctx *lctx,
402 struct msgb *msg)
403{
404 struct lapd_datalink *dl = lctx->dl;
405 struct osmo_dlsap_prim dp;
406
407 osmo_prim_init(&dp.oph, 0, prim, op, msg);
408 return dl->send_dlsap(&dp, lctx);
409}
410
411/* send simple DL message */
412static inline int send_dl_simple(uint8_t prim, uint8_t op,
413 struct lapd_msg_ctx *lctx)
414{
Pau Espin Pedrol9dd3bf02016-02-29 08:49:22 -0500415 return send_dl_l3(prim, op, lctx, NULL);
rootaf48bed2011-09-26 11:23:06 +0200416}
417
418/* send MDL-ERROR INDICATION */
419static int mdl_error(uint8_t cause, struct lapd_msg_ctx *lctx)
420{
421 struct lapd_datalink *dl = lctx->dl;
422 struct osmo_dlsap_prim dp;
423
Harald Welte00b2faf2020-05-02 19:56:36 +0200424 LOGDL(dl, LOGL_NOTICE,
425 "sending MDL-ERROR-IND cause %d from state %s\n",
426 cause, lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200427 osmo_prim_init(&dp.oph, 0, PRIM_MDL_ERROR, PRIM_OP_INDICATION, NULL);
428 dp.u.error_ind.cause = cause;
429 return dl->send_dlsap(&dp, lctx);
430}
431
432/* send UA response */
433static int lapd_send_ua(struct lapd_msg_ctx *lctx, uint8_t len, uint8_t *data)
434{
435 struct msgb *msg = lapd_msgb_alloc(len, "LAPD UA");
436 struct lapd_msg_ctx nctx;
437 struct lapd_datalink *dl = lctx->dl;
438
439 memcpy(&nctx, lctx, sizeof(nctx));
440 msg->l3h = msgb_put(msg, len);
441 if (len)
442 memcpy(msg->l3h, data, len);
443 /* keep nctx.ldp */
444 /* keep nctx.sapi */
445 /* keep nctx.tei */
446 nctx.cr = dl->cr.loc2rem.resp;
447 nctx.format = LAPD_FORM_U;
448 nctx.s_u = LAPD_U_UA;
449 /* keep nctx.p_f */
450 nctx.length = len;
451 nctx.more = 0;
452
453 return dl->send_ph_data_req(&nctx, msg);
454}
455
456/* send DM response */
457static int lapd_send_dm(struct lapd_msg_ctx *lctx)
458{
459 struct msgb *msg = lapd_msgb_alloc(0, "LAPD DM");
460 struct lapd_msg_ctx nctx;
461 struct lapd_datalink *dl = lctx->dl;
462
463 memcpy(&nctx, lctx, sizeof(nctx));
464 /* keep nctx.ldp */
465 /* keep nctx.sapi */
466 /* keep nctx.tei */
467 nctx.cr = dl->cr.loc2rem.resp;
468 nctx.format = LAPD_FORM_U;
469 nctx.s_u = LAPD_U_DM;
470 /* keep nctx.p_f */
471 nctx.length = 0;
472 nctx.more = 0;
473
474 return dl->send_ph_data_req(&nctx, msg);
475}
476
477/* send RR response / command */
478static int lapd_send_rr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
479{
480 struct msgb *msg = lapd_msgb_alloc(0, "LAPD RR");
481 struct lapd_msg_ctx nctx;
482 struct lapd_datalink *dl = lctx->dl;
483
484 memcpy(&nctx, lctx, sizeof(nctx));
485 /* keep nctx.ldp */
486 /* keep nctx.sapi */
487 /* keep nctx.tei */
488 nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
489 nctx.format = LAPD_FORM_S;
490 nctx.s_u = LAPD_S_RR;
491 nctx.p_f = f_bit;
492 nctx.n_recv = dl->v_recv;
493 nctx.length = 0;
494 nctx.more = 0;
495
496 return dl->send_ph_data_req(&nctx, msg);
497}
498
499/* send RNR response / command */
500static int lapd_send_rnr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
501{
502 struct msgb *msg = lapd_msgb_alloc(0, "LAPD RNR");
503 struct lapd_msg_ctx nctx;
504 struct lapd_datalink *dl = lctx->dl;
505
506 memcpy(&nctx, lctx, sizeof(nctx));
507 /* keep nctx.ldp */
508 /* keep nctx.sapi */
509 /* keep nctx.tei */
510 nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
511 nctx.format = LAPD_FORM_S;
512 nctx.s_u = LAPD_S_RNR;
513 nctx.p_f = f_bit;
514 nctx.n_recv = dl->v_recv;
515 nctx.length = 0;
516 nctx.more = 0;
517
518 return dl->send_ph_data_req(&nctx, msg);
519}
520
521/* send REJ response */
522static int lapd_send_rej(struct lapd_msg_ctx *lctx, uint8_t f_bit)
523{
524 struct msgb *msg = lapd_msgb_alloc(0, "LAPD REJ");
525 struct lapd_msg_ctx nctx;
526 struct lapd_datalink *dl = lctx->dl;
527
528 memcpy(&nctx, lctx, sizeof(nctx));
529 /* keep nctx.ldp */
530 /* keep nctx.sapi */
531 /* keep nctx.tei */
532 nctx.cr = dl->cr.loc2rem.resp;
533 nctx.format = LAPD_FORM_S;
534 nctx.s_u = LAPD_S_REJ;
535 nctx.p_f = f_bit;
536 nctx.n_recv = dl->v_recv;
537 nctx.length = 0;
538 nctx.more = 0;
539
540 return dl->send_ph_data_req(&nctx, msg);
541}
542
543/* resend SABM or DISC message */
544static int lapd_send_resend(struct lapd_datalink *dl)
545{
546 struct msgb *msg;
547 uint8_t h = do_mod(dl->v_send, dl->range_hist);
548 int length = dl->tx_hist[h].msg->len;
549 struct lapd_msg_ctx nctx;
550
551 /* assemble message */
552 memcpy(&nctx, &dl->lctx, sizeof(nctx));
553 /* keep nctx.ldp */
554 /* keep nctx.sapi */
555 /* keep nctx.tei */
556 nctx.cr = dl->cr.loc2rem.cmd;
557 nctx.format = LAPD_FORM_U;
558 if (dl->state == LAPD_STATE_SABM_SENT)
559 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
560 else
561 nctx.s_u = LAPD_U_DISC;
562 nctx.p_f = 1;
563 nctx.length = length;
564 nctx.more = 0;
565
566 /* Resend SABM/DISC from tx_hist */
567 msg = lapd_msgb_alloc(length, "LAPD resend");
568 msg->l3h = msgb_put(msg, length);
569 if (length)
570 memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
571
572 return dl->send_ph_data_req(&nctx, msg);
573}
574
575/* reestablish link */
576static int lapd_reestablish(struct lapd_datalink *dl)
577{
578 struct osmo_dlsap_prim dp;
579 struct msgb *msg;
580
Harald Welte00b2faf2020-05-02 19:56:36 +0200581 LOGDL(dl, LOGL_DEBUG, "LAPD reestablish\n");
Philipp Maier08177d32016-12-08 17:23:26 +0100582
rootaf48bed2011-09-26 11:23:06 +0200583 msg = lapd_msgb_alloc(0, "DUMMY");
584 osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg);
Pau Espin Pedrola99e1102017-12-08 14:30:47 +0100585
rootaf48bed2011-09-26 11:23:06 +0200586 return lapd_est_req(&dp, &dl->lctx);
587}
588
589/* Timer callback on T200 expiry */
590static void lapd_t200_cb(void *data)
591{
592 struct lapd_datalink *dl = data;
593
Harald Welte00b2faf2020-05-02 19:56:36 +0200594 LOGDL(dl, LOGL_INFO, "Timeout T200 state=%s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200595
596 switch (dl->state) {
597 case LAPD_STATE_SABM_SENT:
598 /* 5.4.1.3 */
Harald Welte7a569522019-06-02 22:37:21 +0200599 if (dl->retrans_ctr >= dl->n200_est_rel + 1) {
rootaf48bed2011-09-26 11:23:06 +0200600 /* flush tx and send buffers */
601 lapd_dl_flush_tx(dl);
602 lapd_dl_flush_send(dl);
603 /* go back to idle state */
604 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
605 /* NOTE: we must not change any other states or buffers
606 * and queues, since we may reconnect after handover
607 * failure. the buffered messages is replaced there */
Philipp Maier6b986c22017-02-01 12:00:45 +0100608 /* send MDL ERROR INIDCATION to L3 */
609 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
Philipp Maierd9f61292016-12-08 10:45:06 +0100610 /* send RELEASE INDICATION to L3 */
611 send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
612 &dl->lctx);
rootaf48bed2011-09-26 11:23:06 +0200613 break;
614 }
615 /* retransmit SABM command */
616 lapd_send_resend(dl);
617 /* increment re-transmission counter */
618 dl->retrans_ctr++;
619 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200620 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200621 break;
622 case LAPD_STATE_DISC_SENT:
623 /* 5.4.4.3 */
Harald Welte7a569522019-06-02 22:37:21 +0200624 if (dl->retrans_ctr >= dl->n200_est_rel + 1) {
rootaf48bed2011-09-26 11:23:06 +0200625 /* send MDL ERROR INIDCATION to L3 */
626 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
Philipp Maier6b986c22017-02-01 12:00:45 +0100627 /* send RELEASE INDICATION to L3 */
628 send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
rootaf48bed2011-09-26 11:23:06 +0200629 /* flush tx and send buffers */
630 lapd_dl_flush_tx(dl);
631 lapd_dl_flush_send(dl);
632 /* go back to idle state */
633 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
634 /* NOTE: we must not change any other states or buffers
635 * and queues, since we may reconnect after handover
636 * failure. the buffered messages is replaced there */
637 break;
638 }
639 /* retransmit DISC command */
640 lapd_send_resend(dl);
641 /* increment re-transmission counter */
642 dl->retrans_ctr++;
643 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200644 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200645 break;
646 case LAPD_STATE_MF_EST:
647 /* 5.5.7 */
648 dl->retrans_ctr = 0;
649 lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
650 /* fall through */
651 case LAPD_STATE_TIMER_RECOV:
652 dl->retrans_ctr++;
Harald Welte7a569522019-06-02 22:37:21 +0200653 if (dl->retrans_ctr <= dl->n200) {
rootaf48bed2011-09-26 11:23:06 +0200654 uint8_t vs = sub_mod(dl->v_send, 1, dl->v_range);
655 uint8_t h = do_mod(vs, dl->range_hist);
656 /* retransmit I frame (V_s-1) with P=1, if any */
657 if (dl->tx_hist[h].msg) {
658 struct msgb *msg;
659 int length = dl->tx_hist[h].msg->len;
660 struct lapd_msg_ctx nctx;
661
Harald Welte00b2faf2020-05-02 19:56:36 +0200662 LOGDL(dl, LOGL_INFO, "retransmit last frame V(S)=%d\n", vs);
rootaf48bed2011-09-26 11:23:06 +0200663 /* Create I frame (segment) from tx_hist */
664 memcpy(&nctx, &dl->lctx, sizeof(nctx));
665 /* keep nctx.ldp */
666 /* keep nctx.sapi */
667 /* keep nctx.tei */
668 nctx.cr = dl->cr.loc2rem.cmd;
669 nctx.format = LAPD_FORM_I;
670 nctx.p_f = 1;
671 nctx.n_send = vs;
672 nctx.n_recv = dl->v_recv;
673 nctx.length = length;
674 nctx.more = dl->tx_hist[h].more;
675 msg = lapd_msgb_alloc(length, "LAPD I resend");
676 msg->l3h = msgb_put(msg, length);
677 memcpy(msg->l3h, dl->tx_hist[h].msg->data,
678 length);
679 dl->send_ph_data_req(&nctx, msg);
680 } else {
681 /* OR send appropriate supervision frame with P=1 */
682 if (!dl->own_busy && !dl->seq_err_cond) {
683 lapd_send_rr(&dl->lctx, 1, 1);
684 /* NOTE: In case of sequence error
685 * condition, the REJ frame has been
686 * transmitted when entering the
687 * condition, so it has not be done
688 * here
689 */
690 } else if (dl->own_busy) {
691 lapd_send_rnr(&dl->lctx, 1, 1);
692 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +0200693 LOGDL(dl, LOGL_INFO, "unhandled, pls. fix\n");
rootaf48bed2011-09-26 11:23:06 +0200694 }
695 }
696 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200697 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200698 } else {
699 /* send MDL ERROR INIDCATION to L3 */
700 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
701 /* reestablish */
702 if (!dl->reestablish)
703 break;
Harald Welte00b2faf2020-05-02 19:56:36 +0200704 LOGDL(dl, LOGL_NOTICE, "N200+1 reached, performingreestablishment\n");
rootaf48bed2011-09-26 11:23:06 +0200705 lapd_reestablish(dl);
706 }
707 break;
708 default:
Harald Welte00b2faf2020-05-02 19:56:36 +0200709 LOGDL(dl, LOGL_INFO, "T200 expired in unexpected dl->state %s)\n",
710 lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200711 }
712}
713
714/* Timer callback on T203 expiry */
715static void lapd_t203_cb(void *data)
716{
717 struct lapd_datalink *dl = data;
718
Harald Welte00b2faf2020-05-02 19:56:36 +0200719 LOGDL(dl, LOGL_INFO, "Timeout T203 state=%s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200720
721 if (dl->state != LAPD_STATE_MF_EST) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200722 LOGDL(dl, LOGL_ERROR, "T203 fired outside MF EST state, please fix!\n");
rootaf48bed2011-09-26 11:23:06 +0200723 return;
724 }
725
726 /* set retransmission counter to 0 */
727 dl->retrans_ctr = 0;
728 /* enter timer recovery state */
729 lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
730 /* transmit a supervisory command with P bit set to 1 as follows: */
731 if (!dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200732 LOGDL(dl, LOGL_INFO, "transmit an RR poll command\n");
rootaf48bed2011-09-26 11:23:06 +0200733 /* Send RR with P=1 */
734 lapd_send_rr(&dl->lctx, 1, 1);
735 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +0200736 LOGDL(dl, LOGL_INFO, "transmit an RNR poll command\n");
rootaf48bed2011-09-26 11:23:06 +0200737 /* Send RNR with P=1 */
738 lapd_send_rnr(&dl->lctx, 1, 1);
739 }
740 /* start T200 */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200741 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200742}
743
744/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
745static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
746{
747 struct lapd_datalink *dl = lctx->dl;
748 uint8_t nr = lctx->n_recv;
Holger Hans Peter Freytherfb6a2e22012-03-16 10:35:38 +0100749 int s = 0, rej = 0, t200_reset = 0;
rootaf48bed2011-09-26 11:23:06 +0200750 int i, h;
751
752 /* supervisory frame ? */
753 if (lctx->format == LAPD_FORM_S)
754 s = 1;
755 /* REJ frame ? */
756 if (s && lctx->s_u == LAPD_S_REJ)
757 rej = 1;
758
759 /* Flush all transmit buffers of acknowledged frames */
760 for (i = dl->v_ack; i != nr; i = inc_mod(i, dl->v_range)) {
761 h = do_mod(i, dl->range_hist);
762 if (dl->tx_hist[h].msg) {
763 msgb_free(dl->tx_hist[h].msg);
764 dl->tx_hist[h].msg = NULL;
Harald Welte00b2faf2020-05-02 19:56:36 +0200765 LOGDL(dl, LOGL_INFO, "ack frame %d\n", i);
rootaf48bed2011-09-26 11:23:06 +0200766 }
767 }
768
769 if (dl->state != LAPD_STATE_TIMER_RECOV) {
770 /* When not in the timer recovery condition, the data
771 * link layer entity shall reset the timer T200 on
772 * receipt of a valid I frame with N(R) higher than V(A),
773 * or an REJ with an N(R) equal to V(A). */
774 if ((!rej && nr != dl->v_ack)
775 || (rej && nr == dl->v_ack)) {
rootaf48bed2011-09-26 11:23:06 +0200776 t200_reset = 1;
Andreas Eversberg742fc792011-09-27 09:40:25 +0200777 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200778 /* 5.5.3.1 Note 1 + 2 imply timer recovery cond. */
779 }
780 /* 5.7.4: N(R) sequence error
781 * N(R) is called valid, if and only if
782 * (N(R)-V(A)) mod 8 <= (V(S)-V(A)) mod 8.
783 */
784 if (sub_mod(nr, dl->v_ack, dl->v_range)
785 > sub_mod(dl->v_send, dl->v_ack, dl->v_range)) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200786 LOGDL(dl, LOGL_NOTICE, "N(R) sequence error\n");
rootaf48bed2011-09-26 11:23:06 +0200787 mdl_error(MDL_CAUSE_SEQ_ERR, lctx);
788 }
789 }
790
791 /* V(A) shall be set to the value of N(R) */
792 dl->v_ack = nr;
793
Andreas Eversberg742fc792011-09-27 09:40:25 +0200794 /* If T200 has been stopped by the receipt of an I, RR or RNR frame,
rootaf48bed2011-09-26 11:23:06 +0200795 * and if there are outstanding I frames, restart T200 */
796 if (t200_reset && !rej) {
797 if (dl->tx_hist[sub_mod(dl->v_send, 1, dl->range_hist)].msg) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200798 LOGDL(dl, LOGL_INFO, "start T200, due to unacked I frame(s)\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +0200799 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200800 }
801 }
802
803 /* This also does a restart, when I or S frame is received */
804
805 /* Stop T203, if running */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200806 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200807 /* Start T203, if T200 is not running in MF EST state, if enabled */
808 if (!osmo_timer_pending(&dl->t200)
809 && (dl->t203_sec || dl->t203_usec)
810 && (dl->state == LAPD_STATE_MF_EST)) {
Andreas Eversberg742fc792011-09-27 09:40:25 +0200811 lapd_start_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200812 }
813}
814
815/* L1 -> L2 */
816
817/* Receive a LAPD U (Unnumbered) message from L1 */
818static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
819{
820 struct lapd_datalink *dl = lctx->dl;
821 int length = lctx->length;
Sylvain Munaut9a5f3b82011-11-20 09:01:59 +0100822 int rc = 0;
rootaf48bed2011-09-26 11:23:06 +0200823 uint8_t prim, op;
824
825 switch (lctx->s_u) {
826 case LAPD_U_SABM:
827 case LAPD_U_SABME:
828 prim = PRIM_DL_EST;
829 op = PRIM_OP_INDICATION;
830
Harald Welte00b2faf2020-05-02 19:56:36 +0200831 LOGDL(dl, LOGL_INFO, "SABM(E) received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200832 /* 5.7.1 */
833 dl->seq_err_cond = 0;
834 /* G.2.2 Wrong value of the C/R bit */
835 if (lctx->cr == dl->cr.rem2loc.resp) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200836 LOGDL(dl, LOGL_ERROR, "SABM response error\n");
rootaf48bed2011-09-26 11:23:06 +0200837 msgb_free(msg);
838 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
839 return -EINVAL;
840 }
841
842 /* G.4.5 If SABM is received with L>N201 or with M bit
843 * set, AN MDL-ERROR-INDICATION is sent to MM.
844 */
845 if (lctx->more || length > lctx->n201) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200846 LOGDL(dl, LOGL_ERROR, "SABM too large error\n");
rootaf48bed2011-09-26 11:23:06 +0200847 msgb_free(msg);
848 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
849 return -EIO;
850 }
851
852 switch (dl->state) {
853 case LAPD_STATE_IDLE:
854 break;
855 case LAPD_STATE_MF_EST:
Harald Welte00b2faf2020-05-02 19:56:36 +0200856 LOGDL(dl, LOGL_INFO, "SABM command, multiple frame established state\n");
rootaf48bed2011-09-26 11:23:06 +0200857 /* If link is lost on the remote side, we start over
858 * and send DL-ESTABLISH indication again. */
Andreas Eversberg6e182082013-02-06 14:13:21 +0100859 /* Additionally, continue in case of content resoltion
860 * (GSM network). This happens, if the mobile has not
861 * yet received UA or another mobile (collision) tries
862 * to establish connection. The mobile must receive
863 * UA again. */
Andreas Eversbergccc46332013-06-12 09:25:27 +0200864 /* 5.4.2.1 */
865 if (!length) {
866 /* If no content resolution, this is a
867 * re-establishment. */
Harald Welte00b2faf2020-05-02 19:56:36 +0200868 LOGDL(dl, LOGL_INFO, "Remote reestablish\n");
rootaf48bed2011-09-26 11:23:06 +0200869 break;
870 }
Andreas Eversbergccc46332013-06-12 09:25:27 +0200871 if (!dl->cont_res) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200872 LOGDL(dl, LOGL_INFO, "SABM command not allowed in state %s\n",
873 lapd_state_name(dl->state));
Andreas Eversbergccc46332013-06-12 09:25:27 +0200874 mdl_error(MDL_CAUSE_SABM_MF, lctx);
875 msgb_free(msg);
876 return 0;
877 }
rootaf48bed2011-09-26 11:23:06 +0200878 /* Ignore SABM if content differs from first SABM. */
Andreas Eversbergccc46332013-06-12 09:25:27 +0200879 if (dl->mode == LAPD_MODE_NETWORK && length) {
rootaf48bed2011-09-26 11:23:06 +0200880#ifdef TEST_CONTENT_RESOLUTION_NETWORK
881 dl->cont_res->data[0] ^= 0x01;
882#endif
Andreas Eversberg6e182082013-02-06 14:13:21 +0100883 if (memcmp(dl->cont_res->data, msg->data,
884 length)) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200885 LOGDL(dl, LOGL_INFO, "Another SABM with different content - "
886 "ignoring!\n");
rootaf48bed2011-09-26 11:23:06 +0200887 msgb_free(msg);
888 return 0;
889 }
890 }
891 /* send UA again */
892 lapd_send_ua(lctx, length, msg->l3h);
893 msgb_free(msg);
894 return 0;
895 case LAPD_STATE_DISC_SENT:
896 /* 5.4.6.2 send DM with F=P */
897 lapd_send_dm(lctx);
Andreas Eversberg742fc792011-09-27 09:40:25 +0200898 /* stop Timer T200 */
899 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200900 msgb_free(msg);
901 return send_dl_simple(prim, op, lctx);
902 default:
903 /* collision: Send UA, but still wait for rx UA, then
904 * change to MF_EST state.
905 */
906 /* check for contention resoultion */
907 if (dl->tx_hist[0].msg && dl->tx_hist[0].msg->len) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200908 LOGDL(dl, LOGL_NOTICE, "SABM not allowed during contention "
909 "resolution (state=%s)\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200910 mdl_error(MDL_CAUSE_SABM_INFO_NOTALL, lctx);
911 }
912 lapd_send_ua(lctx, length, msg->l3h);
913 msgb_free(msg);
914 return 0;
915 }
916 /* save message context for further use */
917 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
918#ifndef TEST_CONTENT_RESOLUTION_NETWORK
919 /* send UA response */
920 lapd_send_ua(lctx, length, msg->l3h);
921#endif
922 /* set Vs, Vr and Va to 0 */
923 dl->v_send = dl->v_recv = dl->v_ack = 0;
924 /* clear tx_hist */
925 lapd_dl_flush_hist(dl);
926 /* enter multiple-frame-established state */
927 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
928 /* store content resolution data on network side
929 * Note: cont_res will be removed when changing state again,
930 * so it must be allocated AFTER lapd_dl_newstate(). */
931 if (dl->mode == LAPD_MODE_NETWORK && length) {
932 dl->cont_res = lapd_msgb_alloc(length, "CONT RES");
933 memcpy(msgb_put(dl->cont_res, length), msg->l3h,
934 length);
Harald Welte00b2faf2020-05-02 19:56:36 +0200935 LOGDL(dl, LOGL_NOTICE, "Store content res.\n");
rootaf48bed2011-09-26 11:23:06 +0200936 }
937 /* send notification to L3 */
938 if (length == 0) {
939 /* 5.4.1.2 Normal establishment procedures */
940 rc = send_dl_simple(prim, op, lctx);
941 msgb_free(msg);
942 } else {
943 /* 5.4.1.4 Contention resolution establishment */
Harald Welte087116a2013-06-18 21:41:34 +0200944 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +0200945 rc = send_dl_l3(prim, op, lctx, msg);
946 }
947 break;
948 case LAPD_U_DM:
Harald Welte00b2faf2020-05-02 19:56:36 +0200949 LOGDL(dl, LOGL_INFO, "DM received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +0200950 /* G.2.2 Wrong value of the C/R bit */
951 if (lctx->cr == dl->cr.rem2loc.cmd) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200952 LOGDL(dl, LOGL_ERROR, "DM command error\n");
rootaf48bed2011-09-26 11:23:06 +0200953 msgb_free(msg);
954 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
955 return -EINVAL;
956 }
957 if (!lctx->p_f) {
958 /* 5.4.1.2 DM responses with the F bit set to "0"
959 * shall be ignored.
960 */
961 msgb_free(msg);
962 return 0;
963 }
964 switch (dl->state) {
965 case LAPD_STATE_SABM_SENT:
966 break;
967 case LAPD_STATE_MF_EST:
968 if (lctx->p_f) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200969 LOGDL(dl, LOGL_INFO, "unsolicited DM response\n");
rootaf48bed2011-09-26 11:23:06 +0200970 mdl_error(MDL_CAUSE_UNSOL_DM_RESP, lctx);
971 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +0200972 LOGDL(dl, LOGL_INFO, "unsolicited DM response, "
973 "multiple frame established state\n");
rootaf48bed2011-09-26 11:23:06 +0200974 mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
975 /* reestablish */
976 if (!dl->reestablish) {
977 msgb_free(msg);
978 return 0;
979 }
Harald Welte00b2faf2020-05-02 19:56:36 +0200980 LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");
rootaf48bed2011-09-26 11:23:06 +0200981 lapd_reestablish(dl);
982 }
983 msgb_free(msg);
984 return 0;
985 case LAPD_STATE_TIMER_RECOV:
986 /* FP = 0 (DM is normal in case PF = 1) */
987 if (!lctx->p_f) {
Harald Welte00b2faf2020-05-02 19:56:36 +0200988 LOGDL(dl, LOGL_INFO, "unsolicited DM response, multiple frame "
989 "established state\n");
rootaf48bed2011-09-26 11:23:06 +0200990 mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
991 msgb_free(msg);
992 /* reestablish */
993 if (!dl->reestablish)
994 return 0;
Harald Welte00b2faf2020-05-02 19:56:36 +0200995 LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");
rootaf48bed2011-09-26 11:23:06 +0200996 return lapd_reestablish(dl);
997 }
998 break;
999 case LAPD_STATE_DISC_SENT:
Andreas Eversberg742fc792011-09-27 09:40:25 +02001000 /* stop Timer T200 */
1001 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001002 /* go to idle state */
1003 lapd_dl_flush_tx(dl);
1004 lapd_dl_flush_send(dl);
1005 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1006 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
1007 msgb_free(msg);
1008 return 0;
1009 case LAPD_STATE_IDLE:
1010 /* 5.4.5 all other frame types shall be discarded */
1011 default:
Harald Welte00b2faf2020-05-02 19:56:36 +02001012 LOGDL(dl, LOGL_INFO, "unsolicited DM response! (discarding)\n");
rootaf48bed2011-09-26 11:23:06 +02001013 msgb_free(msg);
1014 return 0;
1015 }
Andreas Eversberg742fc792011-09-27 09:40:25 +02001016 /* stop timer T200 */
1017 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001018 /* go to idle state */
1019 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1020 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);
1021 msgb_free(msg);
1022 break;
1023 case LAPD_U_UI:
Harald Welte00b2faf2020-05-02 19:56:36 +02001024 LOGDL(dl, LOGL_INFO, "UI received\n");
rootaf48bed2011-09-26 11:23:06 +02001025 /* G.2.2 Wrong value of the C/R bit */
1026 if (lctx->cr == dl->cr.rem2loc.resp) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001027 LOGDL(dl, LOGL_ERROR, "UI indicates response error\n");
rootaf48bed2011-09-26 11:23:06 +02001028 msgb_free(msg);
1029 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1030 return -EINVAL;
1031 }
1032
1033 /* G.4.5 If UI is received with L>N201 or with M bit
1034 * set, AN MDL-ERROR-INDICATION is sent to MM.
1035 */
1036 if (length > lctx->n201 || lctx->more) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001037 LOGDL(dl, LOGL_ERROR, "UI too large error (%d > N201(%d) or M=%d)\n",
1038 length, lctx->n201, lctx->more);
rootaf48bed2011-09-26 11:23:06 +02001039 msgb_free(msg);
1040 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1041 return -EIO;
1042 }
1043
1044 /* do some length checks */
1045 if (length == 0) {
1046 /* 5.3.3 UI frames received with the length indicator
1047 * set to "0" shall be ignored
1048 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001049 LOGDL(dl, LOGL_INFO, "length=0 (discarding)\n");
rootaf48bed2011-09-26 11:23:06 +02001050 msgb_free(msg);
1051 return 0;
1052 }
Harald Welte087116a2013-06-18 21:41:34 +02001053 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +02001054 rc = send_dl_l3(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION, lctx,
1055 msg);
1056 break;
1057 case LAPD_U_DISC:
1058 prim = PRIM_DL_REL;
1059 op = PRIM_OP_INDICATION;
1060
Harald Welte00b2faf2020-05-02 19:56:36 +02001061 LOGDL(dl, LOGL_INFO, "DISC received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001062 /* flush tx and send buffers */
1063 lapd_dl_flush_tx(dl);
1064 lapd_dl_flush_send(dl);
1065 /* 5.7.1 */
1066 dl->seq_err_cond = 0;
1067 /* G.2.2 Wrong value of the C/R bit */
1068 if (lctx->cr == dl->cr.rem2loc.resp) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001069 LOGDL(dl, LOGL_ERROR, "DISC response error\n");
rootaf48bed2011-09-26 11:23:06 +02001070 msgb_free(msg);
1071 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1072 return -EINVAL;
1073 }
1074 if (length > 0 || lctx->more) {
1075 /* G.4.4 If a DISC or DM frame is received with L>0 or
1076 * with the M bit set to "1", an MDL-ERROR-INDICATION
1077 * primitive with cause "U frame with incorrect
1078 * parameters" is sent to the mobile management entity.
1079 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001080 LOGDL(dl, LOGL_ERROR, "U frame iwth incorrect parameters\n");
rootaf48bed2011-09-26 11:23:06 +02001081 msgb_free(msg);
1082 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1083 return -EIO;
1084 }
1085 switch (dl->state) {
1086 case LAPD_STATE_IDLE:
Harald Welte00b2faf2020-05-02 19:56:36 +02001087 LOGDL(dl, LOGL_INFO, "DISC in idle state\n");
rootaf48bed2011-09-26 11:23:06 +02001088 /* send DM with F=P */
1089 msgb_free(msg);
1090 return lapd_send_dm(lctx);
1091 case LAPD_STATE_SABM_SENT:
Harald Welte00b2faf2020-05-02 19:56:36 +02001092 LOGDL(dl, LOGL_INFO, "DISC in SABM state\n");
rootaf48bed2011-09-26 11:23:06 +02001093 /* 5.4.6.2 send DM with F=P */
1094 lapd_send_dm(lctx);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001095 /* stop Timer T200 */
1096 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001097 /* go to idle state */
1098 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1099 msgb_free(msg);
1100 return send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
1101 lctx);
1102 case LAPD_STATE_MF_EST:
1103 case LAPD_STATE_TIMER_RECOV:
Harald Welte00b2faf2020-05-02 19:56:36 +02001104 LOGDL(dl, LOGL_INFO, "DISC in est state\n");
rootaf48bed2011-09-26 11:23:06 +02001105 break;
1106 case LAPD_STATE_DISC_SENT:
Harald Welte00b2faf2020-05-02 19:56:36 +02001107 LOGDL(dl, LOGL_INFO, "DISC in disc state\n");
rootaf48bed2011-09-26 11:23:06 +02001108 prim = PRIM_DL_REL;
1109 op = PRIM_OP_CONFIRM;
1110 break;
1111 default:
1112 lapd_send_ua(lctx, length, msg->l3h);
1113 msgb_free(msg);
1114 return 0;
1115 }
1116 /* send UA response */
1117 lapd_send_ua(lctx, length, msg->l3h);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001118 /* stop Timer T200 */
1119 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001120 /* enter idle state, keep tx-buffer with UA response */
1121 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1122 /* send notification to L3 */
1123 rc = send_dl_simple(prim, op, lctx);
1124 msgb_free(msg);
1125 break;
1126 case LAPD_U_UA:
Harald Welte00b2faf2020-05-02 19:56:36 +02001127 LOGDL(dl, LOGL_INFO, "UA received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001128 /* G.2.2 Wrong value of the C/R bit */
1129 if (lctx->cr == dl->cr.rem2loc.cmd) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001130 LOGDL(dl, LOGL_ERROR, "UA indicates command error\n");
rootaf48bed2011-09-26 11:23:06 +02001131 msgb_free(msg);
1132 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1133 return -EINVAL;
1134 }
1135
1136 /* G.4.5 If UA is received with L>N201 or with M bit
1137 * set, AN MDL-ERROR-INDICATION is sent to MM.
1138 */
1139 if (lctx->more || length > lctx->n201) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001140 LOGDL(dl, LOGL_ERROR, "UA too large error\n");
rootaf48bed2011-09-26 11:23:06 +02001141 msgb_free(msg);
1142 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1143 return -EIO;
1144 }
1145
1146 if (!lctx->p_f) {
1147 /* 5.4.1.2 A UA response with the F bit set to "0"
1148 * shall be ignored.
1149 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001150 LOGDL(dl, LOGL_INFO, "F=0 (discarding)\n");
rootaf48bed2011-09-26 11:23:06 +02001151 msgb_free(msg);
1152 return 0;
1153 }
1154 switch (dl->state) {
1155 case LAPD_STATE_SABM_SENT:
1156 break;
1157 case LAPD_STATE_MF_EST:
1158 case LAPD_STATE_TIMER_RECOV:
Harald Welte00b2faf2020-05-02 19:56:36 +02001159 LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");
rootaf48bed2011-09-26 11:23:06 +02001160 mdl_error(MDL_CAUSE_UNSOL_UA_RESP, lctx);
1161 msgb_free(msg);
1162 return 0;
1163 case LAPD_STATE_DISC_SENT:
Harald Welte00b2faf2020-05-02 19:56:36 +02001164 LOGDL(dl, LOGL_INFO, "UA in disconnect state\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +02001165 /* stop Timer T200 */
1166 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001167 /* go to idle state */
1168 lapd_dl_flush_tx(dl);
1169 lapd_dl_flush_send(dl);
1170 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1171 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
1172 msgb_free(msg);
1173 return 0;
1174 case LAPD_STATE_IDLE:
1175 /* 5.4.5 all other frame types shall be discarded */
1176 default:
Harald Welte00b2faf2020-05-02 19:56:36 +02001177 LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");
rootaf48bed2011-09-26 11:23:06 +02001178 msgb_free(msg);
1179 return 0;
1180 }
Harald Welte00b2faf2020-05-02 19:56:36 +02001181 LOGDL(dl, LOGL_INFO, "UA in SABM state\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +02001182 /* stop Timer T200 */
1183 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001184 /* compare UA with SABME if contention resolution is applied */
1185 if (dl->tx_hist[0].msg->len) {
1186 if (length != (dl->tx_hist[0].msg->len)
1187 || !!memcmp(dl->tx_hist[0].msg->data, msg->l3h,
1188 length)) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001189 LOGDL(dl, LOGL_INFO, "**** UA response mismatches ****\n");
rootaf48bed2011-09-26 11:23:06 +02001190 rc = send_dl_simple(PRIM_DL_REL,
1191 PRIM_OP_INDICATION, lctx);
1192 msgb_free(msg);
1193 /* go to idle state */
1194 lapd_dl_flush_tx(dl);
1195 lapd_dl_flush_send(dl);
1196 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1197 return 0;
1198 }
1199 }
1200 /* set Vs, Vr and Va to 0 */
1201 dl->v_send = dl->v_recv = dl->v_ack = 0;
1202 /* clear tx_hist */
1203 lapd_dl_flush_hist(dl);
1204 /* enter multiple-frame-established state */
1205 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1206 /* send outstanding frames, if any (resume / reconnect) */
1207 lapd_send_i(lctx, __LINE__);
1208 /* send notification to L3 */
1209 rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx);
1210 msgb_free(msg);
1211 break;
1212 case LAPD_U_FRMR:
Harald Welte00b2faf2020-05-02 19:56:36 +02001213 LOGDL(dl, LOGL_NOTICE, "Frame reject received\n");
rootaf48bed2011-09-26 11:23:06 +02001214 /* send MDL ERROR INIDCATION to L3 */
1215 mdl_error(MDL_CAUSE_FRMR, lctx);
1216 msgb_free(msg);
1217 /* reestablish */
1218 if (!dl->reestablish)
1219 break;
Harald Welte00b2faf2020-05-02 19:56:36 +02001220 LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");
rootaf48bed2011-09-26 11:23:06 +02001221 rc = lapd_reestablish(dl);
1222 break;
1223 default:
1224 /* G.3.1 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001225 LOGDL(dl, LOGL_NOTICE, "Unnumbered frame not allowed\n");
rootaf48bed2011-09-26 11:23:06 +02001226 msgb_free(msg);
1227 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1228 return -EINVAL;
1229 }
1230 return rc;
1231}
1232
1233/* Receive a LAPD S (Supervisory) message from L1 */
1234static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
1235{
1236 struct lapd_datalink *dl = lctx->dl;
1237 int length = lctx->length;
1238
1239 if (length > 0 || lctx->more) {
1240 /* G.4.3 If a supervisory frame is received with L>0 or
1241 * with the M bit set to "1", an MDL-ERROR-INDICATION
1242 * primitive with cause "S frame with incorrect
1243 * parameters" is sent to the mobile management entity. */
Harald Welte00b2faf2020-05-02 19:56:36 +02001244 LOGDL(dl, LOGL_ERROR, "S frame with incorrect parameters\n");
rootaf48bed2011-09-26 11:23:06 +02001245 msgb_free(msg);
1246 mdl_error(MDL_CAUSE_SFRM_INC_PARAM, lctx);
1247 return -EIO;
1248 }
1249
1250 if (lctx->cr == dl->cr.rem2loc.resp
1251 && lctx->p_f
1252 && dl->state != LAPD_STATE_TIMER_RECOV) {
1253 /* 5.4.2.2: Inidcate error on supervisory reponse F=1 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001254 LOGDL(dl, LOGL_NOTICE, "S frame response with F=1 error\n");
rootaf48bed2011-09-26 11:23:06 +02001255 mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
1256 }
1257
1258 switch (dl->state) {
1259 case LAPD_STATE_IDLE:
1260 /* if P=1, respond DM with F=1 (5.2.2) */
1261 /* 5.4.5 all other frame types shall be discarded */
1262 if (lctx->p_f)
1263 lapd_send_dm(lctx); /* F=P */
1264 /* fall though */
1265 case LAPD_STATE_SABM_SENT:
1266 case LAPD_STATE_DISC_SENT:
Harald Welte00b2faf2020-05-02 19:56:36 +02001267 LOGDL(dl, LOGL_NOTICE, "S frame ignored in this state\n");
rootaf48bed2011-09-26 11:23:06 +02001268 msgb_free(msg);
1269 return 0;
1270 }
1271 switch (lctx->s_u) {
1272 case LAPD_S_RR:
Harald Welte00b2faf2020-05-02 19:56:36 +02001273 LOGDL(dl, LOGL_INFO, "RR received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001274 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1275 lapd_acknowledge(lctx);
1276
1277 /* 5.5.3.2 */
1278 if (lctx->cr == dl->cr.rem2loc.cmd
1279 && lctx->p_f) {
1280 if (!dl->own_busy && !dl->seq_err_cond) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001281 LOGDL(dl, LOGL_INFO, "RR frame command with polling bit set and "
1282 "we are not busy, so we reply with RR frame response\n");
rootaf48bed2011-09-26 11:23:06 +02001283 lapd_send_rr(lctx, 1, 0);
1284 /* NOTE: In case of sequence error condition,
1285 * the REJ frame has been transmitted when
1286 * entering the condition, so it has not be
1287 * done here
1288 */
1289 } else if (dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001290 LOGDL(dl, LOGL_INFO, "RR frame command with polling bit set and "
1291 "we are busy, so we reply with RR frame response\n");
rootaf48bed2011-09-26 11:23:06 +02001292 lapd_send_rnr(lctx, 1, 0);
1293 }
1294 } else if (lctx->cr == dl->cr.rem2loc.resp
1295 && lctx->p_f
1296 && dl->state == LAPD_STATE_TIMER_RECOV) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001297 LOGDL(dl, LOGL_INFO, "RR response with F==1, and we are in timer recovery "
1298 "state, so we leave that state\n");
rootaf48bed2011-09-26 11:23:06 +02001299 /* V(S) to the N(R) in the RR frame */
1300 dl->v_send = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001301 /* stop Timer T200 */
1302 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001303 /* 5.5.7 Clear timer recovery condition */
1304 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1305 }
1306 /* Send message, if possible due to acknowledged data */
1307 lapd_send_i(lctx, __LINE__);
1308
1309 break;
1310 case LAPD_S_RNR:
Harald Welte00b2faf2020-05-02 19:56:36 +02001311 LOGDL(dl, LOGL_INFO, "RNR received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001312 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1313 lapd_acknowledge(lctx);
1314
1315 /* 5.5.5 */
1316 /* Set peer receiver busy condition */
1317 dl->peer_busy = 1;
1318
1319 if (lctx->p_f) {
1320 if (lctx->cr == dl->cr.rem2loc.cmd) {
1321 if (!dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001322 LOGDL(dl, LOGL_INFO, "RNR poll command and we are not busy, "
1323 "so we reply with RR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001324 /* Send RR with F=1 */
1325 lapd_send_rr(lctx, 1, 0);
1326 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +02001327 LOGDL(dl, LOGL_INFO, "RNR poll command and we are busy, so "
1328 "we reply with RNR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001329 /* Send RNR with F=1 */
1330 lapd_send_rnr(lctx, 1, 0);
1331 }
1332 } else if (dl->state == LAPD_STATE_TIMER_RECOV) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001333 LOGDL(dl, LOGL_INFO, "RNR poll response and we in timer recovery "
1334 "state, so we leave that state\n");
rootaf48bed2011-09-26 11:23:06 +02001335 /* 5.5.7 Clear timer recovery condition */
1336 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1337 /* V(S) to the N(R) in the RNR frame */
1338 dl->v_send = lctx->n_recv;
1339 }
1340 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001341 LOGDL(dl, LOGL_INFO, "RNR not polling/final state received\n");
rootaf48bed2011-09-26 11:23:06 +02001342
1343 /* Send message, if possible due to acknowledged data */
1344 lapd_send_i(lctx, __LINE__);
1345
1346 break;
1347 case LAPD_S_REJ:
Harald Welte00b2faf2020-05-02 19:56:36 +02001348 LOGDL(dl, LOGL_INFO, "REJ received in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001349 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1350 lapd_acknowledge(lctx);
1351
1352 /* 5.5.4.1 */
1353 if (dl->state != LAPD_STATE_TIMER_RECOV) {
1354 /* Clear an existing peer receiver busy condition */
1355 dl->peer_busy = 0;
1356 /* V(S) and V(A) to the N(R) in the REJ frame */
1357 dl->v_send = dl->v_ack = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001358 /* stop Timer T200 */
1359 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001360 /* 5.5.3.2 */
1361 if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
1362 if (!dl->own_busy && !dl->seq_err_cond) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001363 LOGDL(dl, LOGL_INFO, "REJ poll command not in timer recovery "
1364 "state and not in own busy condition received, so we "
1365 "respond with RR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001366 lapd_send_rr(lctx, 1, 0);
1367 /* NOTE: In case of sequence error
1368 * condition, the REJ frame has been
1369 * transmitted when entering the
1370 * condition, so it has not be done
1371 * here
1372 */
1373 } else if (dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001374 LOGDL(dl, LOGL_INFO, "REJ poll command not in timer recovery "
1375 "state and in own busy condition received, so we "
1376 "respond with RNR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001377 lapd_send_rnr(lctx, 1, 0);
1378 }
1379 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001380 LOGDL(dl, LOGL_INFO, "REJ response or not polling command not "
1381 "in timer recovery state received\n");
rootaf48bed2011-09-26 11:23:06 +02001382 /* send MDL ERROR INIDCATION to L3 */
1383 if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001384 LOGDL(dl, LOGL_ERROR, "unsolicited supervisory response!\n");
rootaf48bed2011-09-26 11:23:06 +02001385 mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
1386 }
1387
1388 } else if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001389 LOGDL(dl, LOGL_INFO, "REJ poll response in timer recovery state received\n");
rootaf48bed2011-09-26 11:23:06 +02001390 /* Clear an existing peer receiver busy condition */
1391 dl->peer_busy = 0;
1392 /* V(S) and V(A) to the N(R) in the REJ frame */
1393 dl->v_send = dl->v_ack = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001394 /* stop Timer T200 */
1395 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001396 /* 5.5.7 Clear timer recovery condition */
1397 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1398 } else {
1399 /* Clear an existing peer receiver busy condition */
1400 dl->peer_busy = 0;
1401 /* V(S) and V(A) to the N(R) in the REJ frame */
1402 dl->v_send = dl->v_ack = lctx->n_recv;
1403 /* 5.5.3.2 */
1404 if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
1405 if (!dl->own_busy && !dl->seq_err_cond) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001406 LOGDL(dl, LOGL_INFO, "REJ poll command in timer recovery "
1407 "state and not in own busy condition received, so we "
1408 "respond with RR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001409 lapd_send_rr(lctx, 1, 0);
1410 /* NOTE: In case of sequence error
1411 * condition, the REJ frame has been
1412 * transmitted when entering the
1413 * condition, so it has not be done
1414 * here
1415 */
1416 } else if (dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001417 LOGDL(dl, LOGL_INFO, "REJ poll command in timer recovery "
1418 "state and in own busy condition received, so we "
1419 "respond with RNR final response\n");
rootaf48bed2011-09-26 11:23:06 +02001420 lapd_send_rnr(lctx, 1, 0);
1421 }
1422 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001423 LOGDL(dl, LOGL_INFO, "REJ response or not polling command in "
1424 "timer recovery state received\n");
rootaf48bed2011-09-26 11:23:06 +02001425 }
1426
1427 /* FIXME: 5.5.4.2 2) */
1428
1429 /* Send message, if possible due to acknowledged data */
1430 lapd_send_i(lctx, __LINE__);
1431
1432 break;
1433 default:
1434 /* G.3.1 */
Harald Welte00b2faf2020-05-02 19:56:36 +02001435 LOGDL(dl, LOGL_ERROR, "Supervisory frame not allowed\n");
rootaf48bed2011-09-26 11:23:06 +02001436 msgb_free(msg);
1437 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1438 return -EINVAL;
1439 }
1440 msgb_free(msg);
1441 return 0;
1442}
1443
1444/* Receive a LAPD I (Information) message from L1 */
1445static int lapd_rx_i(struct msgb *msg, struct lapd_msg_ctx *lctx)
1446{
1447 struct lapd_datalink *dl = lctx->dl;
1448 //uint8_t nr = lctx->n_recv;
1449 uint8_t ns = lctx->n_send;
1450 int length = lctx->length;
1451 int rc;
1452
Harald Welte00b2faf2020-05-02 19:56:36 +02001453 LOGDL(dl, LOGL_INFO, "I received in state %s on SAPI(%u)\n",
1454 lapd_state_name(dl->state), lctx->sapi);
Pau Espin Pedrola99e1102017-12-08 14:30:47 +01001455
rootaf48bed2011-09-26 11:23:06 +02001456 /* G.2.2 Wrong value of the C/R bit */
1457 if (lctx->cr == dl->cr.rem2loc.resp) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001458 LOGDL(dl, LOGL_ERROR, "I frame response not allowed (state %s)\n",
1459 lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001460 msgb_free(msg);
1461 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1462 return -EINVAL;
1463 }
1464
1465 if (length == 0 || length > lctx->n201) {
1466 /* G.4.2 If the length indicator of an I frame is set
1467 * to a numerical value L>N201 or L=0, an MDL-ERROR-INDICATION
1468 * primitive with cause "I frame with incorrect length"
1469 * is sent to the mobile management entity. */
Harald Welte00b2faf2020-05-02 19:56:36 +02001470 LOGDL(dl, LOGL_ERROR, "I frame length not allowed (state %s)\n",
1471 lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001472 msgb_free(msg);
1473 mdl_error(MDL_CAUSE_IFRM_INC_LEN, lctx);
1474 return -EIO;
1475 }
1476
1477 /* G.4.2 If the numerical value of L is L<N201 and the M
1478 * bit is set to "1", then an MDL-ERROR-INDICATION primitive with
1479 * cause "I frame with incorrect use of M bit" is sent to the
1480 * mobile management entity. */
1481 if (lctx->more && length < lctx->n201) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001482 LOGDL(dl, LOGL_ERROR, "I frame with M bit too short (state %s)\n",
1483 lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001484 msgb_free(msg);
1485 mdl_error(MDL_CAUSE_IFRM_INC_MBITS, lctx);
1486 return -EIO;
1487 }
1488
1489 switch (dl->state) {
1490 case LAPD_STATE_IDLE:
1491 /* if P=1, respond DM with F=1 (5.2.2) */
1492 /* 5.4.5 all other frame types shall be discarded */
1493 if (lctx->p_f)
1494 lapd_send_dm(lctx); /* F=P */
1495 /* fall though */
1496 case LAPD_STATE_SABM_SENT:
1497 case LAPD_STATE_DISC_SENT:
Harald Welte00b2faf2020-05-02 19:56:36 +02001498 LOGDL(dl, LOGL_NOTICE, "I frame ignored in state %s\n", lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001499 msgb_free(msg);
1500 return 0;
1501 }
1502
1503 /* 5.7.1: N(s) sequence error */
1504 if (ns != dl->v_recv) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001505 LOGDL(dl, LOGL_NOTICE, "N(S) sequence error: N(S)=%u, V(R)=%u (state %s)\n",
1506 ns, dl->v_recv, lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02001507 /* discard data */
1508 msgb_free(msg);
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001509 if (dl->seq_err_cond != 1) {
rootaf48bed2011-09-26 11:23:06 +02001510 /* FIXME: help me understand what exactly todo here
rootaf48bed2011-09-26 11:23:06 +02001511 */
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001512 dl->seq_err_cond = 1;
rootaf48bed2011-09-26 11:23:06 +02001513 lapd_send_rej(lctx, lctx->p_f);
1514 } else {
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001515 /* If there are two subsequent sequence errors received,
1516 * ignore it. (Ignore every second subsequent error.)
1517 * This happens if our reply with the REJ is too slow,
1518 * so the remote gets a T200 timeout and sends another
1519 * frame with a sequence error.
1520 * Test showed that replying with two subsequent REJ
1521 * messages could the remote L2 process to abort.
1522 * Replying too slow shouldn't happen, but may happen
1523 * over serial link between BB and LAPD.
1524 */
1525 dl->seq_err_cond = 2;
rootaf48bed2011-09-26 11:23:06 +02001526 }
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001527 /* Even if N(s) sequence error, acknowledge to N(R)-1 */
1528 /* 5.5.3.1: Acknowlege all transmitted frames up the N(R)-1 */
1529 lapd_acknowledge(lctx); /* V(A) is also set here */
1530
1531 /* Send message, if possible due to acknowledged data */
1532 lapd_send_i(lctx, __LINE__);
1533
1534 return 0;
rootaf48bed2011-09-26 11:23:06 +02001535 }
1536 dl->seq_err_cond = 0;
1537
1538 /* Increment receiver state */
1539 dl->v_recv = inc_mod(dl->v_recv, dl->v_range);
Harald Welte00b2faf2020-05-02 19:56:36 +02001540 LOGDL(dl, LOGL_INFO, "incrementing V(R) to %u\n", dl->v_recv);
rootaf48bed2011-09-26 11:23:06 +02001541
1542 /* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */
1543 lapd_acknowledge(lctx); /* V(A) is also set here */
1544
1545 /* Only if we are not in own receiver busy condition */
1546 if (!dl->own_busy) {
1547 /* if the frame carries a complete segment */
1548 if (!lctx->more && !dl->rcv_buffer) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001549 LOGDL(dl, LOGL_INFO, "message in single I frame\n");
rootaf48bed2011-09-26 11:23:06 +02001550 /* send a DATA INDICATION to L3 */
Harald Welte087116a2013-06-18 21:41:34 +02001551 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +02001552 rc = send_dl_l3(PRIM_DL_DATA, PRIM_OP_INDICATION, lctx,
1553 msg);
1554 } else {
1555 /* create rcv_buffer */
1556 if (!dl->rcv_buffer) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001557 LOGDL(dl, LOGL_INFO, "message in multiple I frames (first message)\n");
rootaf48bed2011-09-26 11:23:06 +02001558 dl->rcv_buffer = lapd_msgb_alloc(dl->maxf,
1559 "LAPD RX");
1560 dl->rcv_buffer->l3h = dl->rcv_buffer->data;
1561 }
1562 /* concat. rcv_buffer */
1563 if (msgb_l3len(dl->rcv_buffer) + length > dl->maxf) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001564 LOGDL(dl, LOGL_NOTICE, "Received frame overflow!\n");
rootaf48bed2011-09-26 11:23:06 +02001565 } else {
1566 memcpy(msgb_put(dl->rcv_buffer, length),
1567 msg->l3h, length);
1568 }
1569 /* if the last segment was received */
1570 if (!lctx->more) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001571 LOGDL(dl, LOGL_INFO, "message in multiple I frames (last message)\n");
rootaf48bed2011-09-26 11:23:06 +02001572 rc = send_dl_l3(PRIM_DL_DATA,
1573 PRIM_OP_INDICATION, lctx,
1574 dl->rcv_buffer);
1575 dl->rcv_buffer = NULL;
1576 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001577 LOGDL(dl, LOGL_INFO, "message in multiple I frames (next message)\n");
rootaf48bed2011-09-26 11:23:06 +02001578 msgb_free(msg);
1579
1580 }
1581 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001582 LOGDL(dl, LOGL_INFO, "I frame ignored during own receiver busy condition\n");
rootaf48bed2011-09-26 11:23:06 +02001583
1584 /* Check for P bit */
1585 if (lctx->p_f) {
1586 /* 5.5.2.1 */
1587 /* check if we are not in own receiver busy */
1588 if (!dl->own_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001589 LOGDL(dl, LOGL_INFO, "we are not busy, send RR\n");
rootaf48bed2011-09-26 11:23:06 +02001590 /* Send RR with F=1 */
1591 rc = lapd_send_rr(lctx, 1, 0);
1592 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +02001593 LOGDL(dl, LOGL_INFO, "we are busy, send RNR\n");
rootaf48bed2011-09-26 11:23:06 +02001594 /* Send RNR with F=1 */
1595 rc = lapd_send_rnr(lctx, 1, 0);
1596 }
1597 } else {
1598 /* 5.5.2.2 */
1599 /* check if we are not in own receiver busy */
1600 if (!dl->own_busy) {
1601 /* NOTE: V(R) is already set above */
1602 rc = lapd_send_i(lctx, __LINE__);
Daniel Willmann3dc4e162014-03-20 19:24:48 +01001603
1604 /* if update_pending_iframe returns 0 it updated
1605 * the lapd header of an iframe in the tx queue */
1606 if (rc && dl->update_pending_frames)
1607 rc = dl->update_pending_frames(lctx);
1608
rootaf48bed2011-09-26 11:23:06 +02001609 if (rc) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001610 LOGDL(dl, LOGL_INFO, "we are not busy and have no pending data, "
1611 "send RR\n");
rootaf48bed2011-09-26 11:23:06 +02001612 /* Send RR with F=0 */
1613 return lapd_send_rr(lctx, 0, 0);
1614 }
1615 /* all I or one RR is sent, we are done */
1616 return 0;
1617 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +02001618 LOGDL(dl, LOGL_INFO, "we are busy, send RNR\n");
rootaf48bed2011-09-26 11:23:06 +02001619 /* Send RNR with F=0 */
1620 rc = lapd_send_rnr(lctx, 0, 0);
1621 }
1622 }
1623
1624 /* Send message, if possible due to acknowledged data */
1625 lapd_send_i(lctx, __LINE__);
1626
1627 return rc;
1628}
1629
1630/* Receive a LAPD message from L1 */
1631int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx)
1632{
1633 int rc;
1634
1635 switch (lctx->format) {
1636 case LAPD_FORM_U:
1637 rc = lapd_rx_u(msg, lctx);
1638 break;
1639 case LAPD_FORM_S:
1640 rc = lapd_rx_s(msg, lctx);
1641 break;
1642 case LAPD_FORM_I:
1643 rc = lapd_rx_i(msg, lctx);
1644 break;
1645 default:
Harald Welte00b2faf2020-05-02 19:56:36 +02001646 LOGDL(lctx->dl, LOGL_NOTICE, "unknown LAPD format\n");
rootaf48bed2011-09-26 11:23:06 +02001647 msgb_free(msg);
1648 rc = -EINVAL;
1649 }
1650 return rc;
1651}
1652
1653/* L3 -> L2 */
1654
1655/* send unit data */
1656static int lapd_udata_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1657{
1658 struct lapd_datalink *dl = lctx->dl;
1659 struct msgb *msg = dp->oph.msg;
1660 struct lapd_msg_ctx nctx;
1661
1662 memcpy(&nctx, lctx, sizeof(nctx));
1663 /* keep nctx.ldp */
1664 /* keep nctx.sapi */
1665 /* keep nctx.tei */
1666 nctx.cr = dl->cr.loc2rem.cmd;
1667 nctx.format = LAPD_FORM_U;
1668 nctx.s_u = LAPD_U_UI;
1669 /* keep nctx.p_f */
1670 nctx.length = msg->len;
1671 nctx.more = 0;
1672
1673 return dl->send_ph_data_req(&nctx, msg);
1674}
1675
1676/* request link establishment */
1677static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1678{
1679 struct lapd_datalink *dl = lctx->dl;
1680 struct msgb *msg = dp->oph.msg;
1681 struct lapd_msg_ctx nctx;
1682
1683 if (msg->len)
Harald Welte00b2faf2020-05-02 19:56:36 +02001684 LOGDL(dl, LOGL_INFO, "perform establishment with content (SABM)\n");
rootaf48bed2011-09-26 11:23:06 +02001685 else
Harald Welte00b2faf2020-05-02 19:56:36 +02001686 LOGDL(dl, LOGL_INFO, "perform normal establishm. (SABM)\n");
rootaf48bed2011-09-26 11:23:06 +02001687
1688 /* Flush send-queue */
1689 /* Clear send-buffer */
1690 lapd_dl_flush_send(dl);
1691 /* be sure that history is empty */
1692 lapd_dl_flush_hist(dl);
1693
1694 /* save message context for further use */
1695 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
1696
1697 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001698 msgb_free(dl->rcv_buffer);
1699 dl->rcv_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +02001700
1701 /* assemble message */
1702 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1703 /* keep nctx.ldp */
1704 /* keep nctx.sapi */
1705 /* keep nctx.tei */
1706 nctx.cr = dl->cr.loc2rem.cmd;
1707 nctx.format = LAPD_FORM_U;
1708 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
1709 nctx.p_f = 1;
1710 nctx.length = msg->len;
1711 nctx.more = 0;
1712
1713 /* Transmit-buffer carries exactly one segment */
1714 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
1715 msgb_put(dl->tx_hist[0].msg, msg->len);
1716 if (msg->len)
1717 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
1718 dl->tx_hist[0].more = 0;
1719 /* set Vs to 0, because it is used as index when resending SABM */
1720 dl->v_send = 0;
Pau Espin Pedrola99e1102017-12-08 14:30:47 +01001721
rootaf48bed2011-09-26 11:23:06 +02001722 /* Set states */
1723 dl->own_busy = dl->peer_busy = 0;
1724 dl->retrans_ctr = 0;
1725 lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
1726
1727 /* Tramsmit and start T200 */
1728 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001729 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001730
1731 return 0;
1732}
1733
1734/* send data */
1735static int lapd_data_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1736{
1737 struct lapd_datalink *dl = lctx->dl;
1738 struct msgb *msg = dp->oph.msg;
1739
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +08001740 if (msgb_l3len(msg) == 0) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001741 LOGDL(dl, LOGL_ERROR, "writing an empty message is not possible\n");
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +08001742 msgb_free(msg);
1743 return -1;
1744 }
1745
Harald Welte00b2faf2020-05-02 19:56:36 +02001746 LOGDL(dl, LOGL_INFO, "writing message to send-queue: l3len: %d\n", msgb_l3len(msg));
rootaf48bed2011-09-26 11:23:06 +02001747
1748 /* Write data into the send queue */
1749 msgb_enqueue(&dl->send_queue, msg);
1750
1751 /* Send message, if possible */
1752 lapd_send_i(&dl->lctx, __LINE__);
1753
1754 return 0;
1755}
1756
1757/* Send next I frame from queued/buffered data */
1758static int lapd_send_i(struct lapd_msg_ctx *lctx, int line)
1759{
1760 struct lapd_datalink *dl = lctx->dl;
1761 uint8_t k = dl->k;
1762 uint8_t h;
1763 struct msgb *msg;
1764 int length, left;
1765 int rc = - 1; /* we sent nothing */
1766 struct lapd_msg_ctx nctx;
1767
1768
Harald Welte00b2faf2020-05-02 19:56:36 +02001769 LOGDL(dl, LOGL_INFO, "%s() called from line %d\n", __func__, line);
rootaf48bed2011-09-26 11:23:06 +02001770
1771 next_frame:
1772
1773 if (dl->peer_busy) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001774 LOGDL(dl, LOGL_INFO, "peer busy, not sending\n");
rootaf48bed2011-09-26 11:23:06 +02001775 return rc;
1776 }
1777
1778 if (dl->state == LAPD_STATE_TIMER_RECOV) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001779 LOGDL(dl, LOGL_INFO, "timer recovery, not sending\n");
rootaf48bed2011-09-26 11:23:06 +02001780 return rc;
1781 }
1782
1783 /* If the send state variable V(S) is equal to V(A) plus k
1784 * (where k is the maximum number of outstanding I frames - see
1785 * subclause 5.8.4), the data link layer entity shall not transmit any
1786 * new I frames, but shall retransmit an I frame as a result
1787 * of the error recovery procedures as described in subclauses 5.5.4 and
1788 * 5.5.7. */
1789 if (dl->v_send == add_mod(dl->v_ack, k, dl->v_range)) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001790 LOGDL(dl, LOGL_INFO, "k frames outstanding, not sending more "
1791 "(k=%u V(S)=%u V(A)=%u)\n", k, dl->v_send, dl->v_ack);
rootaf48bed2011-09-26 11:23:06 +02001792 return rc;
1793 }
1794
1795 h = do_mod(dl->v_send, dl->range_hist);
1796
1797 /* if we have no tx_hist yet, we create it */
1798 if (!dl->tx_hist[h].msg) {
1799 /* Get next message into send-buffer, if any */
1800 if (!dl->send_buffer) {
1801 next_message:
1802 dl->send_out = 0;
1803 dl->send_buffer = msgb_dequeue(&dl->send_queue);
1804 /* No more data to be sent */
1805 if (!dl->send_buffer)
1806 return rc;
Harald Welte00b2faf2020-05-02 19:56:36 +02001807 LOGDL(dl, LOGL_INFO, "get message from send-queue\n");
rootaf48bed2011-09-26 11:23:06 +02001808 }
1809
1810 /* How much is left in the send-buffer? */
1811 left = msgb_l3len(dl->send_buffer) - dl->send_out;
1812 /* Segment, if data exceeds N201 */
1813 length = left;
1814 if (length > lctx->n201)
1815 length = lctx->n201;
Harald Welte00b2faf2020-05-02 19:56:36 +02001816 LOGDL(dl, LOGL_INFO, "msg-len %d sent %d left %d N201 %d length %d "
1817 "first byte %02x\n", msgb_l3len(dl->send_buffer), dl->send_out, left,
1818 lctx->n201, length, dl->send_buffer->l3h[0]);
rootaf48bed2011-09-26 11:23:06 +02001819 /* If message in send-buffer is completely sent */
1820 if (left == 0) {
1821 msgb_free(dl->send_buffer);
1822 dl->send_buffer = NULL;
1823 goto next_message;
1824 }
1825
Harald Welte00b2faf2020-05-02 19:56:36 +02001826 LOGDL(dl, LOGL_INFO, "send I frame %sV(S)=%d\n",
1827 (left > length) ? "segment " : "", dl->v_send);
rootaf48bed2011-09-26 11:23:06 +02001828
1829 /* Create I frame (segment) and transmit-buffer content */
1830 msg = lapd_msgb_alloc(length, "LAPD I");
1831 msg->l3h = msgb_put(msg, length);
1832 /* assemble message */
1833 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1834 /* keep nctx.ldp */
1835 /* keep nctx.sapi */
1836 /* keep nctx.tei */
1837 nctx.cr = dl->cr.loc2rem.cmd;
1838 nctx.format = LAPD_FORM_I;
1839 nctx.p_f = 0;
1840 nctx.n_send = dl->v_send;
1841 nctx.n_recv = dl->v_recv;
1842 nctx.length = length;
1843 if (left > length)
1844 nctx.more = 1;
1845 else
1846 nctx.more = 0;
1847 if (length)
1848 memcpy(msg->l3h, dl->send_buffer->l3h + dl->send_out,
1849 length);
1850 /* store in tx_hist */
1851 dl->tx_hist[h].msg = lapd_msgb_alloc(msg->len, "HIST");
1852 msgb_put(dl->tx_hist[h].msg, msg->len);
1853 if (length)
1854 memcpy(dl->tx_hist[h].msg->data, msg->l3h, msg->len);
1855 dl->tx_hist[h].more = nctx.more;
1856 /* Add length to track how much is already in the tx buffer */
1857 dl->send_out += length;
1858 } else {
Harald Welte00b2faf2020-05-02 19:56:36 +02001859 LOGDL(dl, LOGL_INFO, "resend I frame from tx buffer V(S)=%d\n", dl->v_send);
rootaf48bed2011-09-26 11:23:06 +02001860
1861 /* Create I frame (segment) from tx_hist */
1862 length = dl->tx_hist[h].msg->len;
1863 msg = lapd_msgb_alloc(length, "LAPD I resend");
1864 msg->l3h = msgb_put(msg, length);
1865 /* assemble message */
1866 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1867 /* keep nctx.ldp */
1868 /* keep nctx.sapi */
1869 /* keep nctx.tei */
1870 nctx.cr = dl->cr.loc2rem.cmd;
1871 nctx.format = LAPD_FORM_I;
1872 nctx.p_f = 0;
1873 nctx.n_send = dl->v_send;
1874 nctx.n_recv = dl->v_recv;
1875 nctx.length = length;
1876 nctx.more = dl->tx_hist[h].more;
1877 if (length)
1878 memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
1879 }
1880
1881 /* The value of the send state variable V(S) shall be incremented by 1
1882 * at the end of the transmission of the I frame */
1883 dl->v_send = inc_mod(dl->v_send, dl->v_range);
1884
1885 /* If timer T200 is not running at the time right before transmitting a
1886 * frame, when the PH-READY-TO-SEND primitive is received from the
1887 * physical layer., it shall be set. */
1888 if (!osmo_timer_pending(&dl->t200)) {
Andreas Eversberg742fc792011-09-27 09:40:25 +02001889 /* stop Timer T203, if running */
1890 lapd_stop_t203(dl);
1891 /* start Timer T200 */
1892 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001893 }
1894
1895 dl->send_ph_data_req(&nctx, msg);
1896
1897 rc = 0; /* we sent something */
1898 goto next_frame;
1899}
1900
1901/* request link suspension */
1902static int lapd_susp_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1903{
1904 struct lapd_datalink *dl = lctx->dl;
1905 struct msgb *msg = dp->oph.msg;
1906
Harald Welte00b2faf2020-05-02 19:56:36 +02001907 LOGDL(dl, LOGL_INFO, "perform suspension\n");
rootaf48bed2011-09-26 11:23:06 +02001908
1909 /* put back the send-buffer to the send-queue (first position) */
1910 if (dl->send_buffer) {
Harald Welte00b2faf2020-05-02 19:56:36 +02001911 LOGDL(dl, LOGL_INFO, "put frame in sendbuffer back to queue\n");
rootaf48bed2011-09-26 11:23:06 +02001912 llist_add(&dl->send_buffer->list, &dl->send_queue);
1913 dl->send_buffer = NULL;
1914 } else
Harald Welte00b2faf2020-05-02 19:56:36 +02001915 LOGDL(dl, LOGL_INFO, "no frame in sendbuffer\n");
rootaf48bed2011-09-26 11:23:06 +02001916
1917 /* Clear transmit buffer, but keep send buffer */
1918 lapd_dl_flush_tx(dl);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001919 /* Stop timers (there is no state change, so we must stop all timers */
1920 lapd_stop_t200(dl);
1921 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +02001922
1923 msgb_free(msg);
1924
1925 return send_dl_simple(PRIM_DL_SUSP, PRIM_OP_CONFIRM, &dl->lctx);
1926}
1927
Neels Hofmeyr9e57a5a2015-12-21 11:20:14 +01001928/* request, resume or reconnect of link */
rootaf48bed2011-09-26 11:23:06 +02001929static int lapd_res_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1930{
1931 struct lapd_datalink *dl = lctx->dl;
1932 struct msgb *msg = dp->oph.msg;
1933 struct lapd_msg_ctx nctx;
1934
Harald Welte00b2faf2020-05-02 19:56:36 +02001935 LOGDL(dl, LOGL_INFO, "perform re-establishment (SABM) length=%d\n", msg->len);
Pau Espin Pedrola99e1102017-12-08 14:30:47 +01001936
rootaf48bed2011-09-26 11:23:06 +02001937 /* be sure that history is empty */
1938 lapd_dl_flush_hist(dl);
1939
1940 /* save message context for further use */
1941 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
1942
1943 /* Replace message in the send-buffer (reconnect) */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001944 msgb_free(dl->send_buffer);
1945 dl->send_buffer = NULL;
1946
rootaf48bed2011-09-26 11:23:06 +02001947 dl->send_out = 0;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001948 if (msg->len) {
rootaf48bed2011-09-26 11:23:06 +02001949 /* Write data into the send buffer, to be sent first */
1950 dl->send_buffer = msg;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001951 } else {
1952 msgb_free(msg);
1953 msg = NULL;
Andreas Eversberg5ad4ac82011-11-01 09:40:21 +01001954 dl->send_buffer = NULL;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001955 }
rootaf48bed2011-09-26 11:23:06 +02001956
1957 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001958 msgb_free(dl->rcv_buffer);
1959 dl->rcv_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +02001960
1961 /* Create new msgb (old one is now free) */
1962 msg = lapd_msgb_alloc(0, "LAPD SABM");
1963 msg->l3h = msg->data;
1964 /* assemble message */
1965 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1966 /* keep nctx.ldp */
1967 /* keep nctx.sapi */
1968 /* keep nctx.tei */
1969 nctx.cr = dl->cr.loc2rem.cmd;
1970 nctx.format = LAPD_FORM_U;
1971 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
1972 nctx.p_f = 1;
1973 nctx.length = 0;
1974 nctx.more = 0;
1975
1976 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
1977 msgb_put(dl->tx_hist[0].msg, msg->len);
1978 if (msg->len)
1979 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
1980 dl->tx_hist[0].more = 0;
1981 /* set Vs to 0, because it is used as index when resending SABM */
1982 dl->v_send = 0;
1983
1984 /* Set states */
1985 dl->own_busy = dl->peer_busy = 0;
1986 dl->retrans_ctr = 0;
1987 lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
1988
1989 /* Tramsmit and start T200 */
1990 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001991 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001992
1993 return 0;
1994}
1995
1996/* requesst release of link */
1997static int lapd_rel_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1998{
1999 struct lapd_datalink *dl = lctx->dl;
2000 struct msgb *msg = dp->oph.msg;
2001 struct lapd_msg_ctx nctx;
2002
2003 /* local release */
2004 if (dp->u.rel_req.mode) {
Harald Welte00b2faf2020-05-02 19:56:36 +02002005 LOGDL(dl, LOGL_INFO, "perform local release\n");
rootaf48bed2011-09-26 11:23:06 +02002006 msgb_free(msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02002007 /* stop Timer T200 */
2008 lapd_stop_t200(dl);
2009 /* enter idle state, T203 is stopped here, if running */
rootaf48bed2011-09-26 11:23:06 +02002010 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
2011 /* flush buffers */
2012 lapd_dl_flush_tx(dl);
2013 lapd_dl_flush_send(dl);
2014 /* send notification to L3 */
2015 return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
2016 }
2017
2018 /* in case we are already disconnecting */
2019 if (dl->state == LAPD_STATE_DISC_SENT)
2020 return -EBUSY;
2021
2022 /* flush tx_hist */
2023 lapd_dl_flush_hist(dl);
2024
Harald Welte00b2faf2020-05-02 19:56:36 +02002025 LOGDL(dl, LOGL_INFO, "perform normal release (DISC)\n");
rootaf48bed2011-09-26 11:23:06 +02002026
2027 /* Push LAPD header on msgb */
2028 /* assemble message */
2029 memcpy(&nctx, &dl->lctx, sizeof(nctx));
2030 /* keep nctx.ldp */
2031 /* keep nctx.sapi */
2032 /* keep nctx.tei */
2033 nctx.cr = dl->cr.loc2rem.cmd;
2034 nctx.format = LAPD_FORM_U;
2035 nctx.s_u = LAPD_U_DISC;
2036 nctx.p_f = 1;
2037 nctx.length = 0;
2038 nctx.more = 0;
2039
2040 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
2041 msgb_put(dl->tx_hist[0].msg, msg->len);
2042 if (msg->len)
2043 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
2044 dl->tx_hist[0].more = 0;
2045 /* set Vs to 0, because it is used as index when resending DISC */
2046 dl->v_send = 0;
Pau Espin Pedrola99e1102017-12-08 14:30:47 +01002047
rootaf48bed2011-09-26 11:23:06 +02002048 /* Set states */
2049 dl->own_busy = dl->peer_busy = 0;
2050 dl->retrans_ctr = 0;
2051 lapd_dl_newstate(dl, LAPD_STATE_DISC_SENT);
2052
2053 /* Tramsmit and start T200 */
2054 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02002055 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02002056
2057 return 0;
2058}
2059
2060/* request release of link in idle state */
2061static int lapd_rel_req_idle(struct osmo_dlsap_prim *dp,
2062 struct lapd_msg_ctx *lctx)
2063{
2064 struct lapd_datalink *dl = lctx->dl;
2065 struct msgb *msg = dp->oph.msg;
2066
2067 msgb_free(msg);
2068
2069 /* send notification to L3 */
2070 return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
2071}
2072
2073/* statefull handling for DL SAP messages from L3 */
Holger Hans Peter Freyther579fb092012-11-22 10:54:23 +01002074static const struct l2downstate {
rootaf48bed2011-09-26 11:23:06 +02002075 uint32_t states;
2076 int prim, op;
2077 const char *name;
2078 int (*rout) (struct osmo_dlsap_prim *dp,
2079 struct lapd_msg_ctx *lctx);
2080} l2downstatelist[] = {
2081 /* create and send UI command */
2082 {ALL_STATES,
Pau Espin Pedrola99e1102017-12-08 14:30:47 +01002083 PRIM_DL_UNIT_DATA, PRIM_OP_REQUEST,
rootaf48bed2011-09-26 11:23:06 +02002084 "DL-UNIT-DATA-REQUEST", lapd_udata_req},
2085
2086 /* create and send SABM command */
2087 {SBIT(LAPD_STATE_IDLE),
2088 PRIM_DL_EST, PRIM_OP_REQUEST,
2089 "DL-ESTABLISH-REQUEST", lapd_est_req},
2090
2091 /* create and send I command */
2092 {SBIT(LAPD_STATE_MF_EST) |
2093 SBIT(LAPD_STATE_TIMER_RECOV),
2094 PRIM_DL_DATA, PRIM_OP_REQUEST,
2095 "DL-DATA-REQUEST", lapd_data_req},
2096
2097 /* suspend datalink */
2098 {SBIT(LAPD_STATE_MF_EST) |
2099 SBIT(LAPD_STATE_TIMER_RECOV),
2100 PRIM_DL_SUSP, PRIM_OP_REQUEST,
2101 "DL-SUSPEND-REQUEST", lapd_susp_req},
2102
2103 /* create and send SABM command (resume) */
2104 {SBIT(LAPD_STATE_MF_EST) |
2105 SBIT(LAPD_STATE_TIMER_RECOV),
2106 PRIM_DL_RES, PRIM_OP_REQUEST,
2107 "DL-RESUME-REQUEST", lapd_res_req},
2108
2109 /* create and send SABM command (reconnect) */
2110 {SBIT(LAPD_STATE_IDLE) |
2111 SBIT(LAPD_STATE_MF_EST) |
2112 SBIT(LAPD_STATE_TIMER_RECOV),
2113 PRIM_DL_RECON, PRIM_OP_REQUEST,
2114 "DL-RECONNECT-REQUEST", lapd_res_req},
2115
2116 /* create and send DISC command */
2117 {SBIT(LAPD_STATE_SABM_SENT) |
2118 SBIT(LAPD_STATE_MF_EST) |
2119 SBIT(LAPD_STATE_TIMER_RECOV) |
2120 SBIT(LAPD_STATE_DISC_SENT),
2121 PRIM_DL_REL, PRIM_OP_REQUEST,
2122 "DL-RELEASE-REQUEST", lapd_rel_req},
2123
2124 /* release in idle state */
2125 {SBIT(LAPD_STATE_IDLE),
2126 PRIM_DL_REL, PRIM_OP_REQUEST,
2127 "DL-RELEASE-REQUEST", lapd_rel_req_idle},
2128};
2129
2130#define L2DOWNSLLEN \
2131 (sizeof(l2downstatelist) / sizeof(struct l2downstate))
2132
2133int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
2134{
2135 struct lapd_datalink *dl = lctx->dl;
2136 int i, supported = 0;
2137 struct msgb *msg = dp->oph.msg;
2138 int rc;
2139
2140 /* find function for current state and message */
2141 for (i = 0; i < L2DOWNSLLEN; i++) {
2142 if (dp->oph.primitive == l2downstatelist[i].prim
2143 && dp->oph.operation == l2downstatelist[i].op) {
2144 supported = 1;
2145 if ((SBIT(dl->state) & l2downstatelist[i].states))
2146 break;
2147 }
2148 }
2149 if (!supported) {
Harald Welte00b2faf2020-05-02 19:56:36 +02002150 LOGDL(dl, LOGL_NOTICE, "Message %u/%u unsupported\n",
2151 dp->oph.primitive, dp->oph.operation);
rootaf48bed2011-09-26 11:23:06 +02002152 msgb_free(msg);
2153 return 0;
2154 }
2155 if (i == L2DOWNSLLEN) {
Harald Welte00b2faf2020-05-02 19:56:36 +02002156 LOGDL(dl, LOGL_NOTICE, "Message %u/%u unhandled at this state %s\n",
2157 dp->oph.primitive, dp->oph.operation, lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02002158 msgb_free(msg);
2159 return 0;
2160 }
2161
Harald Welte00b2faf2020-05-02 19:56:36 +02002162 LOGDL(dl, LOGL_INFO, "Message %s received in state %s\n",
2163 l2downstatelist[i].name, lapd_state_name(dl->state));
rootaf48bed2011-09-26 11:23:06 +02002164
2165 rc = l2downstatelist[i].rout(dp, lctx);
2166
2167 return rc;
2168}
2169
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +01002170/*! @} */