blob: 0d8f12823adada5dee9467ec0db9b47403a61105 [file] [log] [blame]
rootaf48bed2011-09-26 11:23:06 +02001/* LAPD core implementation */
2
3/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2010-2011 by Andreas Eversberg <jolly@eversberg.eu>
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24/*! \addtogroup lapd
25 * @{
26 */
27
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +010028/*! \file lapd_core.c */
rootaf48bed2011-09-26 11:23:06 +020029
30/*!
31 * Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
32 *
33 * RX data is stored in the rcv_buffer (pointer). If the message is complete, it
34 * is removed from rcv_buffer pointer and forwarded to L3. If the RX data is
35 * received while there is an incomplete rcv_buffer, it is appended to it.
36 *
37 * TX data is stored in the send_queue first. When transmitting a frame,
38 * the first message in the send_queue is moved to the send_buffer. There it
39 * resides until all fragments are acknowledged. Fragments to be sent by I
40 * frames are stored in the tx_hist buffer for resend, if required. Also the
41 * current fragment is copied into the tx_queue. There it resides until it is
42 * forwarded to layer 1.
43 *
44 * In case we have SAPI 0, we only have a window size of 1, so the unack-
45 * nowledged message resides always in the send_buffer. In case of a suspend,
46 * it can be written back to the first position of the send_queue.
47 *
48 * The layer 1 normally sends a PH-READY-TO-SEND. But because we use
49 * asynchronous transfer between layer 1 and layer 2 (serial link), we must
50 * send a frame before layer 1 reaches the right timeslot to send it. So we
51 * move the tx_queue to layer 1 when there is not already a pending frame, and
52 * wait until acknowledge after the frame has been sent. If we receive an
53 * acknowledge, we can send the next frame from the buffer, if any.
54 *
55 * The moving of tx_queue to layer 1 may also trigger T200, if desired. Also it
56 * will trigger next I frame, if possible.
57 *
58 * T203 is optional. It will be stated when entering MF EST state. It will also
59 * be started when I or S frame is received in that state . It will be
60 * restarted in the lapd_acknowledge() function, in case outstanding frames
61 * will not trigger T200. It will be stoped, when T200 is started in MF EST
62 * state. It will also be stoped when leaving MF EST state.
63 *
64 */
65
66/* Enable this to test content resolution on network side:
67 * - The first SABM is received, UA is dropped.
68 * - The phone repeats SABM, but it's content is wrong, so it is ignored
69 * - The phone repeats SABM again, content is right, so UA is sent.
70 */
71//#define TEST_CONTENT_RESOLUTION_NETWORK
72
73#include <stdio.h>
74#include <stdint.h>
75#include <string.h>
76#include <errno.h>
77#include <arpa/inet.h>
78
79#include <osmocom/core/logging.h>
80#include <osmocom/core/timer.h>
81#include <osmocom/core/msgb.h>
82#include <osmocom/core/utils.h>
83#include <osmocom/core/talloc.h>
84#include <osmocom/gsm/lapd_core.h>
85
86/* TS 04.06 Table 4 / Section 3.8.1 */
87#define LAPD_U_SABM 0x7
88#define LAPD_U_SABME 0xf
89#define LAPD_U_DM 0x3
90#define LAPD_U_UI 0x0
91#define LAPD_U_DISC 0x8
92#define LAPD_U_UA 0xC
93#define LAPD_U_FRMR 0x11
94
95#define LAPD_S_RR 0x0
96#define LAPD_S_RNR 0x1
97#define LAPD_S_REJ 0x2
98
99#define CR_USER2NET_CMD 0
100#define CR_USER2NET_RESP 1
101#define CR_NET2USER_CMD 1
102#define CR_NET2USER_RESP 0
103
104#define LAPD_HEADROOM 56
105
106#define SBIT(a) (1 << a)
107#define ALL_STATES 0xffffffff
108
Andreas Eversberg742fc792011-09-27 09:40:25 +0200109static void lapd_t200_cb(void *data);
110static void lapd_t203_cb(void *data);
111static int lapd_send_i(struct lapd_msg_ctx *lctx, int line);
112static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
113
rootaf48bed2011-09-26 11:23:06 +0200114/* UTILITY FUNCTIONS */
115
116struct msgb *lapd_msgb_alloc(int length, const char *name)
117{
118 /* adding space for padding, FIXME: add as an option */
119 if (length < 21)
120 length = 21;
121 return msgb_alloc_headroom(length + LAPD_HEADROOM, LAPD_HEADROOM, name);
122}
123
124static inline uint8_t do_mod(uint8_t x, uint8_t m)
125{
126 return x & (m - 1);
127}
128
129static inline uint8_t inc_mod(uint8_t x, uint8_t m)
130{
131 return (x + 1) & (m - 1);
132}
133
134static inline uint8_t add_mod(uint8_t x, uint8_t y, uint8_t m)
135{
136 return (x + y) & (m - 1);
137}
138
139static inline uint8_t sub_mod(uint8_t x, uint8_t y, uint8_t m)
140{
141 return (x - y) & (m - 1); /* handle negative results correctly */
142}
143
144static void lapd_dl_flush_send(struct lapd_datalink *dl)
145{
146 struct msgb *msg;
147
148 /* Flush send-queue */
149 while ((msg = msgb_dequeue(&dl->send_queue)))
150 msgb_free(msg);
151
152 /* Clear send-buffer */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200153 msgb_free(dl->send_buffer);
154 dl->send_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +0200155}
156
157static void lapd_dl_flush_hist(struct lapd_datalink *dl)
158{
159 unsigned int i;
160
161 for (i = 0; i < dl->range_hist; i++) {
162 if (dl->tx_hist[i].msg) {
163 msgb_free(dl->tx_hist[i].msg);
164 dl->tx_hist[i].msg = NULL;
165 }
166 }
167}
168
169static void lapd_dl_flush_tx(struct lapd_datalink *dl)
170{
171 struct msgb *msg;
172
173 while ((msg = msgb_dequeue(&dl->tx_queue)))
174 msgb_free(msg);
175 lapd_dl_flush_hist(dl);
176}
177
178/* Figure B.2/Q.921 */
179const char *lapd_state_names[] = {
180 "LAPD_STATE_NULL",
181 "LAPD_STATE_TEI_UNASS",
182 "LAPD_STATE_ASS_TEI_WAIT",
183 "LAPD_STATE_EST_TEI_WAIT",
184 "LAPD_STATE_IDLE",
185 "LAPD_STATE_SABM_SENT",
186 "LAPD_STATE_DISC_SENT",
187 "LAPD_STATE_MF_EST",
188 "LAPD_STATE_TIMER_RECOV",
189
190};
191
Andreas Eversberg742fc792011-09-27 09:40:25 +0200192static void lapd_start_t200(struct lapd_datalink *dl)
193{
194 if (osmo_timer_pending(&dl->t200))
195 return;
196 LOGP(DLLAPD, LOGL_INFO, "start T200\n");
197 osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec);
198}
199
200static void lapd_start_t203(struct lapd_datalink *dl)
201{
202 if (osmo_timer_pending(&dl->t203))
203 return;
204 LOGP(DLLAPD, LOGL_INFO, "start T203\n");
205 osmo_timer_schedule(&dl->t203, dl->t203_sec, dl->t203_usec);
206}
207
208static void lapd_stop_t200(struct lapd_datalink *dl)
209{
210 if (!osmo_timer_pending(&dl->t200))
211 return;
212 LOGP(DLLAPD, LOGL_INFO, "stop T200\n");
213 osmo_timer_del(&dl->t200);
214}
215
216static void lapd_stop_t203(struct lapd_datalink *dl)
217{
218 if (!osmo_timer_pending(&dl->t203))
219 return;
220 LOGP(DLLAPD, LOGL_INFO, "stop T203\n");
221 osmo_timer_del(&dl->t203);
222}
223
rootaf48bed2011-09-26 11:23:06 +0200224static void lapd_dl_newstate(struct lapd_datalink *dl, uint32_t state)
225{
226 LOGP(DLLAPD, LOGL_INFO, "new state %s -> %s\n",
227 lapd_state_names[dl->state], lapd_state_names[state]);
228
229 if (state != LAPD_STATE_MF_EST && dl->state == LAPD_STATE_MF_EST) {
230 /* stop T203 on leaving MF EST state, if running */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200231 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200232 /* remove content res. (network side) on leaving MF EST state */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200233 msgb_free(dl->cont_res);
234 dl->cont_res = NULL;
rootaf48bed2011-09-26 11:23:06 +0200235 }
236
237 /* start T203 on entering MF EST state, if enabled */
238 if ((dl->t203_sec || dl->t203_usec)
Andreas Eversberg742fc792011-09-27 09:40:25 +0200239 && state == LAPD_STATE_MF_EST && dl->state != LAPD_STATE_MF_EST)
240 lapd_start_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200241
242 dl->state = state;
243}
244
rootaf48bed2011-09-26 11:23:06 +0200245static void *tall_lapd_ctx = NULL;
246
247/* init datalink instance and allocate history */
248void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
249 int maxf)
250{
251 int m;
252
253 memset(dl, 0, sizeof(*dl));
254 INIT_LLIST_HEAD(&dl->send_queue);
255 INIT_LLIST_HEAD(&dl->tx_queue);
256 dl->reestablish = 1;
257 dl->n200_est_rel = 3;
258 dl->n200 = 3;
259 dl->t200_sec = 1;
260 dl->t200_usec = 0;
261 dl->t200.data = dl;
262 dl->t200.cb = &lapd_t200_cb;
263 dl->t203_sec = 10;
264 dl->t203_usec = 0;
265 dl->t203.data = dl;
266 dl->t203.cb = &lapd_t203_cb;
267 dl->maxf = maxf;
268 if (k > v_range - 1)
269 k = v_range - 1;
270 dl->k = k;
271 dl->v_range = v_range;
272
273 /* Calculate modulo for history array:
274 * - The history range must be at least k+1.
275 * - The history range must be 2^x, where x is as low as possible.
276 */
277 k++;
278 for (m = 0x80; m; m >>= 1) {
279 if ((m & k)) {
280 if (k > m)
281 m <<= 1;
282 dl->range_hist = m;
283 break;
284 }
285 }
286
287 LOGP(DLLAPD, LOGL_INFO, "Init DL layer: sequence range = %d, k = %d, "
288 "history range = %d\n", dl->v_range, dl->k, dl->range_hist);
289
290 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
291
292 if (!tall_lapd_ctx)
293 tall_lapd_ctx = talloc_named_const(NULL, 1, "lapd context");
Holger Hans Peter Freyther10f0bde2014-02-09 20:03:38 +0100294 dl->tx_hist = talloc_zero_array(tall_lapd_ctx,
295 struct lapd_history, dl->range_hist);
rootaf48bed2011-09-26 11:23:06 +0200296}
297
298/* reset to IDLE state */
299void lapd_dl_reset(struct lapd_datalink *dl)
300{
301 if (dl->state == LAPD_STATE_IDLE)
302 return;
303 LOGP(DLLAPD, LOGL_INFO, "Resetting LAPDm instance\n");
304 /* enter idle state (and remove eventual cont_res) */
305 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
306 /* flush buffer */
307 lapd_dl_flush_tx(dl);
308 lapd_dl_flush_send(dl);
309 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +0200310 msgb_free(dl->rcv_buffer);
311 dl->rcv_buffer = NULL;
Andreas Eversberg742fc792011-09-27 09:40:25 +0200312 /* stop Timers */
313 lapd_stop_t200(dl);
314 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200315}
316
317/* reset and de-allocate history buffer */
318void lapd_dl_exit(struct lapd_datalink *dl)
319{
320 /* free all ressources except history buffer */
321 lapd_dl_reset(dl);
322 /* free history buffer list */
323 talloc_free(dl->tx_hist);
Holger Hans Peter Freytherf5a079f2013-05-08 18:42:39 +0200324 dl->tx_hist = NULL;
rootaf48bed2011-09-26 11:23:06 +0200325}
326
327/*! \brief Set the \ref lapdm_mode of a LAPDm entity */
328int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode)
329{
330 switch (mode) {
331 case LAPD_MODE_USER:
332 dl->cr.loc2rem.cmd = CR_USER2NET_CMD;
333 dl->cr.loc2rem.resp = CR_USER2NET_RESP;
334 dl->cr.rem2loc.cmd = CR_NET2USER_CMD;
335 dl->cr.rem2loc.resp = CR_NET2USER_RESP;
336 break;
337 case LAPD_MODE_NETWORK:
338 dl->cr.loc2rem.cmd = CR_NET2USER_CMD;
339 dl->cr.loc2rem.resp = CR_NET2USER_RESP;
340 dl->cr.rem2loc.cmd = CR_USER2NET_CMD;
341 dl->cr.rem2loc.resp = CR_USER2NET_RESP;
342 break;
343 default:
344 return -EINVAL;
345 }
346 dl->mode = mode;
347
348 return 0;
349}
350
351/* send DL message with optional msgb */
352static int send_dl_l3(uint8_t prim, uint8_t op, struct lapd_msg_ctx *lctx,
353 struct msgb *msg)
354{
355 struct lapd_datalink *dl = lctx->dl;
356 struct osmo_dlsap_prim dp;
357
358 osmo_prim_init(&dp.oph, 0, prim, op, msg);
359 return dl->send_dlsap(&dp, lctx);
360}
361
362/* send simple DL message */
363static inline int send_dl_simple(uint8_t prim, uint8_t op,
364 struct lapd_msg_ctx *lctx)
365{
366 struct msgb *msg = lapd_msgb_alloc(0, "DUMMY");
367
368 return send_dl_l3(prim, op, lctx, msg);
369}
370
371/* send MDL-ERROR INDICATION */
372static int mdl_error(uint8_t cause, struct lapd_msg_ctx *lctx)
373{
374 struct lapd_datalink *dl = lctx->dl;
375 struct osmo_dlsap_prim dp;
376
377 LOGP(DLLAPD, LOGL_NOTICE, "sending MDL-ERROR-IND cause %d\n",
378 cause);
379 osmo_prim_init(&dp.oph, 0, PRIM_MDL_ERROR, PRIM_OP_INDICATION, NULL);
380 dp.u.error_ind.cause = cause;
381 return dl->send_dlsap(&dp, lctx);
382}
383
384/* send UA response */
385static int lapd_send_ua(struct lapd_msg_ctx *lctx, uint8_t len, uint8_t *data)
386{
387 struct msgb *msg = lapd_msgb_alloc(len, "LAPD UA");
388 struct lapd_msg_ctx nctx;
389 struct lapd_datalink *dl = lctx->dl;
390
391 memcpy(&nctx, lctx, sizeof(nctx));
392 msg->l3h = msgb_put(msg, len);
393 if (len)
394 memcpy(msg->l3h, data, len);
395 /* keep nctx.ldp */
396 /* keep nctx.sapi */
397 /* keep nctx.tei */
398 nctx.cr = dl->cr.loc2rem.resp;
399 nctx.format = LAPD_FORM_U;
400 nctx.s_u = LAPD_U_UA;
401 /* keep nctx.p_f */
402 nctx.length = len;
403 nctx.more = 0;
404
405 return dl->send_ph_data_req(&nctx, msg);
406}
407
408/* send DM response */
409static int lapd_send_dm(struct lapd_msg_ctx *lctx)
410{
411 struct msgb *msg = lapd_msgb_alloc(0, "LAPD DM");
412 struct lapd_msg_ctx nctx;
413 struct lapd_datalink *dl = lctx->dl;
414
415 memcpy(&nctx, lctx, sizeof(nctx));
416 /* keep nctx.ldp */
417 /* keep nctx.sapi */
418 /* keep nctx.tei */
419 nctx.cr = dl->cr.loc2rem.resp;
420 nctx.format = LAPD_FORM_U;
421 nctx.s_u = LAPD_U_DM;
422 /* keep nctx.p_f */
423 nctx.length = 0;
424 nctx.more = 0;
425
426 return dl->send_ph_data_req(&nctx, msg);
427}
428
429/* send RR response / command */
430static int lapd_send_rr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
431{
432 struct msgb *msg = lapd_msgb_alloc(0, "LAPD RR");
433 struct lapd_msg_ctx nctx;
434 struct lapd_datalink *dl = lctx->dl;
435
436 memcpy(&nctx, lctx, sizeof(nctx));
437 /* keep nctx.ldp */
438 /* keep nctx.sapi */
439 /* keep nctx.tei */
440 nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
441 nctx.format = LAPD_FORM_S;
442 nctx.s_u = LAPD_S_RR;
443 nctx.p_f = f_bit;
444 nctx.n_recv = dl->v_recv;
445 nctx.length = 0;
446 nctx.more = 0;
447
448 return dl->send_ph_data_req(&nctx, msg);
449}
450
451/* send RNR response / command */
452static int lapd_send_rnr(struct lapd_msg_ctx *lctx, uint8_t f_bit, uint8_t cmd)
453{
454 struct msgb *msg = lapd_msgb_alloc(0, "LAPD RNR");
455 struct lapd_msg_ctx nctx;
456 struct lapd_datalink *dl = lctx->dl;
457
458 memcpy(&nctx, lctx, sizeof(nctx));
459 /* keep nctx.ldp */
460 /* keep nctx.sapi */
461 /* keep nctx.tei */
462 nctx.cr = (cmd) ? dl->cr.loc2rem.cmd : dl->cr.loc2rem.resp;
463 nctx.format = LAPD_FORM_S;
464 nctx.s_u = LAPD_S_RNR;
465 nctx.p_f = f_bit;
466 nctx.n_recv = dl->v_recv;
467 nctx.length = 0;
468 nctx.more = 0;
469
470 return dl->send_ph_data_req(&nctx, msg);
471}
472
473/* send REJ response */
474static int lapd_send_rej(struct lapd_msg_ctx *lctx, uint8_t f_bit)
475{
476 struct msgb *msg = lapd_msgb_alloc(0, "LAPD REJ");
477 struct lapd_msg_ctx nctx;
478 struct lapd_datalink *dl = lctx->dl;
479
480 memcpy(&nctx, lctx, sizeof(nctx));
481 /* keep nctx.ldp */
482 /* keep nctx.sapi */
483 /* keep nctx.tei */
484 nctx.cr = dl->cr.loc2rem.resp;
485 nctx.format = LAPD_FORM_S;
486 nctx.s_u = LAPD_S_REJ;
487 nctx.p_f = f_bit;
488 nctx.n_recv = dl->v_recv;
489 nctx.length = 0;
490 nctx.more = 0;
491
492 return dl->send_ph_data_req(&nctx, msg);
493}
494
495/* resend SABM or DISC message */
496static int lapd_send_resend(struct lapd_datalink *dl)
497{
498 struct msgb *msg;
499 uint8_t h = do_mod(dl->v_send, dl->range_hist);
500 int length = dl->tx_hist[h].msg->len;
501 struct lapd_msg_ctx nctx;
502
503 /* assemble message */
504 memcpy(&nctx, &dl->lctx, sizeof(nctx));
505 /* keep nctx.ldp */
506 /* keep nctx.sapi */
507 /* keep nctx.tei */
508 nctx.cr = dl->cr.loc2rem.cmd;
509 nctx.format = LAPD_FORM_U;
510 if (dl->state == LAPD_STATE_SABM_SENT)
511 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
512 else
513 nctx.s_u = LAPD_U_DISC;
514 nctx.p_f = 1;
515 nctx.length = length;
516 nctx.more = 0;
517
518 /* Resend SABM/DISC from tx_hist */
519 msg = lapd_msgb_alloc(length, "LAPD resend");
520 msg->l3h = msgb_put(msg, length);
521 if (length)
522 memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
523
524 return dl->send_ph_data_req(&nctx, msg);
525}
526
527/* reestablish link */
528static int lapd_reestablish(struct lapd_datalink *dl)
529{
530 struct osmo_dlsap_prim dp;
531 struct msgb *msg;
532
533 msg = lapd_msgb_alloc(0, "DUMMY");
534 osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg);
535
536 return lapd_est_req(&dp, &dl->lctx);
537}
538
539/* Timer callback on T200 expiry */
540static void lapd_t200_cb(void *data)
541{
542 struct lapd_datalink *dl = data;
543
Andreas Eversberg742fc792011-09-27 09:40:25 +0200544 LOGP(DLLAPD, LOGL_INFO, "Timeout T200 (%p) state=%d\n", dl,
rootaf48bed2011-09-26 11:23:06 +0200545 (int) dl->state);
546
547 switch (dl->state) {
548 case LAPD_STATE_SABM_SENT:
549 /* 5.4.1.3 */
550 if (dl->retrans_ctr + 1 >= dl->n200_est_rel + 1) {
551 /* send RELEASE INDICATION to L3 */
552 send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
553 &dl->lctx);
554 /* send MDL ERROR INIDCATION to L3 */
555 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
556 /* flush tx and send buffers */
557 lapd_dl_flush_tx(dl);
558 lapd_dl_flush_send(dl);
559 /* go back to idle state */
560 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
561 /* NOTE: we must not change any other states or buffers
562 * and queues, since we may reconnect after handover
563 * failure. the buffered messages is replaced there */
564 break;
565 }
566 /* retransmit SABM command */
567 lapd_send_resend(dl);
568 /* increment re-transmission counter */
569 dl->retrans_ctr++;
570 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200571 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200572 break;
573 case LAPD_STATE_DISC_SENT:
574 /* 5.4.4.3 */
575 if (dl->retrans_ctr + 1 >= dl->n200_est_rel + 1) {
576 /* send RELEASE INDICATION to L3 */
577 send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
578 /* send MDL ERROR INIDCATION to L3 */
579 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
580 /* flush tx and send buffers */
581 lapd_dl_flush_tx(dl);
582 lapd_dl_flush_send(dl);
583 /* go back to idle state */
584 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
585 /* NOTE: we must not change any other states or buffers
586 * and queues, since we may reconnect after handover
587 * failure. the buffered messages is replaced there */
588 break;
589 }
590 /* retransmit DISC command */
591 lapd_send_resend(dl);
592 /* increment re-transmission counter */
593 dl->retrans_ctr++;
594 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200595 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200596 break;
597 case LAPD_STATE_MF_EST:
598 /* 5.5.7 */
599 dl->retrans_ctr = 0;
600 lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
601 /* fall through */
602 case LAPD_STATE_TIMER_RECOV:
603 dl->retrans_ctr++;
604 if (dl->retrans_ctr < dl->n200) {
605 uint8_t vs = sub_mod(dl->v_send, 1, dl->v_range);
606 uint8_t h = do_mod(vs, dl->range_hist);
607 /* retransmit I frame (V_s-1) with P=1, if any */
608 if (dl->tx_hist[h].msg) {
609 struct msgb *msg;
610 int length = dl->tx_hist[h].msg->len;
611 struct lapd_msg_ctx nctx;
612
613 LOGP(DLLAPD, LOGL_INFO, "retransmit last frame"
614 " V(S)=%d\n", vs);
615 /* Create I frame (segment) from tx_hist */
616 memcpy(&nctx, &dl->lctx, sizeof(nctx));
617 /* keep nctx.ldp */
618 /* keep nctx.sapi */
619 /* keep nctx.tei */
620 nctx.cr = dl->cr.loc2rem.cmd;
621 nctx.format = LAPD_FORM_I;
622 nctx.p_f = 1;
623 nctx.n_send = vs;
624 nctx.n_recv = dl->v_recv;
625 nctx.length = length;
626 nctx.more = dl->tx_hist[h].more;
627 msg = lapd_msgb_alloc(length, "LAPD I resend");
628 msg->l3h = msgb_put(msg, length);
629 memcpy(msg->l3h, dl->tx_hist[h].msg->data,
630 length);
631 dl->send_ph_data_req(&nctx, msg);
632 } else {
633 /* OR send appropriate supervision frame with P=1 */
634 if (!dl->own_busy && !dl->seq_err_cond) {
635 lapd_send_rr(&dl->lctx, 1, 1);
636 /* NOTE: In case of sequence error
637 * condition, the REJ frame has been
638 * transmitted when entering the
639 * condition, so it has not be done
640 * here
641 */
642 } else if (dl->own_busy) {
643 lapd_send_rnr(&dl->lctx, 1, 1);
644 } else {
645 LOGP(DLLAPD, LOGL_INFO, "unhandled, "
646 "pls. fix\n");
647 }
648 }
649 /* restart T200 (PH-READY-TO-SEND) */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200650 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200651 } else {
652 /* send MDL ERROR INIDCATION to L3 */
653 mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx);
654 /* reestablish */
655 if (!dl->reestablish)
656 break;
657 LOGP(DLLAPD, LOGL_NOTICE, "N200 reached, performing "
658 "reestablishment.\n");
659 lapd_reestablish(dl);
660 }
661 break;
662 default:
663 LOGP(DLLAPD, LOGL_INFO, "T200 expired in unexpected "
664 "dl->state %d\n", (int) dl->state);
665 }
666}
667
668/* Timer callback on T203 expiry */
669static void lapd_t203_cb(void *data)
670{
671 struct lapd_datalink *dl = data;
672
Andreas Eversberg742fc792011-09-27 09:40:25 +0200673 LOGP(DLLAPD, LOGL_INFO, "Timeout T203 (%p) state=%d\n", dl,
rootaf48bed2011-09-26 11:23:06 +0200674 (int) dl->state);
675
676 if (dl->state != LAPD_STATE_MF_EST) {
677 LOGP(DLLAPD, LOGL_ERROR, "T203 fired outside MF EST state, "
678 "please fix!\n");
679 return;
680 }
681
682 /* set retransmission counter to 0 */
683 dl->retrans_ctr = 0;
684 /* enter timer recovery state */
685 lapd_dl_newstate(dl, LAPD_STATE_TIMER_RECOV);
686 /* transmit a supervisory command with P bit set to 1 as follows: */
687 if (!dl->own_busy) {
688 LOGP(DLLAPD, LOGL_INFO, "transmit an RR poll command\n");
689 /* Send RR with P=1 */
690 lapd_send_rr(&dl->lctx, 1, 1);
691 } else {
692 LOGP(DLLAPD, LOGL_INFO, "transmit an RNR poll command\n");
693 /* Send RNR with P=1 */
694 lapd_send_rnr(&dl->lctx, 1, 1);
695 }
696 /* start T200 */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200697 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200698}
699
700/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */
701static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
702{
703 struct lapd_datalink *dl = lctx->dl;
704 uint8_t nr = lctx->n_recv;
Holger Hans Peter Freytherfb6a2e22012-03-16 10:35:38 +0100705 int s = 0, rej = 0, t200_reset = 0;
rootaf48bed2011-09-26 11:23:06 +0200706 int i, h;
707
708 /* supervisory frame ? */
709 if (lctx->format == LAPD_FORM_S)
710 s = 1;
711 /* REJ frame ? */
712 if (s && lctx->s_u == LAPD_S_REJ)
713 rej = 1;
714
715 /* Flush all transmit buffers of acknowledged frames */
716 for (i = dl->v_ack; i != nr; i = inc_mod(i, dl->v_range)) {
717 h = do_mod(i, dl->range_hist);
718 if (dl->tx_hist[h].msg) {
719 msgb_free(dl->tx_hist[h].msg);
720 dl->tx_hist[h].msg = NULL;
721 LOGP(DLLAPD, LOGL_INFO, "ack frame %d\n", i);
722 }
723 }
724
725 if (dl->state != LAPD_STATE_TIMER_RECOV) {
726 /* When not in the timer recovery condition, the data
727 * link layer entity shall reset the timer T200 on
728 * receipt of a valid I frame with N(R) higher than V(A),
729 * or an REJ with an N(R) equal to V(A). */
730 if ((!rej && nr != dl->v_ack)
731 || (rej && nr == dl->v_ack)) {
rootaf48bed2011-09-26 11:23:06 +0200732 t200_reset = 1;
Andreas Eversberg742fc792011-09-27 09:40:25 +0200733 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200734 /* 5.5.3.1 Note 1 + 2 imply timer recovery cond. */
735 }
736 /* 5.7.4: N(R) sequence error
737 * N(R) is called valid, if and only if
738 * (N(R)-V(A)) mod 8 <= (V(S)-V(A)) mod 8.
739 */
740 if (sub_mod(nr, dl->v_ack, dl->v_range)
741 > sub_mod(dl->v_send, dl->v_ack, dl->v_range)) {
742 LOGP(DLLAPD, LOGL_NOTICE, "N(R) sequence error\n");
743 mdl_error(MDL_CAUSE_SEQ_ERR, lctx);
744 }
745 }
746
747 /* V(A) shall be set to the value of N(R) */
748 dl->v_ack = nr;
749
Andreas Eversberg742fc792011-09-27 09:40:25 +0200750 /* If T200 has been stopped by the receipt of an I, RR or RNR frame,
rootaf48bed2011-09-26 11:23:06 +0200751 * and if there are outstanding I frames, restart T200 */
752 if (t200_reset && !rej) {
753 if (dl->tx_hist[sub_mod(dl->v_send, 1, dl->range_hist)].msg) {
754 LOGP(DLLAPD, LOGL_INFO, "start T200, due to unacked I "
755 "frame(s)\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +0200756 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200757 }
758 }
759
760 /* This also does a restart, when I or S frame is received */
761
762 /* Stop T203, if running */
Andreas Eversberg742fc792011-09-27 09:40:25 +0200763 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200764 /* Start T203, if T200 is not running in MF EST state, if enabled */
765 if (!osmo_timer_pending(&dl->t200)
766 && (dl->t203_sec || dl->t203_usec)
767 && (dl->state == LAPD_STATE_MF_EST)) {
Andreas Eversberg742fc792011-09-27 09:40:25 +0200768 lapd_start_t203(dl);
rootaf48bed2011-09-26 11:23:06 +0200769 }
770}
771
772/* L1 -> L2 */
773
774/* Receive a LAPD U (Unnumbered) message from L1 */
775static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
776{
777 struct lapd_datalink *dl = lctx->dl;
778 int length = lctx->length;
Sylvain Munaut9a5f3b82011-11-20 09:01:59 +0100779 int rc = 0;
rootaf48bed2011-09-26 11:23:06 +0200780 uint8_t prim, op;
781
782 switch (lctx->s_u) {
783 case LAPD_U_SABM:
784 case LAPD_U_SABME:
785 prim = PRIM_DL_EST;
786 op = PRIM_OP_INDICATION;
787
788 LOGP(DLLAPD, LOGL_INFO, "SABM(E) received in state %s\n",
789 lapd_state_names[dl->state]);
790 /* 5.7.1 */
791 dl->seq_err_cond = 0;
792 /* G.2.2 Wrong value of the C/R bit */
793 if (lctx->cr == dl->cr.rem2loc.resp) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +0100794 LOGP(DLLAPD, LOGL_ERROR, "SABM response error\n");
rootaf48bed2011-09-26 11:23:06 +0200795 msgb_free(msg);
796 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
797 return -EINVAL;
798 }
799
800 /* G.4.5 If SABM is received with L>N201 or with M bit
801 * set, AN MDL-ERROR-INDICATION is sent to MM.
802 */
803 if (lctx->more || length > lctx->n201) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +0100804 LOGP(DLLAPD, LOGL_ERROR, "SABM too large error\n");
rootaf48bed2011-09-26 11:23:06 +0200805 msgb_free(msg);
806 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
807 return -EIO;
808 }
809
810 switch (dl->state) {
811 case LAPD_STATE_IDLE:
812 break;
813 case LAPD_STATE_MF_EST:
814 LOGP(DLLAPD, LOGL_INFO, "SABM command, multiple "
815 "frame established state\n");
816 /* If link is lost on the remote side, we start over
817 * and send DL-ESTABLISH indication again. */
Andreas Eversberg6e182082013-02-06 14:13:21 +0100818 /* Additionally, continue in case of content resoltion
819 * (GSM network). This happens, if the mobile has not
820 * yet received UA or another mobile (collision) tries
821 * to establish connection. The mobile must receive
822 * UA again. */
Andreas Eversbergccc46332013-06-12 09:25:27 +0200823 /* 5.4.2.1 */
824 if (!length) {
825 /* If no content resolution, this is a
826 * re-establishment. */
827 LOGP(DLLAPD, LOGL_INFO,
828 "Remote reestablish\n");
rootaf48bed2011-09-26 11:23:06 +0200829 break;
830 }
Andreas Eversbergccc46332013-06-12 09:25:27 +0200831 if (!dl->cont_res) {
832 LOGP(DLLAPD, LOGL_INFO, "SABM command not "
833 "allowed in this state\n");
834 mdl_error(MDL_CAUSE_SABM_MF, lctx);
835 msgb_free(msg);
836 return 0;
837 }
rootaf48bed2011-09-26 11:23:06 +0200838 /* Ignore SABM if content differs from first SABM. */
Andreas Eversbergccc46332013-06-12 09:25:27 +0200839 if (dl->mode == LAPD_MODE_NETWORK && length) {
rootaf48bed2011-09-26 11:23:06 +0200840#ifdef TEST_CONTENT_RESOLUTION_NETWORK
841 dl->cont_res->data[0] ^= 0x01;
842#endif
Andreas Eversberg6e182082013-02-06 14:13:21 +0100843 if (memcmp(dl->cont_res->data, msg->data,
844 length)) {
rootaf48bed2011-09-26 11:23:06 +0200845 LOGP(DLLAPD, LOGL_INFO, "Another SABM "
846 "with diffrent content - "
847 "ignoring!\n");
848 msgb_free(msg);
849 return 0;
850 }
851 }
852 /* send UA again */
853 lapd_send_ua(lctx, length, msg->l3h);
854 msgb_free(msg);
855 return 0;
856 case LAPD_STATE_DISC_SENT:
857 /* 5.4.6.2 send DM with F=P */
858 lapd_send_dm(lctx);
Andreas Eversberg742fc792011-09-27 09:40:25 +0200859 /* stop Timer T200 */
860 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200861 msgb_free(msg);
862 return send_dl_simple(prim, op, lctx);
863 default:
864 /* collision: Send UA, but still wait for rx UA, then
865 * change to MF_EST state.
866 */
867 /* check for contention resoultion */
868 if (dl->tx_hist[0].msg && dl->tx_hist[0].msg->len) {
869 LOGP(DLLAPD, LOGL_NOTICE, "SABM not allowed "
870 "during contention resolution\n");
871 mdl_error(MDL_CAUSE_SABM_INFO_NOTALL, lctx);
872 }
873 lapd_send_ua(lctx, length, msg->l3h);
874 msgb_free(msg);
875 return 0;
876 }
877 /* save message context for further use */
878 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
879#ifndef TEST_CONTENT_RESOLUTION_NETWORK
880 /* send UA response */
881 lapd_send_ua(lctx, length, msg->l3h);
882#endif
883 /* set Vs, Vr and Va to 0 */
884 dl->v_send = dl->v_recv = dl->v_ack = 0;
885 /* clear tx_hist */
886 lapd_dl_flush_hist(dl);
887 /* enter multiple-frame-established state */
888 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
889 /* store content resolution data on network side
890 * Note: cont_res will be removed when changing state again,
891 * so it must be allocated AFTER lapd_dl_newstate(). */
892 if (dl->mode == LAPD_MODE_NETWORK && length) {
893 dl->cont_res = lapd_msgb_alloc(length, "CONT RES");
894 memcpy(msgb_put(dl->cont_res, length), msg->l3h,
895 length);
896 LOGP(DLLAPD, LOGL_NOTICE, "Store content res.\n");
897 }
898 /* send notification to L3 */
899 if (length == 0) {
900 /* 5.4.1.2 Normal establishment procedures */
901 rc = send_dl_simple(prim, op, lctx);
902 msgb_free(msg);
903 } else {
904 /* 5.4.1.4 Contention resolution establishment */
Harald Welte087116a2013-06-18 21:41:34 +0200905 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +0200906 rc = send_dl_l3(prim, op, lctx, msg);
907 }
908 break;
909 case LAPD_U_DM:
910 LOGP(DLLAPD, LOGL_INFO, "DM received in state %s\n",
911 lapd_state_names[dl->state]);
912 /* G.2.2 Wrong value of the C/R bit */
913 if (lctx->cr == dl->cr.rem2loc.cmd) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +0100914 LOGP(DLLAPD, LOGL_ERROR, "DM command error\n");
rootaf48bed2011-09-26 11:23:06 +0200915 msgb_free(msg);
916 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
917 return -EINVAL;
918 }
919 if (!lctx->p_f) {
920 /* 5.4.1.2 DM responses with the F bit set to "0"
921 * shall be ignored.
922 */
923 msgb_free(msg);
924 return 0;
925 }
926 switch (dl->state) {
927 case LAPD_STATE_SABM_SENT:
928 break;
929 case LAPD_STATE_MF_EST:
930 if (lctx->p_f) {
931 LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
932 "response\n");
933 mdl_error(MDL_CAUSE_UNSOL_DM_RESP, lctx);
934 } else {
935 LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
936 "response, multiple frame established "
937 "state\n");
938 mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
939 /* reestablish */
940 if (!dl->reestablish) {
941 msgb_free(msg);
942 return 0;
943 }
944 LOGP(DLLAPD, LOGL_NOTICE, "Performing "
945 "reestablishment.\n");
946 lapd_reestablish(dl);
947 }
948 msgb_free(msg);
949 return 0;
950 case LAPD_STATE_TIMER_RECOV:
951 /* FP = 0 (DM is normal in case PF = 1) */
952 if (!lctx->p_f) {
953 LOGP(DLLAPD, LOGL_INFO, "unsolicited DM "
954 "response, multiple frame established "
955 "state\n");
956 mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);
957 msgb_free(msg);
958 /* reestablish */
959 if (!dl->reestablish)
960 return 0;
961 LOGP(DLLAPD, LOGL_NOTICE, "Performing "
962 "reestablishment.\n");
963 return lapd_reestablish(dl);
964 }
965 break;
966 case LAPD_STATE_DISC_SENT:
Andreas Eversberg742fc792011-09-27 09:40:25 +0200967 /* stop Timer T200 */
968 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200969 /* go to idle state */
970 lapd_dl_flush_tx(dl);
971 lapd_dl_flush_send(dl);
972 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
973 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
974 msgb_free(msg);
975 return 0;
976 case LAPD_STATE_IDLE:
977 /* 5.4.5 all other frame types shall be discarded */
978 default:
979 LOGP(DLLAPD, LOGL_INFO, "unsolicited DM response! "
980 "(discarding)\n");
981 msgb_free(msg);
982 return 0;
983 }
Andreas Eversberg742fc792011-09-27 09:40:25 +0200984 /* stop timer T200 */
985 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +0200986 /* go to idle state */
987 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
988 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);
989 msgb_free(msg);
990 break;
991 case LAPD_U_UI:
992 LOGP(DLLAPD, LOGL_INFO, "UI received\n");
993 /* G.2.2 Wrong value of the C/R bit */
994 if (lctx->cr == dl->cr.rem2loc.resp) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +0100995 LOGP(DLLAPD, LOGL_ERROR, "UI indicates response "
rootaf48bed2011-09-26 11:23:06 +0200996 "error\n");
997 msgb_free(msg);
998 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
999 return -EINVAL;
1000 }
1001
1002 /* G.4.5 If UI is received with L>N201 or with M bit
1003 * set, AN MDL-ERROR-INDICATION is sent to MM.
1004 */
1005 if (length > lctx->n201 || lctx->more) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001006 LOGP(DLLAPD, LOGL_ERROR, "UI too large error "
rootaf48bed2011-09-26 11:23:06 +02001007 "(%d > N201(%d) or M=%d)\n", length,
1008 lctx->n201, lctx->more);
1009 msgb_free(msg);
1010 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1011 return -EIO;
1012 }
1013
1014 /* do some length checks */
1015 if (length == 0) {
1016 /* 5.3.3 UI frames received with the length indicator
1017 * set to "0" shall be ignored
1018 */
1019 LOGP(DLLAPD, LOGL_INFO, "length=0 (discarding)\n");
1020 msgb_free(msg);
1021 return 0;
1022 }
Harald Welte087116a2013-06-18 21:41:34 +02001023 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +02001024 rc = send_dl_l3(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION, lctx,
1025 msg);
1026 break;
1027 case LAPD_U_DISC:
1028 prim = PRIM_DL_REL;
1029 op = PRIM_OP_INDICATION;
1030
1031 LOGP(DLLAPD, LOGL_INFO, "DISC received in state %s\n",
1032 lapd_state_names[dl->state]);
1033 /* flush tx and send buffers */
1034 lapd_dl_flush_tx(dl);
1035 lapd_dl_flush_send(dl);
1036 /* 5.7.1 */
1037 dl->seq_err_cond = 0;
1038 /* G.2.2 Wrong value of the C/R bit */
1039 if (lctx->cr == dl->cr.rem2loc.resp) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001040 LOGP(DLLAPD, LOGL_ERROR, "DISC response error\n");
rootaf48bed2011-09-26 11:23:06 +02001041 msgb_free(msg);
1042 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1043 return -EINVAL;
1044 }
1045 if (length > 0 || lctx->more) {
1046 /* G.4.4 If a DISC or DM frame is received with L>0 or
1047 * with the M bit set to "1", an MDL-ERROR-INDICATION
1048 * primitive with cause "U frame with incorrect
1049 * parameters" is sent to the mobile management entity.
1050 */
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001051 LOGP(DLLAPD, LOGL_ERROR,
rootaf48bed2011-09-26 11:23:06 +02001052 "U frame iwth incorrect parameters ");
1053 msgb_free(msg);
1054 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1055 return -EIO;
1056 }
1057 switch (dl->state) {
1058 case LAPD_STATE_IDLE:
1059 LOGP(DLLAPD, LOGL_INFO, "DISC in idle state\n");
1060 /* send DM with F=P */
1061 msgb_free(msg);
1062 return lapd_send_dm(lctx);
1063 case LAPD_STATE_SABM_SENT:
1064 LOGP(DLLAPD, LOGL_INFO, "DISC in SABM state\n");
1065 /* 5.4.6.2 send DM with F=P */
1066 lapd_send_dm(lctx);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001067 /* stop Timer T200 */
1068 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001069 /* go to idle state */
1070 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1071 msgb_free(msg);
1072 return send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,
1073 lctx);
1074 case LAPD_STATE_MF_EST:
1075 case LAPD_STATE_TIMER_RECOV:
1076 LOGP(DLLAPD, LOGL_INFO, "DISC in est state\n");
1077 break;
1078 case LAPD_STATE_DISC_SENT:
1079 LOGP(DLLAPD, LOGL_INFO, "DISC in disc state\n");
1080 prim = PRIM_DL_REL;
1081 op = PRIM_OP_CONFIRM;
1082 break;
1083 default:
1084 lapd_send_ua(lctx, length, msg->l3h);
1085 msgb_free(msg);
1086 return 0;
1087 }
1088 /* send UA response */
1089 lapd_send_ua(lctx, length, msg->l3h);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001090 /* stop Timer T200 */
1091 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001092 /* enter idle state, keep tx-buffer with UA response */
1093 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1094 /* send notification to L3 */
1095 rc = send_dl_simple(prim, op, lctx);
1096 msgb_free(msg);
1097 break;
1098 case LAPD_U_UA:
1099 LOGP(DLLAPD, LOGL_INFO, "UA received in state %s\n",
1100 lapd_state_names[dl->state]);
1101 /* G.2.2 Wrong value of the C/R bit */
1102 if (lctx->cr == dl->cr.rem2loc.cmd) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001103 LOGP(DLLAPD, LOGL_ERROR, "UA indicates command "
rootaf48bed2011-09-26 11:23:06 +02001104 "error\n");
1105 msgb_free(msg);
1106 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1107 return -EINVAL;
1108 }
1109
1110 /* G.4.5 If UA is received with L>N201 or with M bit
1111 * set, AN MDL-ERROR-INDICATION is sent to MM.
1112 */
1113 if (lctx->more || length > lctx->n201) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001114 LOGP(DLLAPD, LOGL_ERROR, "UA too large error\n");
rootaf48bed2011-09-26 11:23:06 +02001115 msgb_free(msg);
1116 mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);
1117 return -EIO;
1118 }
1119
1120 if (!lctx->p_f) {
1121 /* 5.4.1.2 A UA response with the F bit set to "0"
1122 * shall be ignored.
1123 */
1124 LOGP(DLLAPD, LOGL_INFO, "F=0 (discarding)\n");
1125 msgb_free(msg);
1126 return 0;
1127 }
1128 switch (dl->state) {
1129 case LAPD_STATE_SABM_SENT:
1130 break;
1131 case LAPD_STATE_MF_EST:
1132 case LAPD_STATE_TIMER_RECOV:
1133 LOGP(DLLAPD, LOGL_INFO, "unsolicited UA response! "
1134 "(discarding)\n");
1135 mdl_error(MDL_CAUSE_UNSOL_UA_RESP, lctx);
1136 msgb_free(msg);
1137 return 0;
1138 case LAPD_STATE_DISC_SENT:
1139 LOGP(DLLAPD, LOGL_INFO, "UA in disconnect state\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +02001140 /* stop Timer T200 */
1141 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001142 /* go to idle state */
1143 lapd_dl_flush_tx(dl);
1144 lapd_dl_flush_send(dl);
1145 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1146 rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);
1147 msgb_free(msg);
1148 return 0;
1149 case LAPD_STATE_IDLE:
1150 /* 5.4.5 all other frame types shall be discarded */
1151 default:
1152 LOGP(DLLAPD, LOGL_INFO, "unsolicited UA response! "
1153 "(discarding)\n");
1154 msgb_free(msg);
1155 return 0;
1156 }
1157 LOGP(DLLAPD, LOGL_INFO, "UA in SABM state\n");
Andreas Eversberg742fc792011-09-27 09:40:25 +02001158 /* stop Timer T200 */
1159 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001160 /* compare UA with SABME if contention resolution is applied */
1161 if (dl->tx_hist[0].msg->len) {
1162 if (length != (dl->tx_hist[0].msg->len)
1163 || !!memcmp(dl->tx_hist[0].msg->data, msg->l3h,
1164 length)) {
1165 LOGP(DLLAPD, LOGL_INFO, "**** UA response "
1166 "mismatches ****\n");
1167 rc = send_dl_simple(PRIM_DL_REL,
1168 PRIM_OP_INDICATION, lctx);
1169 msgb_free(msg);
1170 /* go to idle state */
1171 lapd_dl_flush_tx(dl);
1172 lapd_dl_flush_send(dl);
1173 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
1174 return 0;
1175 }
1176 }
1177 /* set Vs, Vr and Va to 0 */
1178 dl->v_send = dl->v_recv = dl->v_ack = 0;
1179 /* clear tx_hist */
1180 lapd_dl_flush_hist(dl);
1181 /* enter multiple-frame-established state */
1182 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1183 /* send outstanding frames, if any (resume / reconnect) */
1184 lapd_send_i(lctx, __LINE__);
1185 /* send notification to L3 */
1186 rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx);
1187 msgb_free(msg);
1188 break;
1189 case LAPD_U_FRMR:
1190 LOGP(DLLAPD, LOGL_NOTICE, "Frame reject received\n");
1191 /* send MDL ERROR INIDCATION to L3 */
1192 mdl_error(MDL_CAUSE_FRMR, lctx);
1193 msgb_free(msg);
1194 /* reestablish */
1195 if (!dl->reestablish)
1196 break;
1197 LOGP(DLLAPD, LOGL_NOTICE, "Performing reestablishment.\n");
1198 rc = lapd_reestablish(dl);
1199 break;
1200 default:
1201 /* G.3.1 */
1202 LOGP(DLLAPD, LOGL_NOTICE, "Unnumbered frame not allowed.\n");
1203 msgb_free(msg);
1204 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1205 return -EINVAL;
1206 }
1207 return rc;
1208}
1209
1210/* Receive a LAPD S (Supervisory) message from L1 */
1211static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)
1212{
1213 struct lapd_datalink *dl = lctx->dl;
1214 int length = lctx->length;
1215
1216 if (length > 0 || lctx->more) {
1217 /* G.4.3 If a supervisory frame is received with L>0 or
1218 * with the M bit set to "1", an MDL-ERROR-INDICATION
1219 * primitive with cause "S frame with incorrect
1220 * parameters" is sent to the mobile management entity. */
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001221 LOGP(DLLAPD, LOGL_ERROR,
rootaf48bed2011-09-26 11:23:06 +02001222 "S frame with incorrect parameters\n");
1223 msgb_free(msg);
1224 mdl_error(MDL_CAUSE_SFRM_INC_PARAM, lctx);
1225 return -EIO;
1226 }
1227
1228 if (lctx->cr == dl->cr.rem2loc.resp
1229 && lctx->p_f
1230 && dl->state != LAPD_STATE_TIMER_RECOV) {
1231 /* 5.4.2.2: Inidcate error on supervisory reponse F=1 */
1232 LOGP(DLLAPD, LOGL_NOTICE, "S frame response with F=1 error\n");
1233 mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
1234 }
1235
1236 switch (dl->state) {
1237 case LAPD_STATE_IDLE:
1238 /* if P=1, respond DM with F=1 (5.2.2) */
1239 /* 5.4.5 all other frame types shall be discarded */
1240 if (lctx->p_f)
1241 lapd_send_dm(lctx); /* F=P */
1242 /* fall though */
1243 case LAPD_STATE_SABM_SENT:
1244 case LAPD_STATE_DISC_SENT:
1245 LOGP(DLLAPD, LOGL_NOTICE, "S frame ignored in this state\n");
1246 msgb_free(msg);
1247 return 0;
1248 }
1249 switch (lctx->s_u) {
1250 case LAPD_S_RR:
1251 LOGP(DLLAPD, LOGL_INFO, "RR received in state %s\n",
1252 lapd_state_names[dl->state]);
1253 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1254 lapd_acknowledge(lctx);
1255
1256 /* 5.5.3.2 */
1257 if (lctx->cr == dl->cr.rem2loc.cmd
1258 && lctx->p_f) {
1259 if (!dl->own_busy && !dl->seq_err_cond) {
1260 LOGP(DLLAPD, LOGL_INFO, "RR frame command "
1261 "with polling bit set and we are not "
1262 "busy, so we reply with RR frame "
1263 "response\n");
1264 lapd_send_rr(lctx, 1, 0);
1265 /* NOTE: In case of sequence error condition,
1266 * the REJ frame has been transmitted when
1267 * entering the condition, so it has not be
1268 * done here
1269 */
1270 } else if (dl->own_busy) {
1271 LOGP(DLLAPD, LOGL_INFO, "RR frame command "
1272 "with polling bit set and we are busy, "
1273 "so we reply with RR frame response\n");
1274 lapd_send_rnr(lctx, 1, 0);
1275 }
1276 } else if (lctx->cr == dl->cr.rem2loc.resp
1277 && lctx->p_f
1278 && dl->state == LAPD_STATE_TIMER_RECOV) {
1279 LOGP(DLLAPD, LOGL_INFO, "RR response with F==1, "
1280 "and we are in timer recovery state, so "
1281 "we leave that state\n");
1282 /* V(S) to the N(R) in the RR frame */
1283 dl->v_send = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001284 /* stop Timer T200 */
1285 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001286 /* 5.5.7 Clear timer recovery condition */
1287 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1288 }
1289 /* Send message, if possible due to acknowledged data */
1290 lapd_send_i(lctx, __LINE__);
1291
1292 break;
1293 case LAPD_S_RNR:
1294 LOGP(DLLAPD, LOGL_INFO, "RNR received in state %s\n",
1295 lapd_state_names[dl->state]);
1296 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1297 lapd_acknowledge(lctx);
1298
1299 /* 5.5.5 */
1300 /* Set peer receiver busy condition */
1301 dl->peer_busy = 1;
1302
1303 if (lctx->p_f) {
1304 if (lctx->cr == dl->cr.rem2loc.cmd) {
1305 if (!dl->own_busy) {
1306 LOGP(DLLAPD, LOGL_INFO, "RNR poll "
1307 "command and we are not busy, "
1308 "so we reply with RR final "
1309 "response\n");
1310 /* Send RR with F=1 */
1311 lapd_send_rr(lctx, 1, 0);
1312 } else {
1313 LOGP(DLLAPD, LOGL_INFO, "RNR poll "
1314 "command and we are busy, so "
1315 "we reply with RNR final "
1316 "response\n");
1317 /* Send RNR with F=1 */
1318 lapd_send_rnr(lctx, 1, 0);
1319 }
1320 } else if (dl->state == LAPD_STATE_TIMER_RECOV) {
1321 LOGP(DLLAPD, LOGL_INFO, "RNR poll response "
1322 "and we in timer recovery state, so "
1323 "we leave that state\n");
1324 /* 5.5.7 Clear timer recovery condition */
1325 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1326 /* V(S) to the N(R) in the RNR frame */
1327 dl->v_send = lctx->n_recv;
1328 }
1329 } else
1330 LOGP(DLLAPD, LOGL_INFO, "RNR not polling/final state "
1331 "received\n");
1332
1333 /* Send message, if possible due to acknowledged data */
1334 lapd_send_i(lctx, __LINE__);
1335
1336 break;
1337 case LAPD_S_REJ:
1338 LOGP(DLLAPD, LOGL_INFO, "REJ received in state %s\n",
1339 lapd_state_names[dl->state]);
1340 /* 5.5.3.1: Acknowlege all tx frames up the the N(R)-1 */
1341 lapd_acknowledge(lctx);
1342
1343 /* 5.5.4.1 */
1344 if (dl->state != LAPD_STATE_TIMER_RECOV) {
1345 /* Clear an existing peer receiver busy condition */
1346 dl->peer_busy = 0;
1347 /* V(S) and V(A) to the N(R) in the REJ frame */
1348 dl->v_send = dl->v_ack = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001349 /* stop Timer T200 */
1350 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001351 /* 5.5.3.2 */
1352 if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
1353 if (!dl->own_busy && !dl->seq_err_cond) {
1354 LOGP(DLLAPD, LOGL_INFO, "REJ poll "
1355 "command not in timer recovery "
1356 "state and not in own busy "
1357 "condition received, so we "
1358 "respond with RR final "
1359 "response\n");
1360 lapd_send_rr(lctx, 1, 0);
1361 /* NOTE: In case of sequence error
1362 * condition, the REJ frame has been
1363 * transmitted when entering the
1364 * condition, so it has not be done
1365 * here
1366 */
1367 } else if (dl->own_busy) {
1368 LOGP(DLLAPD, LOGL_INFO, "REJ poll "
1369 "command not in timer recovery "
1370 "state and in own busy "
1371 "condition received, so we "
1372 "respond with RNR final "
1373 "response\n");
1374 lapd_send_rnr(lctx, 1, 0);
1375 }
1376 } else
1377 LOGP(DLLAPD, LOGL_INFO, "REJ response or not "
1378 "polling command not in timer recovery "
1379 "state received\n");
1380 /* send MDL ERROR INIDCATION to L3 */
1381 if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
1382 mdl_error(MDL_CAUSE_UNSOL_SPRV_RESP, lctx);
1383 }
1384
1385 } else if (lctx->cr == dl->cr.rem2loc.resp && lctx->p_f) {
1386 LOGP(DLLAPD, LOGL_INFO, "REJ poll response in timer "
1387 "recovery state received\n");
1388 /* Clear an existing peer receiver busy condition */
1389 dl->peer_busy = 0;
1390 /* V(S) and V(A) to the N(R) in the REJ frame */
1391 dl->v_send = dl->v_ack = lctx->n_recv;
Andreas Eversberg742fc792011-09-27 09:40:25 +02001392 /* stop Timer T200 */
1393 lapd_stop_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001394 /* 5.5.7 Clear timer recovery condition */
1395 lapd_dl_newstate(dl, LAPD_STATE_MF_EST);
1396 } else {
1397 /* Clear an existing peer receiver busy condition */
1398 dl->peer_busy = 0;
1399 /* V(S) and V(A) to the N(R) in the REJ frame */
1400 dl->v_send = dl->v_ack = lctx->n_recv;
1401 /* 5.5.3.2 */
1402 if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) {
1403 if (!dl->own_busy && !dl->seq_err_cond) {
1404 LOGP(DLLAPD, LOGL_INFO, "REJ poll "
1405 "command in timer recovery "
1406 "state and not in own busy "
1407 "condition received, so we "
1408 "respond with RR final "
1409 "response\n");
1410 lapd_send_rr(lctx, 1, 0);
1411 /* NOTE: In case of sequence error
1412 * condition, the REJ frame has been
1413 * transmitted when entering the
1414 * condition, so it has not be done
1415 * here
1416 */
1417 } else if (dl->own_busy) {
1418 LOGP(DLLAPD, LOGL_INFO, "REJ poll "
1419 "command in timer recovery "
1420 "state and in own busy "
1421 "condition received, so we "
1422 "respond with RNR final "
1423 "response\n");
1424 lapd_send_rnr(lctx, 1, 0);
1425 }
1426 } else
1427 LOGP(DLLAPD, LOGL_INFO, "REJ response or not "
1428 "polling command in timer recovery "
1429 "state received\n");
1430 }
1431
1432 /* FIXME: 5.5.4.2 2) */
1433
1434 /* Send message, if possible due to acknowledged data */
1435 lapd_send_i(lctx, __LINE__);
1436
1437 break;
1438 default:
1439 /* G.3.1 */
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001440 LOGP(DLLAPD, LOGL_ERROR, "Supervisory frame not allowed.\n");
rootaf48bed2011-09-26 11:23:06 +02001441 msgb_free(msg);
1442 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1443 return -EINVAL;
1444 }
1445 msgb_free(msg);
1446 return 0;
1447}
1448
1449/* Receive a LAPD I (Information) message from L1 */
1450static int lapd_rx_i(struct msgb *msg, struct lapd_msg_ctx *lctx)
1451{
1452 struct lapd_datalink *dl = lctx->dl;
1453 //uint8_t nr = lctx->n_recv;
1454 uint8_t ns = lctx->n_send;
1455 int length = lctx->length;
1456 int rc;
1457
1458 LOGP(DLLAPD, LOGL_INFO, "I received in state %s\n",
1459 lapd_state_names[dl->state]);
1460
1461 /* G.2.2 Wrong value of the C/R bit */
1462 if (lctx->cr == dl->cr.rem2loc.resp) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001463 LOGP(DLLAPD, LOGL_ERROR, "I frame response not allowed\n");
rootaf48bed2011-09-26 11:23:06 +02001464 msgb_free(msg);
1465 mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);
1466 return -EINVAL;
1467 }
1468
1469 if (length == 0 || length > lctx->n201) {
1470 /* G.4.2 If the length indicator of an I frame is set
1471 * to a numerical value L>N201 or L=0, an MDL-ERROR-INDICATION
1472 * primitive with cause "I frame with incorrect length"
1473 * is sent to the mobile management entity. */
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001474 LOGP(DLLAPD, LOGL_ERROR, "I frame length not allowed\n");
rootaf48bed2011-09-26 11:23:06 +02001475 msgb_free(msg);
1476 mdl_error(MDL_CAUSE_IFRM_INC_LEN, lctx);
1477 return -EIO;
1478 }
1479
1480 /* G.4.2 If the numerical value of L is L<N201 and the M
1481 * bit is set to "1", then an MDL-ERROR-INDICATION primitive with
1482 * cause "I frame with incorrect use of M bit" is sent to the
1483 * mobile management entity. */
1484 if (lctx->more && length < lctx->n201) {
Holger Hans Peter Freyther8c012312012-11-26 16:52:23 +01001485 LOGP(DLLAPD, LOGL_ERROR, "I frame with M bit too short\n");
rootaf48bed2011-09-26 11:23:06 +02001486 msgb_free(msg);
1487 mdl_error(MDL_CAUSE_IFRM_INC_MBITS, lctx);
1488 return -EIO;
1489 }
1490
1491 switch (dl->state) {
1492 case LAPD_STATE_IDLE:
1493 /* if P=1, respond DM with F=1 (5.2.2) */
1494 /* 5.4.5 all other frame types shall be discarded */
1495 if (lctx->p_f)
1496 lapd_send_dm(lctx); /* F=P */
1497 /* fall though */
1498 case LAPD_STATE_SABM_SENT:
1499 case LAPD_STATE_DISC_SENT:
1500 LOGP(DLLAPD, LOGL_NOTICE, "I frame ignored in this state\n");
1501 msgb_free(msg);
1502 return 0;
1503 }
1504
1505 /* 5.7.1: N(s) sequence error */
1506 if (ns != dl->v_recv) {
1507 LOGP(DLLAPD, LOGL_NOTICE, "N(S) sequence error: N(S)=%u, "
1508 "V(R)=%u\n", ns, dl->v_recv);
1509 /* discard data */
1510 msgb_free(msg);
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001511 if (dl->seq_err_cond != 1) {
rootaf48bed2011-09-26 11:23:06 +02001512 /* FIXME: help me understand what exactly todo here
rootaf48bed2011-09-26 11:23:06 +02001513 */
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001514 dl->seq_err_cond = 1;
rootaf48bed2011-09-26 11:23:06 +02001515 lapd_send_rej(lctx, lctx->p_f);
1516 } else {
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001517 /* If there are two subsequent sequence errors received,
1518 * ignore it. (Ignore every second subsequent error.)
1519 * This happens if our reply with the REJ is too slow,
1520 * so the remote gets a T200 timeout and sends another
1521 * frame with a sequence error.
1522 * Test showed that replying with two subsequent REJ
1523 * messages could the remote L2 process to abort.
1524 * Replying too slow shouldn't happen, but may happen
1525 * over serial link between BB and LAPD.
1526 */
1527 dl->seq_err_cond = 2;
rootaf48bed2011-09-26 11:23:06 +02001528 }
Andreas.Eversberg301f01e2012-01-10 13:02:01 +01001529 /* Even if N(s) sequence error, acknowledge to N(R)-1 */
1530 /* 5.5.3.1: Acknowlege all transmitted frames up the N(R)-1 */
1531 lapd_acknowledge(lctx); /* V(A) is also set here */
1532
1533 /* Send message, if possible due to acknowledged data */
1534 lapd_send_i(lctx, __LINE__);
1535
1536 return 0;
rootaf48bed2011-09-26 11:23:06 +02001537 }
1538 dl->seq_err_cond = 0;
1539
1540 /* Increment receiver state */
1541 dl->v_recv = inc_mod(dl->v_recv, dl->v_range);
1542 LOGP(DLLAPD, LOGL_INFO, "incrementing V(R) to %u\n", dl->v_recv);
1543
1544 /* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */
1545 lapd_acknowledge(lctx); /* V(A) is also set here */
1546
1547 /* Only if we are not in own receiver busy condition */
1548 if (!dl->own_busy) {
1549 /* if the frame carries a complete segment */
1550 if (!lctx->more && !dl->rcv_buffer) {
1551 LOGP(DLLAPD, LOGL_INFO, "message in single I frame\n");
1552 /* send a DATA INDICATION to L3 */
Harald Welte087116a2013-06-18 21:41:34 +02001553 msgb_trim(msg, length);
rootaf48bed2011-09-26 11:23:06 +02001554 rc = send_dl_l3(PRIM_DL_DATA, PRIM_OP_INDICATION, lctx,
1555 msg);
1556 } else {
1557 /* create rcv_buffer */
1558 if (!dl->rcv_buffer) {
1559 LOGP(DLLAPD, LOGL_INFO, "message in multiple "
1560 "I frames (first message)\n");
1561 dl->rcv_buffer = lapd_msgb_alloc(dl->maxf,
1562 "LAPD RX");
1563 dl->rcv_buffer->l3h = dl->rcv_buffer->data;
1564 }
1565 /* concat. rcv_buffer */
1566 if (msgb_l3len(dl->rcv_buffer) + length > dl->maxf) {
1567 LOGP(DLLAPD, LOGL_NOTICE, "Received frame "
1568 "overflow!\n");
1569 } else {
1570 memcpy(msgb_put(dl->rcv_buffer, length),
1571 msg->l3h, length);
1572 }
1573 /* if the last segment was received */
1574 if (!lctx->more) {
1575 LOGP(DLLAPD, LOGL_INFO, "message in multiple "
1576 "I frames (last message)\n");
1577 rc = send_dl_l3(PRIM_DL_DATA,
1578 PRIM_OP_INDICATION, lctx,
1579 dl->rcv_buffer);
1580 dl->rcv_buffer = NULL;
1581 } else
1582 LOGP(DLLAPD, LOGL_INFO, "message in multiple "
1583 "I frames (next message)\n");
1584 msgb_free(msg);
1585
1586 }
1587 } else
1588 LOGP(DLLAPD, LOGL_INFO, "I frame ignored during own receiver "
1589 "busy condition\n");
1590
1591 /* Check for P bit */
1592 if (lctx->p_f) {
1593 /* 5.5.2.1 */
1594 /* check if we are not in own receiver busy */
1595 if (!dl->own_busy) {
1596 LOGP(DLLAPD, LOGL_INFO, "we are not busy, send RR\n");
1597 /* Send RR with F=1 */
1598 rc = lapd_send_rr(lctx, 1, 0);
1599 } else {
1600 LOGP(DLLAPD, LOGL_INFO, "we are busy, send RNR\n");
1601 /* Send RNR with F=1 */
1602 rc = lapd_send_rnr(lctx, 1, 0);
1603 }
1604 } else {
1605 /* 5.5.2.2 */
1606 /* check if we are not in own receiver busy */
1607 if (!dl->own_busy) {
1608 /* NOTE: V(R) is already set above */
1609 rc = lapd_send_i(lctx, __LINE__);
1610 if (rc) {
1611 LOGP(DLLAPD, LOGL_INFO, "we are not busy and "
1612 "have no pending data, send RR\n");
1613 /* Send RR with F=0 */
1614 return lapd_send_rr(lctx, 0, 0);
1615 }
1616 /* all I or one RR is sent, we are done */
1617 return 0;
1618 } else {
1619 LOGP(DLLAPD, LOGL_INFO, "we are busy, send RNR\n");
1620 /* Send RNR with F=0 */
1621 rc = lapd_send_rnr(lctx, 0, 0);
1622 }
1623 }
1624
1625 /* Send message, if possible due to acknowledged data */
1626 lapd_send_i(lctx, __LINE__);
1627
1628 return rc;
1629}
1630
1631/* Receive a LAPD message from L1 */
1632int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx)
1633{
1634 int rc;
1635
1636 switch (lctx->format) {
1637 case LAPD_FORM_U:
1638 rc = lapd_rx_u(msg, lctx);
1639 break;
1640 case LAPD_FORM_S:
1641 rc = lapd_rx_s(msg, lctx);
1642 break;
1643 case LAPD_FORM_I:
1644 rc = lapd_rx_i(msg, lctx);
1645 break;
1646 default:
1647 LOGP(DLLAPD, LOGL_NOTICE, "unknown LAPD format\n");
1648 msgb_free(msg);
1649 rc = -EINVAL;
1650 }
1651 return rc;
1652}
1653
1654/* L3 -> L2 */
1655
1656/* send unit data */
1657static int lapd_udata_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1658{
1659 struct lapd_datalink *dl = lctx->dl;
1660 struct msgb *msg = dp->oph.msg;
1661 struct lapd_msg_ctx nctx;
1662
1663 memcpy(&nctx, lctx, sizeof(nctx));
1664 /* keep nctx.ldp */
1665 /* keep nctx.sapi */
1666 /* keep nctx.tei */
1667 nctx.cr = dl->cr.loc2rem.cmd;
1668 nctx.format = LAPD_FORM_U;
1669 nctx.s_u = LAPD_U_UI;
1670 /* keep nctx.p_f */
1671 nctx.length = msg->len;
1672 nctx.more = 0;
1673
1674 return dl->send_ph_data_req(&nctx, msg);
1675}
1676
1677/* request link establishment */
1678static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1679{
1680 struct lapd_datalink *dl = lctx->dl;
1681 struct msgb *msg = dp->oph.msg;
1682 struct lapd_msg_ctx nctx;
1683
1684 if (msg->len)
1685 LOGP(DLLAPD, LOGL_INFO, "perform establishment with content "
1686 "(SABM)\n");
1687 else
1688 LOGP(DLLAPD, LOGL_INFO, "perform normal establishm. (SABM)\n");
1689
1690 /* Flush send-queue */
1691 /* Clear send-buffer */
1692 lapd_dl_flush_send(dl);
1693 /* be sure that history is empty */
1694 lapd_dl_flush_hist(dl);
1695
1696 /* save message context for further use */
1697 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
1698
1699 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001700 msgb_free(dl->rcv_buffer);
1701 dl->rcv_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +02001702
1703 /* assemble message */
1704 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1705 /* keep nctx.ldp */
1706 /* keep nctx.sapi */
1707 /* keep nctx.tei */
1708 nctx.cr = dl->cr.loc2rem.cmd;
1709 nctx.format = LAPD_FORM_U;
1710 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
1711 nctx.p_f = 1;
1712 nctx.length = msg->len;
1713 nctx.more = 0;
1714
1715 /* Transmit-buffer carries exactly one segment */
1716 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
1717 msgb_put(dl->tx_hist[0].msg, msg->len);
1718 if (msg->len)
1719 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
1720 dl->tx_hist[0].more = 0;
1721 /* set Vs to 0, because it is used as index when resending SABM */
1722 dl->v_send = 0;
1723
1724 /* Set states */
1725 dl->own_busy = dl->peer_busy = 0;
1726 dl->retrans_ctr = 0;
1727 lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
1728
1729 /* Tramsmit and start T200 */
1730 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001731 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001732
1733 return 0;
1734}
1735
1736/* send data */
1737static int lapd_data_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1738{
1739 struct lapd_datalink *dl = lctx->dl;
1740 struct msgb *msg = dp->oph.msg;
1741
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +08001742 if (msgb_l3len(msg) == 0) {
1743 LOGP(DLLAPD, LOGL_ERROR,
1744 "writing an empty message is not possible.\n");
1745 msgb_free(msg);
1746 return -1;
1747 }
1748
Holger Hans Peter Freyther6ecafef2012-01-13 05:46:26 +08001749 LOGP(DLLAPD, LOGL_INFO,
1750 "writing message to send-queue: l3len: %d\n", msgb_l3len(msg));
rootaf48bed2011-09-26 11:23:06 +02001751
1752 /* Write data into the send queue */
1753 msgb_enqueue(&dl->send_queue, msg);
1754
1755 /* Send message, if possible */
1756 lapd_send_i(&dl->lctx, __LINE__);
1757
1758 return 0;
1759}
1760
1761/* Send next I frame from queued/buffered data */
1762static int lapd_send_i(struct lapd_msg_ctx *lctx, int line)
1763{
1764 struct lapd_datalink *dl = lctx->dl;
1765 uint8_t k = dl->k;
1766 uint8_t h;
1767 struct msgb *msg;
1768 int length, left;
1769 int rc = - 1; /* we sent nothing */
1770 struct lapd_msg_ctx nctx;
1771
1772
1773 LOGP(DLLAPD, LOGL_INFO, "%s() called from line %d\n", __func__, line);
1774
1775 next_frame:
1776
1777 if (dl->peer_busy) {
1778 LOGP(DLLAPD, LOGL_INFO, "peer busy, not sending\n");
1779 return rc;
1780 }
1781
1782 if (dl->state == LAPD_STATE_TIMER_RECOV) {
1783 LOGP(DLLAPD, LOGL_INFO, "timer recovery, not sending\n");
1784 return rc;
1785 }
1786
1787 /* If the send state variable V(S) is equal to V(A) plus k
1788 * (where k is the maximum number of outstanding I frames - see
1789 * subclause 5.8.4), the data link layer entity shall not transmit any
1790 * new I frames, but shall retransmit an I frame as a result
1791 * of the error recovery procedures as described in subclauses 5.5.4 and
1792 * 5.5.7. */
1793 if (dl->v_send == add_mod(dl->v_ack, k, dl->v_range)) {
1794 LOGP(DLLAPD, LOGL_INFO, "k frames outstanding, not sending "
1795 "more (k=%u V(S)=%u V(A)=%u)\n", k, dl->v_send,
1796 dl->v_ack);
1797 return rc;
1798 }
1799
1800 h = do_mod(dl->v_send, dl->range_hist);
1801
1802 /* if we have no tx_hist yet, we create it */
1803 if (!dl->tx_hist[h].msg) {
1804 /* Get next message into send-buffer, if any */
1805 if (!dl->send_buffer) {
1806 next_message:
1807 dl->send_out = 0;
1808 dl->send_buffer = msgb_dequeue(&dl->send_queue);
1809 /* No more data to be sent */
1810 if (!dl->send_buffer)
1811 return rc;
1812 LOGP(DLLAPD, LOGL_INFO, "get message from "
1813 "send-queue\n");
1814 }
1815
1816 /* How much is left in the send-buffer? */
1817 left = msgb_l3len(dl->send_buffer) - dl->send_out;
1818 /* Segment, if data exceeds N201 */
1819 length = left;
1820 if (length > lctx->n201)
1821 length = lctx->n201;
1822 LOGP(DLLAPD, LOGL_INFO, "msg-len %d sent %d left %d N201 %d "
1823 "length %d first byte %02x\n",
1824 msgb_l3len(dl->send_buffer), dl->send_out, left,
1825 lctx->n201, length, dl->send_buffer->l3h[0]);
1826 /* If message in send-buffer is completely sent */
1827 if (left == 0) {
1828 msgb_free(dl->send_buffer);
1829 dl->send_buffer = NULL;
1830 goto next_message;
1831 }
1832
1833 LOGP(DLLAPD, LOGL_INFO, "send I frame %sV(S)=%d\n",
1834 (left > length) ? "segment " : "", dl->v_send);
1835
1836 /* Create I frame (segment) and transmit-buffer content */
1837 msg = lapd_msgb_alloc(length, "LAPD I");
1838 msg->l3h = msgb_put(msg, length);
1839 /* assemble message */
1840 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1841 /* keep nctx.ldp */
1842 /* keep nctx.sapi */
1843 /* keep nctx.tei */
1844 nctx.cr = dl->cr.loc2rem.cmd;
1845 nctx.format = LAPD_FORM_I;
1846 nctx.p_f = 0;
1847 nctx.n_send = dl->v_send;
1848 nctx.n_recv = dl->v_recv;
1849 nctx.length = length;
1850 if (left > length)
1851 nctx.more = 1;
1852 else
1853 nctx.more = 0;
1854 if (length)
1855 memcpy(msg->l3h, dl->send_buffer->l3h + dl->send_out,
1856 length);
1857 /* store in tx_hist */
1858 dl->tx_hist[h].msg = lapd_msgb_alloc(msg->len, "HIST");
1859 msgb_put(dl->tx_hist[h].msg, msg->len);
1860 if (length)
1861 memcpy(dl->tx_hist[h].msg->data, msg->l3h, msg->len);
1862 dl->tx_hist[h].more = nctx.more;
1863 /* Add length to track how much is already in the tx buffer */
1864 dl->send_out += length;
1865 } else {
1866 LOGP(DLLAPD, LOGL_INFO, "resend I frame from tx buffer "
1867 "V(S)=%d\n", dl->v_send);
1868
1869 /* Create I frame (segment) from tx_hist */
1870 length = dl->tx_hist[h].msg->len;
1871 msg = lapd_msgb_alloc(length, "LAPD I resend");
1872 msg->l3h = msgb_put(msg, length);
1873 /* assemble message */
1874 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1875 /* keep nctx.ldp */
1876 /* keep nctx.sapi */
1877 /* keep nctx.tei */
1878 nctx.cr = dl->cr.loc2rem.cmd;
1879 nctx.format = LAPD_FORM_I;
1880 nctx.p_f = 0;
1881 nctx.n_send = dl->v_send;
1882 nctx.n_recv = dl->v_recv;
1883 nctx.length = length;
1884 nctx.more = dl->tx_hist[h].more;
1885 if (length)
1886 memcpy(msg->l3h, dl->tx_hist[h].msg->data, length);
1887 }
1888
1889 /* The value of the send state variable V(S) shall be incremented by 1
1890 * at the end of the transmission of the I frame */
1891 dl->v_send = inc_mod(dl->v_send, dl->v_range);
1892
1893 /* If timer T200 is not running at the time right before transmitting a
1894 * frame, when the PH-READY-TO-SEND primitive is received from the
1895 * physical layer., it shall be set. */
1896 if (!osmo_timer_pending(&dl->t200)) {
Andreas Eversberg742fc792011-09-27 09:40:25 +02001897 /* stop Timer T203, if running */
1898 lapd_stop_t203(dl);
1899 /* start Timer T200 */
1900 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02001901 }
1902
1903 dl->send_ph_data_req(&nctx, msg);
1904
1905 rc = 0; /* we sent something */
1906 goto next_frame;
1907}
1908
1909/* request link suspension */
1910static int lapd_susp_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1911{
1912 struct lapd_datalink *dl = lctx->dl;
1913 struct msgb *msg = dp->oph.msg;
1914
1915 LOGP(DLLAPD, LOGL_INFO, "perform suspension\n");
1916
1917 /* put back the send-buffer to the send-queue (first position) */
1918 if (dl->send_buffer) {
1919 LOGP(DLLAPD, LOGL_INFO, "put frame in sendbuffer back to "
1920 "queue\n");
1921 llist_add(&dl->send_buffer->list, &dl->send_queue);
1922 dl->send_buffer = NULL;
1923 } else
1924 LOGP(DLLAPD, LOGL_INFO, "no frame in sendbuffer\n");
1925
1926 /* Clear transmit buffer, but keep send buffer */
1927 lapd_dl_flush_tx(dl);
Andreas Eversberg742fc792011-09-27 09:40:25 +02001928 /* Stop timers (there is no state change, so we must stop all timers */
1929 lapd_stop_t200(dl);
1930 lapd_stop_t203(dl);
rootaf48bed2011-09-26 11:23:06 +02001931
1932 msgb_free(msg);
1933
1934 return send_dl_simple(PRIM_DL_SUSP, PRIM_OP_CONFIRM, &dl->lctx);
1935}
1936
1937/* requesst resume or reconnect of link */
1938static int lapd_res_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
1939{
1940 struct lapd_datalink *dl = lctx->dl;
1941 struct msgb *msg = dp->oph.msg;
1942 struct lapd_msg_ctx nctx;
1943
1944 LOGP(DLLAPD, LOGL_INFO, "perform re-establishment (SABM) length=%d\n",
1945 msg->len);
1946
1947 /* be sure that history is empty */
1948 lapd_dl_flush_hist(dl);
1949
1950 /* save message context for further use */
1951 memcpy(&dl->lctx, lctx, sizeof(dl->lctx));
1952
1953 /* Replace message in the send-buffer (reconnect) */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001954 msgb_free(dl->send_buffer);
1955 dl->send_buffer = NULL;
1956
rootaf48bed2011-09-26 11:23:06 +02001957 dl->send_out = 0;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001958 if (msg->len) {
rootaf48bed2011-09-26 11:23:06 +02001959 /* Write data into the send buffer, to be sent first */
1960 dl->send_buffer = msg;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001961 } else {
1962 msgb_free(msg);
1963 msg = NULL;
Andreas Eversberg5ad4ac82011-11-01 09:40:21 +01001964 dl->send_buffer = NULL;
Andreas Eversbergcad54b82013-07-09 20:25:24 +02001965 }
rootaf48bed2011-09-26 11:23:06 +02001966
1967 /* Discard partly received L3 message */
Holger Hans Peter Freyther9b037a62013-07-11 08:17:02 +02001968 msgb_free(dl->rcv_buffer);
1969 dl->rcv_buffer = NULL;
rootaf48bed2011-09-26 11:23:06 +02001970
1971 /* Create new msgb (old one is now free) */
1972 msg = lapd_msgb_alloc(0, "LAPD SABM");
1973 msg->l3h = msg->data;
1974 /* assemble message */
1975 memcpy(&nctx, &dl->lctx, sizeof(nctx));
1976 /* keep nctx.ldp */
1977 /* keep nctx.sapi */
1978 /* keep nctx.tei */
1979 nctx.cr = dl->cr.loc2rem.cmd;
1980 nctx.format = LAPD_FORM_U;
1981 nctx.s_u = (dl->use_sabme) ? LAPD_U_SABME : LAPD_U_SABM;
1982 nctx.p_f = 1;
1983 nctx.length = 0;
1984 nctx.more = 0;
1985
1986 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
1987 msgb_put(dl->tx_hist[0].msg, msg->len);
1988 if (msg->len)
1989 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
1990 dl->tx_hist[0].more = 0;
1991 /* set Vs to 0, because it is used as index when resending SABM */
1992 dl->v_send = 0;
1993
1994 /* Set states */
1995 dl->own_busy = dl->peer_busy = 0;
1996 dl->retrans_ctr = 0;
1997 lapd_dl_newstate(dl, LAPD_STATE_SABM_SENT);
1998
1999 /* Tramsmit and start T200 */
2000 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02002001 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02002002
2003 return 0;
2004}
2005
2006/* requesst release of link */
2007static int lapd_rel_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
2008{
2009 struct lapd_datalink *dl = lctx->dl;
2010 struct msgb *msg = dp->oph.msg;
2011 struct lapd_msg_ctx nctx;
2012
2013 /* local release */
2014 if (dp->u.rel_req.mode) {
2015 LOGP(DLLAPD, LOGL_INFO, "perform local release\n");
2016 msgb_free(msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02002017 /* stop Timer T200 */
2018 lapd_stop_t200(dl);
2019 /* enter idle state, T203 is stopped here, if running */
rootaf48bed2011-09-26 11:23:06 +02002020 lapd_dl_newstate(dl, LAPD_STATE_IDLE);
2021 /* flush buffers */
2022 lapd_dl_flush_tx(dl);
2023 lapd_dl_flush_send(dl);
2024 /* send notification to L3 */
2025 return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
2026 }
2027
2028 /* in case we are already disconnecting */
2029 if (dl->state == LAPD_STATE_DISC_SENT)
2030 return -EBUSY;
2031
2032 /* flush tx_hist */
2033 lapd_dl_flush_hist(dl);
2034
2035 LOGP(DLLAPD, LOGL_INFO, "perform normal release (DISC)\n");
2036
2037 /* Push LAPD header on msgb */
2038 /* assemble message */
2039 memcpy(&nctx, &dl->lctx, sizeof(nctx));
2040 /* keep nctx.ldp */
2041 /* keep nctx.sapi */
2042 /* keep nctx.tei */
2043 nctx.cr = dl->cr.loc2rem.cmd;
2044 nctx.format = LAPD_FORM_U;
2045 nctx.s_u = LAPD_U_DISC;
2046 nctx.p_f = 1;
2047 nctx.length = 0;
2048 nctx.more = 0;
2049
2050 dl->tx_hist[0].msg = lapd_msgb_alloc(msg->len, "HIST");
2051 msgb_put(dl->tx_hist[0].msg, msg->len);
2052 if (msg->len)
2053 memcpy(dl->tx_hist[0].msg->data, msg->l3h, msg->len);
2054 dl->tx_hist[0].more = 0;
2055 /* set Vs to 0, because it is used as index when resending DISC */
2056 dl->v_send = 0;
2057
2058 /* Set states */
2059 dl->own_busy = dl->peer_busy = 0;
2060 dl->retrans_ctr = 0;
2061 lapd_dl_newstate(dl, LAPD_STATE_DISC_SENT);
2062
2063 /* Tramsmit and start T200 */
2064 dl->send_ph_data_req(&nctx, msg);
Andreas Eversberg742fc792011-09-27 09:40:25 +02002065 lapd_start_t200(dl);
rootaf48bed2011-09-26 11:23:06 +02002066
2067 return 0;
2068}
2069
2070/* request release of link in idle state */
2071static int lapd_rel_req_idle(struct osmo_dlsap_prim *dp,
2072 struct lapd_msg_ctx *lctx)
2073{
2074 struct lapd_datalink *dl = lctx->dl;
2075 struct msgb *msg = dp->oph.msg;
2076
2077 msgb_free(msg);
2078
2079 /* send notification to L3 */
2080 return send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, &dl->lctx);
2081}
2082
2083/* statefull handling for DL SAP messages from L3 */
Holger Hans Peter Freyther579fb092012-11-22 10:54:23 +01002084static const struct l2downstate {
rootaf48bed2011-09-26 11:23:06 +02002085 uint32_t states;
2086 int prim, op;
2087 const char *name;
2088 int (*rout) (struct osmo_dlsap_prim *dp,
2089 struct lapd_msg_ctx *lctx);
2090} l2downstatelist[] = {
2091 /* create and send UI command */
2092 {ALL_STATES,
2093 PRIM_DL_UNIT_DATA, PRIM_OP_REQUEST,
2094 "DL-UNIT-DATA-REQUEST", lapd_udata_req},
2095
2096 /* create and send SABM command */
2097 {SBIT(LAPD_STATE_IDLE),
2098 PRIM_DL_EST, PRIM_OP_REQUEST,
2099 "DL-ESTABLISH-REQUEST", lapd_est_req},
2100
2101 /* create and send I command */
2102 {SBIT(LAPD_STATE_MF_EST) |
2103 SBIT(LAPD_STATE_TIMER_RECOV),
2104 PRIM_DL_DATA, PRIM_OP_REQUEST,
2105 "DL-DATA-REQUEST", lapd_data_req},
2106
2107 /* suspend datalink */
2108 {SBIT(LAPD_STATE_MF_EST) |
2109 SBIT(LAPD_STATE_TIMER_RECOV),
2110 PRIM_DL_SUSP, PRIM_OP_REQUEST,
2111 "DL-SUSPEND-REQUEST", lapd_susp_req},
2112
2113 /* create and send SABM command (resume) */
2114 {SBIT(LAPD_STATE_MF_EST) |
2115 SBIT(LAPD_STATE_TIMER_RECOV),
2116 PRIM_DL_RES, PRIM_OP_REQUEST,
2117 "DL-RESUME-REQUEST", lapd_res_req},
2118
2119 /* create and send SABM command (reconnect) */
2120 {SBIT(LAPD_STATE_IDLE) |
2121 SBIT(LAPD_STATE_MF_EST) |
2122 SBIT(LAPD_STATE_TIMER_RECOV),
2123 PRIM_DL_RECON, PRIM_OP_REQUEST,
2124 "DL-RECONNECT-REQUEST", lapd_res_req},
2125
2126 /* create and send DISC command */
2127 {SBIT(LAPD_STATE_SABM_SENT) |
2128 SBIT(LAPD_STATE_MF_EST) |
2129 SBIT(LAPD_STATE_TIMER_RECOV) |
2130 SBIT(LAPD_STATE_DISC_SENT),
2131 PRIM_DL_REL, PRIM_OP_REQUEST,
2132 "DL-RELEASE-REQUEST", lapd_rel_req},
2133
2134 /* release in idle state */
2135 {SBIT(LAPD_STATE_IDLE),
2136 PRIM_DL_REL, PRIM_OP_REQUEST,
2137 "DL-RELEASE-REQUEST", lapd_rel_req_idle},
2138};
2139
2140#define L2DOWNSLLEN \
2141 (sizeof(l2downstatelist) / sizeof(struct l2downstate))
2142
2143int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
2144{
2145 struct lapd_datalink *dl = lctx->dl;
2146 int i, supported = 0;
2147 struct msgb *msg = dp->oph.msg;
2148 int rc;
2149
2150 /* find function for current state and message */
2151 for (i = 0; i < L2DOWNSLLEN; i++) {
2152 if (dp->oph.primitive == l2downstatelist[i].prim
2153 && dp->oph.operation == l2downstatelist[i].op) {
2154 supported = 1;
2155 if ((SBIT(dl->state) & l2downstatelist[i].states))
2156 break;
2157 }
2158 }
2159 if (!supported) {
2160 LOGP(DLLAPD, LOGL_NOTICE, "Message %u/%u unsupported.\n",
2161 dp->oph.primitive, dp->oph.operation);
2162 msgb_free(msg);
2163 return 0;
2164 }
2165 if (i == L2DOWNSLLEN) {
2166 LOGP(DLLAPD, LOGL_NOTICE, "Message %u/%u unhandled at this "
2167 "state %s.\n", dp->oph.primitive, dp->oph.operation,
2168 lapd_state_names[dl->state]);
2169 msgb_free(msg);
2170 return 0;
2171 }
2172
2173 LOGP(DLLAPD, LOGL_INFO, "Message %s received in state %s\n",
2174 l2downstatelist[i].name, lapd_state_names[dl->state]);
2175
2176 rc = l2downstatelist[i].rout(dp, lctx);
2177
2178 return rc;
2179}
2180
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +01002181/*! @} */