1 /*
2 * Copyright (c) 1996-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Author: Hartmut Brandt <harti@freebsd.org>
28 *
29 * $Begemot: libunimsg/netnatm/saal/saal_sscop.c,v 1.11 2004/07/08 08:22:13 brandt Exp $
30 *
31 * Core SSCOP code (ITU-T Q.2110)
32 */
33
34 #include <netnatm/saal/sscop.h>
35 #include <netnatm/saal/sscoppriv.h>
36
37 #ifndef FAILURE
38 #define FAILURE(S)
39 #endif
40
41 #define MKSTR(S) #S
42
43 static const char *const sscop_sigs[] = {
44 MKSTR(SSCOP_ESTABLISH_request),
45 MKSTR(SSCOP_ESTABLISH_indication),
46 MKSTR(SSCOP_ESTABLISH_response),
47 MKSTR(SSCOP_ESTABLISH_confirm),
48 MKSTR(SSCOP_RELEASE_request),
49 MKSTR(SSCOP_RELEASE_indication),
50 MKSTR(SSCOP_RELEASE_confirm),
51 MKSTR(SSCOP_DATA_request),
52 MKSTR(SSCOP_DATA_indication),
53 MKSTR(SSCOP_UDATA_request),
54 MKSTR(SSCOP_UDATA_indication),
55 MKSTR(SSCOP_RECOVER_indication),
56 MKSTR(SSCOP_RECOVER_response),
57 MKSTR(SSCOP_RESYNC_request),
58 MKSTR(SSCOP_RESYNC_indication),
59 MKSTR(SSCOP_RESYNC_response),
60 MKSTR(SSCOP_RESYNC_confirm),
61 MKSTR(SSCOP_RETRIEVE_request),
62 MKSTR(SSCOP_RETRIEVE_indication),
63 MKSTR(SSCOP_RETRIEVE_COMPL_indication),
64 };
65
66 static const char *const sscop_msigs[] = {
67 MKSTR(SSCOP_MDATA_request),
68 MKSTR(SSCOP_MDATA_indication),
69 MKSTR(SSCOP_MERROR_indication),
70 };
71
72 static const char *const states[] = {
73 MKSTR(SSCOP_IDLE),
74 MKSTR(SSCOP_OUT_PEND),
75 MKSTR(SSCOP_IN_PEND),
76 MKSTR(SSCOP_OUT_DIS_PEND),
77 MKSTR(SSCOP_OUT_RESYNC_PEND),
78 MKSTR(SSCOP_IN_RESYNC_PEND),
79 MKSTR(SSCOP_OUT_REC_PEND),
80 MKSTR(SSCOP_REC_PEND),
81 MKSTR(SSCOP_IN_REC_PEND),
82 MKSTR(SSCOP_READY),
83 };
84
85 #ifdef SSCOP_DEBUG
86 static const char *const events[] = {
87 MKSTR(SIG_BGN),
88 MKSTR(SIG_BGAK),
89 MKSTR(SIG_END),
90 MKSTR(SIG_ENDAK),
91 MKSTR(SIG_RS),
92 MKSTR(SIG_RSAK),
93 MKSTR(SIG_BGREJ),
94 MKSTR(SIG_SD),
95 MKSTR(SIG_ER),
96 MKSTR(SIG_POLL),
97 MKSTR(SIG_STAT),
98 MKSTR(SIG_USTAT),
99 MKSTR(SIG_UD),
100 MKSTR(SIG_MD),
101 MKSTR(SIG_ERAK),
102
103 MKSTR(SIG_T_CC),
104 MKSTR(SIG_T_POLL),
105 MKSTR(SIG_T_KA),
106 MKSTR(SIG_T_NR),
107 MKSTR(SIG_T_IDLE),
108
109 MKSTR(SIG_PDU_Q),
110 MKSTR(SIG_USER_DATA),
111 MKSTR(SIG_ESTAB_REQ),
112 MKSTR(SIG_ESTAB_RESP),
113 MKSTR(SIG_RELEASE_REQ),
114 MKSTR(SIG_RECOVER),
115 MKSTR(SIG_SYNC_REQ),
116 MKSTR(SIG_SYNC_RESP),
117 MKSTR(SIG_UDATA),
118 MKSTR(SIG_MDATA),
119 MKSTR(SIG_UPDU_Q),
120 MKSTR(SIG_MPDU_Q),
121 MKSTR(SIG_RETRIEVE),
122 };
123
124 static const char *const pdus[] = {
125 "illegale PDU type 0", /* no PDU type 0 */
126 MKSTR(PDU_BGN),
127 MKSTR(PDU_BGAK),
128 MKSTR(PDU_END),
129 MKSTR(PDU_ENDAK),
130 MKSTR(PDU_RS),
131 MKSTR(PDU_RSAK),
132 MKSTR(PDU_BGREJ),
133 MKSTR(PDU_SD),
134 MKSTR(PDU_ER),
135 MKSTR(PDU_POLL),
136 MKSTR(PDU_STAT),
137 MKSTR(PDU_USTAT),
138 MKSTR(PDU_UD),
139 MKSTR(PDU_MD),
140 MKSTR(PDU_ERAK),
141 };
142 #endif
143
144 MEMINIT();
145
146 static void sscop_signal(struct sscop *, u_int, struct sscop_msg *);
147 static void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *);
148 static void handle_sigs(struct sscop *);
149 static void sscop_set_state(struct sscop *, u_int);
150
151 /************************************************************/
152
153
154 /************************************************************/
155 /*
156 * Queue macros
157 */
158 #define SSCOP_MSG_FREE(MSG) \
159 do { \
160 if(MSG) { \
161 MBUF_FREE((MSG)->m); \
162 MSG_FREE((MSG)); \
163 } \
164 } while(0)
165
166 static inline struct sscop_msg *QFIND(sscop_msgq_head_t *q, u_int rn)
167 {
168 struct sscop_msg *msg = NULL, *m;
169 MSGQ_FOREACH(m, q) {
170 if(m->seqno == rn) {
171 msg = m;
172 break;
173 }
174 }
175 return msg;
176 }
177
178 #define QINSERT(Q,M) \
179 do { \
180 struct sscop_msg *_msg = NULL, *_m; \
181 MSGQ_FOREACH(_m, (Q)) { \
182 if (_m->seqno > (M)->seqno) { \
183 _msg = _m; \
184 break; \
185 } \
186 } \
187 if (_msg != NULL) \
188 MSGQ_INSERT_BEFORE(_msg, (M)); \
189 else \
190 MSGQ_APPEND((Q), (M)); \
191 } while (0)
192
193
194 /*
195 * Send an error indication to the management plane.
196 */
197 #define MAAL_ERROR(S,E,C) \
198 do { \
199 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
200 "MAA-Signal %s in state %s", \
201 sscop_msigs[SSCOP_MERROR_indication], states[(S)->state])); \
202 (S)->funcs->send_manage((S), (S)->aarg, \
203 SSCOP_MERROR_indication, NULL, (E), (C)); \
204 } while(0)
205
206 #define MAAL_DATA(S,M) \
207 do { \
208 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
209 "MAA-Signal %s in state %s", \
210 sscop_msigs[SSCOP_MDATA_indication], states[(S)->state])); \
211 (S)->funcs->send_manage((S), (S)->aarg, \
212 SSCOP_MDATA_indication, (M), 0, 0); \
213 } while(0)
214
215 #define AAL_DATA(S,D,M,N) \
216 do { \
217 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
218 "AA-Signal %s in state %s", \
219 sscop_sigs[D], states[(S)->state])); \
220 (S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N)); \
221 } while(0)
222
223 #define AAL_SIG(S,D) \
224 do { \
225 VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg, \
226 "AA-Signal %s in state %s", \
227 sscop_sigs[D], states[(S)->state])); \
228 (S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0); \
229 } while(0)
230
231 #ifdef SSCOP_DEBUG
232 #define AAL_SEND(S,M) do { \
233 if (ISVERBOSE(S, SSCOP_DBG_PDU)) \
234 sscop_dump_pdu(S, "tx", (M)); \
235 (S)->funcs->send_lower((S), (S)->aarg, (M)); \
236 } while(0)
237 #else
238 #define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M))
239 #endif
240
241
242 /*
243 * Free a save user-to-user data buffer and set the pointer to zero
244 * to signal, that it is free.
245 */
246 #define FREE_UU(F) \
247 do { \
248 if(sscop->F) { \
249 MBUF_FREE(sscop->F); \
250 sscop->F = NULL; \
251 } \
252 } while(0)
253
254 #define SET_UU(F,U) \
255 do { \
256 FREE_UU(F); \
257 sscop->F = U->m; \
258 U->m = NULL; \
259 SSCOP_MSG_FREE(U); \
260 } while(0)
261
262 #define AAL_UU_SIGNAL(S, SIG, M, PL, SN) \
263 do { \
264 if(MBUF_LEN((M)->m) > 0) { \
265 MBUF_UNPAD((M)->m,(PL)); \
266 AAL_DATA((S), (SIG), (M)->m, (SN)); \
267 (M)->m = NULL; \
268 } else { \
269 AAL_DATA((S), (SIG), NULL, (SN)); \
270 } \
271 SSCOP_MSG_FREE((M)); \
272 } while(0)
273
274
275
276 TIMER_FUNC(cc, CC)
277 TIMER_FUNC(nr, NR)
278 TIMER_FUNC(ka, KA)
279 TIMER_FUNC(poll, POLL)
280 TIMER_FUNC(idle, IDLE)
281
282 /************************************************************/
283 /*
284 * INSTANCE AND TYPE HANDLING.
285 */
286 #ifdef SSCOP_DEBUG
287 static void
288 sscop_dump_pdu(struct sscop *sscop, const char *dir,
289 const struct SSCOP_MBUF_T *m)
290 {
291 u_int32_t v1, v2, v3, v4;
292 u_int size = MBUF_LEN(m);
293 u_int n, i;
294
295 if (size < 8)
296 return;
297
298 v1 = MBUF_TRAIL32(m, -1);
299 v2 = MBUF_TRAIL32(m, -2);
300
301 switch ((v1 >> 24) & 0xf) {
302
303 case 0:
304 return;
305
306 case PDU_BGN:
307 sscop->funcs->verbose(sscop, sscop->aarg,
308 "%s BGN n(mr)=%u n(sq)=%u pl=%u",
309 dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
310 return;
311
312 case PDU_BGAK:
313 sscop->funcs->verbose(sscop, sscop->aarg,
314 "%s BGAK n(mr)=%u pl=%u",
315 dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
316 return;
317
318 case PDU_END:
319 sscop->funcs->verbose(sscop, sscop->aarg,
320 "%s END r=%u s=%u pl=%u",
321 dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3);
322 return;
323
324 case PDU_ENDAK:
325 sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir);
326 return;
327
328 case PDU_RS:
329 sscop->funcs->verbose(sscop, sscop->aarg,
330 "%s RS n(mr)=%u n(sq)=%u pl=%u",
331 dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
332 return;
333
334 case PDU_RSAK:
335 sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u",
336 dir, v1 & 0xffffff);
337 return;
338
339 case PDU_BGREJ:
340 sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u",
341 dir, (v1 >> 30) & 0x3);
342 return;
343
344 case PDU_SD:
345 sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u",
346 dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
347 return;
348
349 case PDU_ER:
350 sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u",
351 dir, v1 & 0xffffff, v2 & 0xff);
352 return;
353
354 case PDU_POLL:
355 sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u",
356 dir, v1 & 0xffffff, v2 & 0xffffff);
357 return;
358
359 case PDU_STAT:
360 if (size < 12)
361 return;
362 v3 = MBUF_TRAIL32(m, -3);
363 sscop->funcs->verbose(sscop, sscop->aarg,
364 "%s STAT n(r)=%u n(mr)=%u n(ps)=%u",
365 dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff);
366 n = (size - 12) / 4;
367 for (i = 0; i < (size - 12) / 4; i++, n--) {
368 v4 = MBUF_TRAIL32(m, -4 - (int)i);
369 sscop->funcs->verbose(sscop, sscop->aarg,
370 " LE(%u)=%u", n, v4 & 0xffffff);
371 }
372 return;
373
374 case PDU_USTAT:
375 if (size < 16)
376 return;
377 sscop->funcs->verbose(sscop, sscop->aarg,
378 "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u",
379 dir, v1 & 0xffffff, v2 & 0xffffff,
380 MBUF_TRAIL32(m, -4) & 0xffffff,
381 MBUF_TRAIL32(m, -3) & 0xffffff);
382 return;
383
384 case PDU_UD:
385 sscop->funcs->verbose(sscop, sscop->aarg,
386 "%s UD pl=%u", dir, (v1 >> 30) & 0x3);
387 return;
388
389 case PDU_MD:
390 sscop->funcs->verbose(sscop, sscop->aarg,
391 "%s MD pl=%u", dir, (v1 >> 30) & 0x3);
392 return;
393
394 case PDU_ERAK:
395 sscop->funcs->verbose(sscop, sscop->aarg,
396 "%s ERAK n(mr)=%u", dir, v1 & 0xffffff);
397 return;
398 }
399 }
400 #endif
401
402
403 /*
404 * Initialize state of variables
405 */
406 static void
407 sscop_init(struct sscop *sscop)
408 {
409 sscop->state = SSCOP_IDLE;
410
411 sscop->vt_sq = 0;
412 sscop->vr_sq = 0;
413 sscop->clear_buffers = 1;
414
415 sscop->ll_busy = 0;
416
417 sscop->rxq = 0;
418 }
419
420 static void
421 sscop_clear(struct sscop *sscop)
422 {
423 TIMER_STOP(sscop, cc);
424 TIMER_STOP(sscop, ka);
425 TIMER_STOP(sscop, nr);
426 TIMER_STOP(sscop, idle);
427 TIMER_STOP(sscop, poll);
428
429 FREE_UU(uu_bgn);
430 FREE_UU(uu_bgak);
431 FREE_UU(uu_bgrej);
432 FREE_UU(uu_end);
433 FREE_UU(uu_rs);
434
435 MSGQ_CLEAR(&sscop->xq);
436 MSGQ_CLEAR(&sscop->uxq);
437 MSGQ_CLEAR(&sscop->mxq);
438 MSGQ_CLEAR(&sscop->xbuf);
439 MSGQ_CLEAR(&sscop->rbuf);
440
441 SIGQ_CLEAR(&sscop->sigs);
442 SIGQ_CLEAR(&sscop->saved_sigs);
443 }
444
445
446 /*
447 * Allocate instance memory, initialize the state of all variables.
448 */
449 struct sscop *
450 sscop_create(void *a, const struct sscop_funcs *funcs)
451 {
452 struct sscop *sscop;
453
454 MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop));
455 if (sscop == NULL)
456 return (NULL);
457
458 if (a == NULL)
459 sscop->aarg = sscop;
460 else
461 sscop->aarg = a;
462 sscop->funcs = funcs;
463
464 sscop->maxk = MAXK;
465 sscop->maxj = MAXJ;
466 sscop->maxcc = MAXCC;
467 sscop->maxpd = MAXPD;
468 sscop->maxstat = MAXSTAT;
469 sscop->timercc = TIMERCC;
470 sscop->timerka = TIMERKA;
471 sscop->timernr = TIMERNR;
472 sscop->timerpoll = TIMERPOLL;
473 sscop->timeridle = TIMERIDLE;
474 sscop->robustness = 0;
475 sscop->poll_after_rex = 0;
476 sscop->mr = MAXMR;
477
478 TIMER_INIT(sscop, cc);
479 TIMER_INIT(sscop, nr);
480 TIMER_INIT(sscop, ka);
481 TIMER_INIT(sscop, poll);
482 TIMER_INIT(sscop, idle);
483
484 MSGQ_INIT(&sscop->xq);
485 MSGQ_INIT(&sscop->uxq);
486 MSGQ_INIT(&sscop->mxq);
487 MSGQ_INIT(&sscop->rbuf);
488 MSGQ_INIT(&sscop->xbuf);
489
490 SIGQ_INIT(&sscop->sigs);
491 SIGQ_INIT(&sscop->saved_sigs);
492
493 sscop_init(sscop);
494
495 return (sscop);
496 }
497
498 /*
499 * Free all resources in a sscop instance
500 */
501 void
502 sscop_destroy(struct sscop *sscop)
503 {
504 sscop_reset(sscop);
505
506 MEMFREE(sscop);
507 }
508
509 /*
510 * Reset the SSCOP instance.
511 */
512 void
513 sscop_reset(struct sscop *sscop)
514 {
515 sscop_clear(sscop);
516 sscop_init(sscop);
517 }
518
519 void
520 sscop_getparam(const struct sscop *sscop, struct sscop_param *p)
521 {
522 p->timer_cc = sscop->timercc;
523 p->timer_poll = sscop->timerpoll;
524 p->timer_keep_alive = sscop->timerka;
525 p->timer_no_response = sscop->timernr;
526 p->timer_idle = sscop->timeridle;
527 p->maxk = sscop->maxk;
528 p->maxj = sscop->maxj;
529 p->maxcc = sscop->maxcc;
530 p->maxpd = sscop->maxpd;
531 p->maxstat = sscop->maxstat;
532 p->mr = sscop->mr;
533 p->flags = 0;
534 if(sscop->robustness)
535 p->flags |= SSCOP_ROBUST;
536 if(sscop->poll_after_rex)
537 p->flags |= SSCOP_POLLREX;
538 }
539
540 int
541 sscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask)
542 {
543 u_int mask = *pmask;
544
545 /* can change only in idle state */
546 if (sscop->state != SSCOP_IDLE)
547 return (EISCONN);
548
549 *pmask = 0;
550
551 /*
552 * first check all parameters
553 */
554 if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0)
555 *pmask |= SSCOP_SET_TCC;
556 if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0)
557 *pmask |= SSCOP_SET_TPOLL;
558 if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0)
559 *pmask |= SSCOP_SET_TKA;
560 if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0)
561 *pmask |= SSCOP_SET_TNR;
562 if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0)
563 *pmask |= SSCOP_SET_TIDLE;
564 if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK)
565 *pmask |= SSCOP_SET_MAXK;
566 if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ)
567 *pmask |= SSCOP_SET_MAXJ;
568 if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255)
569 *pmask |= SSCOP_SET_MAXCC;
570 if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24))
571 *pmask |= SSCOP_SET_MAXPD;
572 if ((mask & SSCOP_SET_MAXSTAT) &&
573 ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 ||
574 p->maxstat * 4 > MAXMAXK - 8))
575 *pmask |= SSCOP_SET_MAXSTAT;
576 if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1)
577 *pmask |= SSCOP_SET_MR;
578
579 if (*pmask)
580 return (EINVAL);
581
582
583 /*
584 * now set it
585 */
586 if (mask & SSCOP_SET_TCC)
587 sscop->timercc = p->timer_cc;
588
589 if (mask & SSCOP_SET_TPOLL)
590 sscop->timerpoll = p->timer_poll;
591
592 if (mask & SSCOP_SET_TKA)
593 sscop->timerka = p->timer_keep_alive;
594
595 if (mask & SSCOP_SET_TNR)
596 sscop->timernr = p->timer_no_response;
597
598 if (mask & SSCOP_SET_TIDLE)
599 sscop->timeridle = p->timer_idle;
600
601 if (mask & SSCOP_SET_MAXK)
602 sscop->maxk = p->maxk;
603 if (mask & SSCOP_SET_MAXJ)
604 sscop->maxj = p->maxj;
605
606 if (mask & SSCOP_SET_MAXCC)
607 sscop->maxcc = p->maxcc;
608 if (mask & SSCOP_SET_MAXPD)
609 sscop->maxpd = p->maxpd;
610 if (mask & SSCOP_SET_MAXSTAT)
611 sscop->maxstat = p->maxstat;
612
613 if (mask & SSCOP_SET_MR)
614 sscop->mr = p->mr;
615
616 if (mask & SSCOP_SET_ROBUST)
617 sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0);
618
619 if (mask & SSCOP_SET_POLLREX)
620 sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0);
621
622 return (0);
623 }
624
625 enum sscop_state
626 sscop_getstate(const struct sscop *sscop)
627 {
628 return (sscop->state);
629 }
630
631
632 /************************************************************/
633 /*
634 * EXTERNAL INPUT SIGNAL MAPPING
635 */
636
637 /*
638 * Map AA signal to SSCOP internal signal
639 */
640 int
641 sscop_aasig(struct sscop *sscop, enum sscop_aasig sig,
642 struct SSCOP_MBUF_T *m, u_int arg)
643 {
644 struct sscop_msg *msg;
645
646 if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
647 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
648 "AA-Signal %u - bad signal", sig));
649 MBUF_FREE(m);
650 return (EINVAL);
651 }
652 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
653 "AA-Signal %s in state %s with%s message",
654 sscop_sigs[sig], states[sscop->state], m ? "" : "out"));
655
656 MSG_ALLOC(msg);
657 if (msg == NULL) {
658 FAILURE("sscop: cannot allocate aasig");
659 MBUF_FREE(m);
660 return (ENOMEM);
661 }
662
663 switch(sig) {
664
665 case SSCOP_ESTABLISH_request:
666 msg->m = m;
667 msg->rexmit = arg;
668 sscop_signal(sscop, SIG_ESTAB_REQ, msg);
669 break;
670
671 case SSCOP_ESTABLISH_response:
672 msg->m = m;
673 msg->rexmit = arg;
674 sscop_signal(sscop, SIG_ESTAB_RESP, msg);
675 break;
676
677 case SSCOP_RELEASE_request:
678 msg->m = m;
679 sscop_signal(sscop, SIG_RELEASE_REQ, msg);
680 break;
681
682 case SSCOP_DATA_request:
683 msg->m = m;
684 sscop_signal(sscop, SIG_USER_DATA, msg);
685 break;
686
687 case SSCOP_UDATA_request:
688 msg->m = m;
689 sscop_signal(sscop, SIG_UDATA, msg);
690 break;
691
692 case SSCOP_RECOVER_response:
693 MBUF_FREE(m);
694 MSG_FREE(msg);
695 sscop_signal(sscop, SIG_RECOVER, NULL);
696 break;
697
698 case SSCOP_RESYNC_request:
699 msg->m = m;
700 sscop_signal(sscop, SIG_SYNC_REQ, msg);
701 break;
702
703 case SSCOP_RESYNC_response:
704 MBUF_FREE(m);
705 MSG_FREE(msg);
706 sscop_signal(sscop, SIG_SYNC_RESP, NULL);
707 break;
708
709 case SSCOP_RETRIEVE_request:
710 MBUF_FREE(m);
711 msg->rexmit = arg;
712 sscop_signal(sscop, SIG_RETRIEVE, msg);
713 break;
714
715 case SSCOP_ESTABLISH_indication:
716 case SSCOP_ESTABLISH_confirm:
717 case SSCOP_RELEASE_indication:
718 case SSCOP_RELEASE_confirm:
719 case SSCOP_DATA_indication:
720 case SSCOP_UDATA_indication:
721 case SSCOP_RECOVER_indication:
722 case SSCOP_RESYNC_indication:
723 case SSCOP_RESYNC_confirm:
724 case SSCOP_RETRIEVE_indication:
725 case SSCOP_RETRIEVE_COMPL_indication:
726 MBUF_FREE(m);
727 MSG_FREE(msg);
728 return EINVAL;
729 }
730
731 return 0;
732 }
733
734 /*
735 * Signal from layer management.
736 */
737 int
738 sscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m)
739 {
740 struct sscop_msg *msg;
741
742 if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
743 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
744 "MAA-Signal %u - bad signal", sig));
745 MBUF_FREE(m);
746 return (EINVAL);
747 }
748 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
749 "MAA-Signal %s in state %s with%s message",
750 sscop_msigs[sig], states[sscop->state], m ? "" : "out"));
751
752 MSG_ALLOC(msg);
753 if (msg == NULL) {
754 FAILURE("sscop: cannot allocate maasig");
755 MBUF_FREE(m);
756 return (ENOMEM);
757 }
758
759 switch (sig) {
760
761 case SSCOP_MDATA_request:
762 msg->m = m;
763 sscop_signal(sscop, SIG_MDATA, msg);
764 break;
765
766 case SSCOP_MDATA_indication:
767 case SSCOP_MERROR_indication:
768 MBUF_FREE(m);
769 MSG_FREE(msg);
770 return (EINVAL);
771 }
772 return (0);
773 }
774
775 /*
776 * Map PDU to SSCOP signal.
777 */
778 void
779 sscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m)
780 {
781 struct sscop_msg *msg;
782 union pdu pdu;
783 u_int size;
784
785 MSG_ALLOC(msg);
786 if(msg == NULL) {
787 FAILURE("sscop: cannot allocate in pdu msg");
788 MBUF_FREE(m);
789 return;
790 }
791
792 msg->m = m;
793 msg->rexmit = 0;
794
795 size = MBUF_LEN(m);
796
797 if(size % 4 != 0 || size < 4)
798 goto err;
799
800 pdu.sscop_null = MBUF_TRAIL32(m, -1);
801
802 VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg,
803 "got %s, size=%u", pdus[pdu.sscop_type], size));
804
805 #ifdef SSCOP_DEBUG
806 #define ENSURE(C,F) if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; }
807 #else
808 #define ENSURE(C,F) if(!(C)) goto err
809 #endif
810
811 #ifdef SSCOP_DEBUG
812 if (ISVERBOSE(sscop, SSCOP_DBG_PDU))
813 sscop_dump_pdu(sscop, "rx", m);
814 #endif
815
816 switch(pdu.sscop_type) {
817
818 default:
819 ENSURE(0, (sscop, sscop->aarg,
820 "Bad PDU type %u", pdu.sscop_type));
821 break;
822
823 case PDU_BGN:
824 ENSURE(size >= 8U, (sscop, sscop->aarg,
825 "PDU_BGN size=%u", size));
826 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
827 "PDU_BGN size=%u pl=%u", size, pdu.sscop_pl));
828 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
829 "PDU_BGN size=%u", size));
830 sscop_signal(sscop, SIG_BGN, msg);
831 break;
832
833 case PDU_BGAK:
834 ENSURE(size >= 8U, (sscop, sscop->aarg,
835 "PDU_BGAK size=%u", size));
836 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
837 "PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl));
838 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
839 "PDU_BGAK size=%u", size));
840 sscop_signal(sscop, SIG_BGAK, msg);
841 break;
842
843 case PDU_END:
844 ENSURE(size >= 8U, (sscop, sscop->aarg,
845 "PDU_END size=%u", size));
846 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
847 "PDU_END size=%u pl=%u", size, pdu.sscop_pl));
848 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
849 "PDU_END size=%u", size));
850 sscop_signal(sscop, SIG_END, msg);
851 break;
852
853 case PDU_ENDAK:
854 ENSURE(size == 8U, (sscop, sscop->aarg,
855 "PDU_ENDAK size=%u", size));
856 sscop_signal(sscop, SIG_ENDAK, msg);
857 break;
858
859 case PDU_BGREJ:
860 ENSURE(size >= 8U, (sscop, sscop->aarg,
861 "PDU_BGREJ size=%u", size));
862 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
863 "PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl));
864 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
865 "PDU_BGREJ size=%u", size));
866 sscop_signal(sscop, SIG_BGREJ, msg);
867 break;
868
869 case PDU_SD:
870 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
871 "PDU_SD size=%u pl=%u", size, pdu.sscop_pl));
872 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
873 "PDU_SD size=%u", size));
874 sscop_signal(sscop, SIG_SD, msg);
875 break;
876
877 case PDU_UD:
878 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
879 "PDU_UD size=%u pl=%u", size, pdu.sscop_pl));
880 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
881 "PDU_UD size=%u", size));
882 sscop_signal(sscop, SIG_UD, msg);
883 break;
884
885 case PDU_MD:
886 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
887 "PDU_MD size=%u pl=%u", size, pdu.sscop_pl));
888 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
889 "PDU_MD size=%u", size));
890 sscop_signal(sscop, SIG_MD, msg);
891 break;
892
893 case PDU_POLL:
894 ENSURE(size == 8U, (sscop, sscop->aarg,
895 "PDU_POLL size=%u", size));
896 sscop_signal(sscop, SIG_POLL, msg);
897 break;
898
899 case PDU_STAT:
900 ENSURE(size >= 12U, (sscop, sscop->aarg,
901 "PDU_STAT size=%u", size));
902 ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg,
903 "PDU_STAT size=%u", size));
904 sscop_signal(sscop, SIG_STAT, msg);
905 break;
906
907 case PDU_RS:
908 ENSURE(size >= 8U, (sscop, sscop->aarg,
909 "PDU_RS size=%u", size));
910 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
911 "PDU_RS size=%u pl=%u", size, pdu.sscop_pl));
912 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
913 "PDU_RS size=%u", size));
914 sscop_signal(sscop, SIG_RS, msg);
915 break;
916
917 case PDU_RSAK:
918 ENSURE(size == 8U, (sscop, sscop->aarg,
919 "PDU_RSAK size=%u", size));
920 sscop_signal(sscop, SIG_RSAK, msg);
921 break;
922
923 case PDU_ER:
924 ENSURE(size == 8U, (sscop, sscop->aarg,
925 "PDU_ER size=%u", size));
926 sscop_signal(sscop, SIG_ER, msg);
927 break;
928
929 case PDU_ERAK:
930 ENSURE(size == 8U, (sscop, sscop->aarg,
931 "PDU_ERAK size=%u", size));
932 sscop_signal(sscop, SIG_ERAK, msg);
933 break;
934
935 case PDU_USTAT:
936 ENSURE(size == 16U, (sscop, sscop->aarg,
937 "PDU_ERAK size=%u", size));
938 sscop_signal(sscop, SIG_USTAT, msg);
939 break;
940 }
941 #undef ENSURE
942 return;
943
944 err:
945 MAAL_ERROR(sscop, 'U', 0);
946 SSCOP_MSG_FREE(msg);
947 }
948
949 /************************************************************/
950 /*
951 * UTILITIES
952 */
953
954 /*
955 * Move the receiver window by N packets
956 */
957 u_int
958 sscop_window(struct sscop *sscop, u_int n)
959 {
960 sscop->vr_mr += n;
961 return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r));
962 }
963
964 /*
965 * Lower layer busy handling
966 */
967 u_int
968 sscop_setbusy(struct sscop *sscop, int busy)
969 {
970 u_int old = sscop->ll_busy;
971
972 if (busy > 0)
973 sscop->ll_busy = 1;
974 else if (busy == 0) {
975 sscop->ll_busy = 0;
976 if(old)
977 handle_sigs(sscop);
978 }
979
980 return (old);
981 }
982
983 const char *
984 sscop_signame(enum sscop_aasig sig)
985 {
986 static char str[40];
987
988 if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
989 sprintf(str, "BAD SSCOP_AASIG %u", sig);
990 return (str);
991 } else {
992 return (sscop_sigs[sig]);
993 }
994 }
995
996 const char *
997 sscop_msigname(enum sscop_maasig sig)
998 {
999 static char str[40];
1000
1001 if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
1002 sprintf(str, "BAD SSCOP_MAASIG %u", sig);
1003 return (str);
1004 } else {
1005 return (sscop_msigs[sig]);
1006 }
1007 }
1008
1009 const char *
1010 sscop_statename(enum sscop_state s)
1011 {
1012 static char str[40];
1013
1014 if (s >= sizeof(states)/sizeof(states[0])) {
1015 sprintf(str, "BAD SSCOP_STATE %u", s);
1016 return (str);
1017 } else {
1018 return (states[s]);
1019 }
1020 }
1021
1022
1023 /************************************************************/
1024 /*
1025 * MACROS
1026 */
1027
1028 /*
1029 * p 75: release buffers
1030 */
1031 static void
1032 m_release_buffers(struct sscop *sscop)
1033 {
1034 MSGQ_CLEAR(&sscop->xq);
1035 MSGQ_CLEAR(&sscop->xbuf);
1036 sscop->rxq = 0;
1037 MSGQ_CLEAR(&sscop->rbuf);
1038 }
1039
1040 /*
1041 * P 75: Prepare retrival
1042 */
1043 static void
1044 m_prepare_retrieval(struct sscop *sscop)
1045 {
1046 struct sscop_msg *msg;
1047
1048 if (sscop->clear_buffers) {
1049 MSGQ_CLEAR(&sscop->xq);
1050 MSGQ_CLEAR(&sscop->xbuf);
1051 }
1052 MSGQ_FOREACH(msg, &sscop->xbuf)
1053 msg->rexmit = 0;
1054 sscop->rxq = 0;
1055
1056 MSGQ_CLEAR(&sscop->rbuf);
1057 }
1058
1059 /*
1060 * P 75: Prepare retrival
1061 */
1062 static void
1063 m_prepare_recovery(struct sscop *sscop)
1064 {
1065 struct sscop_msg *msg;
1066
1067 if(sscop->clear_buffers) {
1068 MSGQ_CLEAR(&sscop->xq);
1069 MSGQ_CLEAR(&sscop->xbuf);
1070 }
1071 MSGQ_FOREACH(msg, &sscop->xbuf)
1072 msg->rexmit = 0;
1073 sscop->rxq = 0;
1074 }
1075
1076
1077 /*
1078 * P 75: Clear transmitter
1079 */
1080 static void
1081 m_clear_transmitter(struct sscop *sscop)
1082 {
1083 if(!sscop->clear_buffers) {
1084 MSGQ_CLEAR(&sscop->xq);
1085 MSGQ_CLEAR(&sscop->xbuf);
1086 }
1087 }
1088
1089
1090 /*
1091 * p 75: Deliver data
1092 * Freeing the message is the responibility of the handler function.
1093 */
1094 static void
1095 m_deliver_data(struct sscop *sscop)
1096 {
1097 struct sscop_msg *msg;
1098 u_int sn;
1099
1100 if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL)
1101 return;
1102
1103 if (sscop->clear_buffers) {
1104 MSGQ_CLEAR(&sscop->rbuf);
1105 return;
1106 }
1107
1108 sn = msg->seqno + 1;
1109 AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
1110 MSG_FREE(msg);
1111
1112 while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) {
1113 ASSERT(msg->seqno == sn);
1114 if (++sn == SSCOP_MAXSEQNO)
1115 sn = 0;
1116 AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
1117 MSG_FREE(msg);
1118 }
1119 }
1120
1121 /*
1122 * P 75: Initialize state variables
1123 */
1124 static void
1125 m_initialize_state(struct sscop *sscop)
1126 {
1127 sscop->vt_s = 0;
1128 sscop->vt_ps = 0;
1129 sscop->vt_a = 0;
1130
1131 sscop->vt_pa = 1;
1132 sscop->vt_pd = 0;
1133 sscop->credit = 1;
1134
1135 sscop->vr_r = 0;
1136 sscop->vr_h = 0;
1137 }
1138
1139 /*
1140 * p 76: Data retrieval
1141 */
1142 static void
1143 m_data_retrieval(struct sscop *sscop, u_int rn)
1144 {
1145 struct sscop_msg *s;
1146
1147 if (rn != SSCOP_RETRIEVE_UNKNOWN) {
1148 if(rn >= SSCOP_RETRIEVE_TOTAL)
1149 rn = sscop->vt_a;
1150 else
1151 rn++;
1152 while(rn >= sscop->vt_a && rn < sscop->vt_s) {
1153 if(rn == SSCOP_MAXSEQNO) rn = 0;
1154 if((s = QFIND(&sscop->xbuf, rn)) != NULL) {
1155 MSGQ_REMOVE(&sscop->xbuf, s);
1156 AAL_DATA(sscop, SSCOP_RETRIEVE_indication,
1157 s->m, 0);
1158 MSG_FREE(s);
1159 }
1160 rn++;
1161 }
1162 }
1163
1164 while((s = MSGQ_GET(&sscop->xq)) != NULL) {
1165 AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0);
1166 MSG_FREE(s);
1167 }
1168 AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication);
1169 }
1170
1171 /*
1172 * P 76: Detect retransmission. PDU type must already be stripped.
1173 */
1174 static int
1175 m_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg)
1176 {
1177 union bgn bgn;
1178
1179 bgn.sscop_null = MBUF_TRAIL32(msg->m, -1);
1180
1181 if (sscop->vr_sq == bgn.sscop_bgns)
1182 return (1);
1183
1184 sscop->vr_sq = bgn.sscop_bgns;
1185 return (0);
1186 }
1187
1188 /*
1189 * P 76: Set POLL timer
1190 */
1191 static void
1192 m_set_poll_timer(struct sscop *sscop)
1193 {
1194 if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a)
1195 TIMER_RESTART(sscop, ka);
1196 else
1197 TIMER_RESTART(sscop, poll);
1198 }
1199
1200 /*
1201 * P 77: Reset data transfer timers
1202 */
1203 static void
1204 m_reset_data_xfer_timers(struct sscop *sscop)
1205 {
1206 TIMER_STOP(sscop, ka);
1207 TIMER_STOP(sscop, nr);
1208 TIMER_STOP(sscop, idle);
1209 TIMER_STOP(sscop, poll);
1210 }
1211
1212 /*
1213 * P 77: Set data transfer timers
1214 */
1215 static void
1216 m_set_data_xfer_timers(struct sscop *sscop)
1217 {
1218 TIMER_RESTART(sscop, poll);
1219 TIMER_RESTART(sscop, nr);
1220 }
1221
1222 /*
1223 * P 77: Initialize VR(MR)
1224 */
1225 static void
1226 m_initialize_mr(struct sscop *sscop)
1227 {
1228 sscop->vr_mr = sscop->mr;
1229 }
1230
1231 /************************************************************/
1232 /*
1233 * CONDITIONS
1234 */
1235 static int
1236 c_ready_pduq(struct sscop *sscop)
1237 {
1238 if (!sscop->ll_busy &&
1239 (sscop->rxq != 0 ||
1240 sscop->vt_s < sscop->vt_ms ||
1241 TIMER_ISACT(sscop, idle)))
1242 return (1);
1243 return (0);
1244 }
1245
1246 /************************************************************/
1247 /*
1248 * SEND PDUS
1249 */
1250
1251 /*
1252 * Send BG PDU.
1253 */
1254 static void
1255 send_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1256 {
1257 union pdu pdu;
1258 union bgn bgn;
1259 struct SSCOP_MBUF_T *m;
1260
1261 pdu.sscop_null = 0;
1262 pdu.sscop_type = PDU_BGN;
1263 pdu.sscop_ns = sscop->vr_mr;
1264
1265 bgn.sscop_null = 0;
1266 bgn.sscop_bgns = sscop->vt_sq;
1267
1268 if(uu) {
1269 if ((m = MBUF_DUP(uu)) == NULL) {
1270 FAILURE("sscop: cannot allocate BGN");
1271 return;
1272 }
1273 pdu.sscop_pl += MBUF_PAD4(m);
1274 } else {
1275 if ((m = MBUF_ALLOC(8)) == NULL) {
1276 FAILURE("sscop: cannot allocate BGN");
1277 return;
1278 }
1279 }
1280
1281 MBUF_APPEND32(m, bgn.sscop_null);
1282 MBUF_APPEND32(m, pdu.sscop_null);
1283
1284 AAL_SEND(sscop, m);
1285 }
1286
1287 /*
1288 * Send BGREJ PDU.
1289 */
1290 static void
1291 send_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1292 {
1293 union pdu pdu;
1294 union bgn bgn;
1295 struct SSCOP_MBUF_T *m;
1296
1297 pdu.sscop_null = 0;
1298 pdu.sscop_type = PDU_BGREJ;
1299 bgn.sscop_null = 0;
1300
1301 if(uu) {
1302 if((m = MBUF_DUP(uu)) == NULL) {
1303 FAILURE("sscop: cannot allocate BGREJ");
1304 return;
1305 }
1306 pdu.sscop_pl += MBUF_PAD4(m);
1307 } else {
1308 if((m = MBUF_ALLOC(8)) == NULL) {
1309 FAILURE("sscop: cannot allocate BGREJ");
1310 return;
1311 }
1312 }
1313
1314 MBUF_APPEND32(m, bgn.sscop_null);
1315 MBUF_APPEND32(m, pdu.sscop_null);
1316
1317 AAL_SEND(sscop, m);
1318 }
1319
1320 /*
1321 * Send BGAK PDU.
1322 */
1323 static void
1324 send_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
1325 {
1326 union pdu pdu;
1327 union bgn bgn;
1328 struct SSCOP_MBUF_T *m;
1329
1330 pdu.sscop_null = 0;
1331 pdu.sscop_type = PDU_BGAK;
1332 pdu.sscop_ns = sscop->vr_mr;
1333 bgn.sscop_null = 0;
1334
1335 if(uu) {
1336 if((m = MBUF_DUP(uu)) == NULL) {
1337 FAILURE("sscop: cannot allocate BGAK");
1338 return;
1339 }
1340 pdu.sscop_pl += MBUF_PAD4(m);
1341 } else {
1342 if((m = MBUF_ALLOC(8)) == NULL) {
1343 FAILURE("sscop: cannot allocate BGAK");
1344 return;
1345 }
1346 }
1347
1348 MBUF_APPEND32(m, bgn.sscop_null);
1349 MBUF_APPEND32(m, pdu.sscop_null);
1350
1351 AAL_SEND(sscop, m);
1352 }
1353
1354 /*
1355 * Send SD PDU. The function makes a duplicate of the message.
1356 */
1357 static void
1358 send_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno)
1359 {
1360 union pdu pdu;
1361
1362 if((m = MBUF_DUP(m)) == NULL) {
1363 FAILURE("sscop: cannot allocate SD");
1364 return;
1365 }
1366
1367 pdu.sscop_null = 0;
1368 pdu.sscop_pl = 0;
1369 pdu.sscop_type = PDU_SD;
1370 pdu.sscop_ns = seqno;
1371
1372 pdu.sscop_pl += MBUF_PAD4(m);
1373
1374 MBUF_APPEND32(m, pdu.sscop_null);
1375
1376 AAL_SEND(sscop, m);
1377 }
1378
1379 /*
1380 * Send a UD PDU. The caller must free the sscop msg part.
1381 */
1382 static void
1383 send_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m)
1384 {
1385 union pdu pdu;
1386
1387 pdu.sscop_null = 0;
1388 pdu.sscop_type = PDU_UD;
1389
1390 pdu.sscop_pl += MBUF_PAD4(m);
1391
1392 MBUF_APPEND32(m, pdu.sscop_null);
1393
1394 AAL_SEND(sscop, m);
1395 }
1396
1397 /*
1398 * Send a MD PDU. The caller must free the sscop msg part.
1399 */
1400 static void
1401 send_md(struct sscop *sscop, struct SSCOP_MBUF_T *m)
1402 {
1403 union pdu pdu;
1404
1405 pdu.sscop_null = 0;
1406 pdu.sscop_type = PDU_MD;
1407
1408 pdu.sscop_pl += MBUF_PAD4(m);
1409
1410 MBUF_APPEND32(m, pdu.sscop_null);
1411
1412 AAL_SEND(sscop, m);
1413 }
1414
1415 /*
1416 * Send END PDU.
1417 */
1418 static void
1419 send_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu)
1420 {
1421 union pdu pdu;
1422 struct SSCOP_MBUF_T *m;
1423
1424 sscop->last_end_src = src;
1425
1426 pdu.sscop_null = 0;
1427 pdu.sscop_s = src;
1428 pdu.sscop_type = PDU_END;
1429
1430 if(uu) {
1431 if((m = MBUF_DUP(uu)) == NULL) {
1432 FAILURE("sscop: cannot allocate END");
1433 return;
1434 }
1435 pdu.sscop_pl += MBUF_PAD4(m);
1436 } else {
1437 if((m = MBUF_ALLOC(8)) == NULL) {
1438 FAILURE("sscop: cannot allocate END");
1439 return;
1440 }
1441 }
1442
1443 MBUF_APPEND32(m, 0);
1444 MBUF_APPEND32(m, pdu.sscop_null);
1445
1446 AAL_SEND(sscop, m);
1447 }
1448
1449 /*
1450 * Send USTAT PDU. List must be terminated by -1.
1451 */
1452 static void
1453 send_ustat(struct sscop *sscop, ...)
1454 {
1455 va_list ap;
1456 int f;
1457 u_int n;
1458 union pdu pdu;
1459 union seqno seqno;
1460 struct SSCOP_MBUF_T *m;
1461
1462 va_start(ap, sscop);
1463 n = 0;
1464 while((f = va_arg(ap, int)) >= 0)
1465 n++;
1466 va_end(ap);
1467
1468 if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) {
1469 FAILURE("sscop: cannot allocate USTAT");
1470 return;
1471 }
1472
1473 va_start(ap, sscop);
1474 while((f = va_arg(ap, int)) >= 0) {
1475 seqno.sscop_null = 0;
1476 seqno.sscop_n = f;
1477 MBUF_APPEND32(m, seqno.sscop_null);
1478 }
1479 va_end(ap);
1480
1481 seqno.sscop_null = 0;
1482 seqno.sscop_n = sscop->vr_mr;
1483 MBUF_APPEND32(m, seqno.sscop_null);
1484
1485 pdu.sscop_null = 0;
1486 pdu.sscop_type = PDU_USTAT;
1487 pdu.sscop_ns = sscop->vr_r;
1488 MBUF_APPEND32(m, pdu.sscop_null);
1489
1490 AAL_SEND(sscop, m);
1491 }
1492
1493 /*
1494 * Send ER PDU.
1495 */
1496 static void
1497 send_er(struct sscop *sscop)
1498 {
1499 union pdu pdu;
1500 union bgn bgn;
1501 struct SSCOP_MBUF_T *m;
1502
1503 pdu.sscop_null = 0;
1504 pdu.sscop_type = PDU_ER;
1505 pdu.sscop_ns = sscop->vr_mr;
1506
1507 bgn.sscop_null = 0;
1508 bgn.sscop_bgns = sscop->vt_sq;
1509
1510 if((m = MBUF_ALLOC(8)) == NULL) {
1511 FAILURE("sscop: cannot allocate ER");
1512 return;
1513 }
1514 MBUF_APPEND32(m, bgn.sscop_null);
1515 MBUF_APPEND32(m, pdu.sscop_null);
1516
1517 AAL_SEND(sscop, m);
1518 }
1519
1520 /*
1521 * Send POLL PDU.
1522 */
1523 static void
1524 send_poll(struct sscop *sscop)
1525 {
1526 union pdu pdu;
1527 union seqno seqno;
1528 struct SSCOP_MBUF_T *m;
1529
1530 seqno.sscop_null = 0;
1531 seqno.sscop_n = sscop->vt_ps;
1532
1533 pdu.sscop_null = 0;
1534 pdu.sscop_ns = sscop->vt_s;
1535 pdu.sscop_type = PDU_POLL;
1536
1537 if((m = MBUF_ALLOC(8)) == NULL) {
1538 FAILURE("sscop: cannot allocate POLL");
1539 return;
1540 }
1541 MBUF_APPEND32(m, seqno.sscop_null);
1542 MBUF_APPEND32(m, pdu.sscop_null);
1543
1544 AAL_SEND(sscop, m);
1545 }
1546
1547 /*
1548 * Send STAT PDU. List is already in buffer.
1549 */
1550 static void
1551 send_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m)
1552 {
1553 union pdu pdu;
1554 union seqno seqno;
1555
1556 seqno.sscop_null = 0;
1557 seqno.sscop_n = nps;
1558 MBUF_APPEND32(m, seqno.sscop_null);
1559
1560 seqno.sscop_null = 0;
1561 seqno.sscop_n = sscop->vr_mr;
1562 MBUF_APPEND32(m, seqno.sscop_null);
1563
1564 pdu.sscop_null = 0;
1565 pdu.sscop_type = PDU_STAT;
1566 pdu.sscop_ns = sscop->vr_r;
1567 MBUF_APPEND32(m, pdu.sscop_null);
1568
1569 AAL_SEND(sscop, m);
1570 }
1571
1572 /*
1573 * Send ENDAK PDU.
1574 */
1575 static void
1576 send_endak(struct sscop *sscop)
1577 {
1578 union pdu pdu;
1579 union seqno seqno;
1580 struct SSCOP_MBUF_T *m;
1581
1582 seqno.sscop_null = 0;
1583 pdu.sscop_null = 0;
1584 pdu.sscop_type = PDU_ENDAK;
1585
1586 if((m = MBUF_ALLOC(8)) == NULL) {
1587 FAILURE("sscop: cannot allocate ENDAK");
1588 return;
1589 }
1590 MBUF_APPEND32(m, seqno.sscop_null);
1591 MBUF_APPEND32(m, pdu.sscop_null);
1592
1593 AAL_SEND(sscop, m);
1594 }
1595
1596 /*
1597 * Send ERAK PDU.
1598 */
1599 static void
1600 send_erak(struct sscop *sscop)
1601 {
1602 union pdu pdu;
1603 union seqno seqno;
1604 struct SSCOP_MBUF_T *m;
1605
1606 seqno.sscop_null = 0;
1607 pdu.sscop_null = 0;
1608 pdu.sscop_type = PDU_ERAK;
1609 pdu.sscop_ns = sscop->vr_mr;
1610
1611 if((m = MBUF_ALLOC(8)) == NULL) {
1612 FAILURE("sscop: cannot allocate ERAK");
1613 return;
1614 }
1615 MBUF_APPEND32(m, seqno.sscop_null);
1616 MBUF_APPEND32(m, pdu.sscop_null);
1617
1618 AAL_SEND(sscop, m);
1619 }
1620
1621 /*
1622 * Send RS PDU
1623 */
1624 static void
1625 send_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu)
1626 {
1627 union pdu pdu;
1628 union bgn bgn;
1629 struct SSCOP_MBUF_T *m;
1630
1631 pdu.sscop_null = 0;
1632 pdu.sscop_type = PDU_RS;
1633 pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr;
1634
1635 bgn.sscop_null = 0;
1636 bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq;
1637
1638 sscop->rs_mr = pdu.sscop_ns;
1639 sscop->rs_sq = bgn.sscop_bgns;
1640
1641 if(uu) {
1642 if((m = MBUF_DUP(uu)) == NULL) {
1643 FAILURE("sscop: cannot allocate RS");
1644 return;
1645 }
1646 pdu.sscop_pl += MBUF_PAD4(m);
1647 } else {
1648 if((m = MBUF_ALLOC(8)) == NULL) {
1649 FAILURE("sscop: cannot allocate RS");
1650 return;
1651 }
1652 }
1653
1654 MBUF_APPEND32(m, bgn.sscop_null);
1655 MBUF_APPEND32(m, pdu.sscop_null);
1656
1657 AAL_SEND(sscop, m);
1658 }
1659
1660 /*
1661 * Send RSAK pdu
1662 */
1663 static void
1664 send_rsak(struct sscop *sscop)
1665 {
1666 union pdu pdu;
1667 union seqno seqno;
1668 struct SSCOP_MBUF_T *m;
1669
1670 seqno.sscop_null = 0;
1671 pdu.sscop_null = 0;
1672 pdu.sscop_type = PDU_RSAK;
1673 pdu.sscop_ns = sscop->vr_mr;
1674
1675 if((m = MBUF_ALLOC(8)) == NULL) {
1676 FAILURE("sscop: cannot allocate RSAK");
1677 return;
1678 }
1679
1680 MBUF_APPEND32(m, seqno.sscop_null);
1681 MBUF_APPEND32(m, pdu.sscop_null);
1682
1683 AAL_SEND(sscop, m);
1684 }
1685
1686 /************************************************************/
1687 /*
1688 * P 31; IDLE && AA-ESTABLISH-request
1689 * arg is UU data (opt).
1690 */
1691 static void
1692 sscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu)
1693 {
1694 u_int br = uu->rexmit;
1695
1696 SET_UU(uu_bgn, uu);
1697
1698 m_clear_transmitter(sscop);
1699
1700 sscop->clear_buffers = br;
1701
1702 sscop->vt_cc = 1;
1703 sscop->vt_sq++;
1704
1705 m_initialize_mr(sscop);
1706
1707 send_bgn(sscop, sscop->uu_bgn);
1708
1709 TIMER_RESTART(sscop, cc);
1710
1711 sscop_set_state(sscop, SSCOP_OUT_PEND);
1712 }
1713
1714 /*
1715 * P 31: IDLE && BGN PDU
1716 * arg is the received PDU (freed).
1717 */
1718 static void
1719 sscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg)
1720 {
1721 union pdu pdu;
1722 union bgn bgn;
1723
1724 pdu.sscop_null = MBUF_STRIP32(msg->m);
1725
1726 if(sscop->robustness) {
1727 bgn.sscop_null = MBUF_STRIP32(msg->m);
1728 sscop->vr_sq = bgn.sscop_bgns;
1729 } else {
1730 if(m_detect_retransmission(sscop, msg)) {
1731 send_bgrej(sscop, sscop->uu_bgrej);
1732 SSCOP_MSG_FREE(msg);
1733 return;
1734 }
1735 (void)MBUF_STRIP32(msg->m);
1736 }
1737
1738 sscop->vt_ms = pdu.sscop_ns;
1739 sscop_set_state(sscop, SSCOP_IN_PEND);
1740
1741 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
1742 }
1743
1744 /*
1745 * p 31: IDLE && ENDAK PDU
1746 * p 34: OUT_PEND && ENDAK PDU
1747 * p 34: OUT_PEND && SD PDU
1748 * p 34: OUT_PEND && ERAK PDU
1749 * p 34: OUT_PEND && END PDU
1750 * p 34: OUT_PEND && STAT PDU
1751 * p 34: OUT_PEND && USTAT PDU
1752 * p 34: OUT_PEND && POLL PDU
1753 * p 36: OUT_PEND && RS PDU
1754 * p 36: OUT_PEND && RSAK PDU
1755 * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU
1756 * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU
1757 * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU
1758 * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU
1759 * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU
1760 * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU
1761 * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU
1762 * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU
1763 * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU
1764 * p 43: OUTGOING_RESYNC && ER PDU
1765 * p 43: OUTGOING_RESYNC && POLL PDU
1766 * p 44: OUTGOING_RESYNC && STAT PDU
1767 * p 44: OUTGOING_RESYNC && USTAT PDU
1768 * p 45: OUTGOING_RESYNC && BGAK PDU
1769 * p 45: OUTGOING_RESYNC && SD PDU
1770 * p 45: OUTGOING_RESYNC && ERAK PDU
1771 * P 60: READY && BGAK PDU
1772 * P 60: READY && ERAK PDU
1773 * arg is pdu (freed).
1774 */
1775 static void
1776 sscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg)
1777 {
1778 SSCOP_MSG_FREE(msg);
1779 }
1780
1781 /*
1782 * p 31: IDLE && END PDU
1783 * arg is pdu (freed).
1784 */
1785 static void
1786 sscop_idle_end(struct sscop *sscop, struct sscop_msg *msg)
1787 {
1788 SSCOP_MSG_FREE(msg);
1789 send_endak(sscop);
1790 }
1791
1792 /*
1793 * p 31: IDLE && ER PDU
1794 * arg is pdu (freed).
1795 */
1796 static void
1797 sscop_idle_er(struct sscop *sscop, struct sscop_msg *msg)
1798 {
1799 SSCOP_MSG_FREE(msg);
1800 MAAL_ERROR(sscop, 'L', 0);
1801 FREE_UU(uu_end);
1802 send_end(sscop, 1, NULL);
1803 }
1804
1805 /*
1806 * p 31: IDLE && BGREJ PDU
1807 * arg is pdu (freed).
1808 */
1809 static void
1810 sscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg)
1811 {
1812 SSCOP_MSG_FREE(msg);
1813 MAAL_ERROR(sscop, 'D', 0);
1814 FREE_UU(uu_end);
1815 }
1816
1817 /*
1818 * p 32: IDLE && POLL PDU
1819 * arg is pdu (freed).
1820 */
1821 static void
1822 sscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg)
1823 {
1824 SSCOP_MSG_FREE(msg);
1825 MAAL_ERROR(sscop, 'G', 0);
1826 FREE_UU(uu_end);
1827 send_end(sscop, 1, NULL);
1828 }
1829
1830 /*
1831 * p 32: IDLE && SD PDU
1832 * arg is pdu (freed).
1833 */
1834 static void
1835 sscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg)
1836 {
1837 SSCOP_MSG_FREE(msg);
1838 MAAL_ERROR(sscop, 'A', 0);
1839 FREE_UU(uu_end);
1840 send_end(sscop, 1, NULL);
1841 }
1842
1843 /*
1844 * p 32: IDLE && BGAK PDU
1845 * arg is pdu (freed).
1846 */
1847 static void
1848 sscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg)
1849 {
1850 SSCOP_MSG_FREE(msg);
1851 MAAL_ERROR(sscop, 'C', 0);
1852 FREE_UU(uu_end);
1853 send_end(sscop, 1, NULL);
1854 }
1855
1856 /*
1857 * p 32: IDLE && ERAK PDU
1858 * arg is pdu (freed).
1859 */
1860 static void
1861 sscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg)
1862 {
1863 SSCOP_MSG_FREE(msg);
1864 MAAL_ERROR(sscop, 'M', 0);
1865 FREE_UU(uu_end);
1866 send_end(sscop, 1, NULL);
1867 }
1868
1869 /*
1870 * p 32: IDLE && STAT PDU
1871 * arg is pdu (freed).
1872 */
1873 static void
1874 sscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg)
1875 {
1876 SSCOP_MSG_FREE(msg);
1877 MAAL_ERROR(sscop, 'H', 0);
1878 FREE_UU(uu_end);
1879 send_end(sscop, 1, NULL);
1880 }
1881
1882 /*
1883 * p 32: IDLE && USTAT PDU
1884 * arg is pdu (freed).
1885 */
1886 static void
1887 sscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg)
1888 {
1889 SSCOP_MSG_FREE(msg);
1890 MAAL_ERROR(sscop, 'I', 0);
1891 FREE_UU(uu_end);
1892 send_end(sscop, 1, NULL);
1893 }
1894
1895 /*
1896 * p 33: IDLE & RS PDU
1897 * arg is pdu (freed).
1898 */
1899 static void
1900 sscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg)
1901 {
1902 SSCOP_MSG_FREE(msg);
1903 MAAL_ERROR(sscop, 'J', 0);
1904 FREE_UU(uu_end);
1905 send_end(sscop, 1, NULL);
1906 }
1907
1908 /*
1909 * p 33: IDLE & RSAK PDU
1910 * arg is pdu (freed).
1911 */
1912 static void
1913 sscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg)
1914 {
1915 SSCOP_MSG_FREE(msg);
1916 MAAL_ERROR(sscop, 'K', 0);
1917 FREE_UU(uu_end);
1918 send_end(sscop, 1, NULL);
1919 }
1920
1921 /*
1922 * p 33: IDLE && PDU_Q
1923 * p XX: OUTPEND && PDU_Q
1924 * p 39: IN_PEND && PDU_Q
1925 * p 45: OUT_RESYNC_PEND && PDU_Q
1926 * p 48: IN_RESYNC_PEND && PDU_Q
1927 * no arg
1928 */
1929 static void
1930 sscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused)
1931 {
1932 #if 0
1933 MSGQ_CLEAR(&sscop->xq);
1934 #endif
1935 }
1936
1937 /*
1938 * p 34: OUT_PEND && BGAK PDU
1939 * arg is pdu (freed).
1940 */
1941 static void
1942 sscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
1943 {
1944 union pdu pdu;
1945
1946 pdu.sscop_null = MBUF_STRIP32(msg->m);
1947 (void)MBUF_STRIP32(msg->m);
1948
1949 TIMER_STOP(sscop, cc);
1950 sscop->vt_ms = pdu.sscop_ns;
1951
1952 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
1953
1954 m_initialize_state(sscop);
1955 m_set_data_xfer_timers(sscop);
1956
1957 sscop_set_state(sscop, SSCOP_READY);
1958 }
1959
1960 /*
1961 * P 34: OUT_PEND && BGREJ PDU
1962 */
1963 static void
1964 sscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
1965 {
1966 union pdu pdu;
1967
1968 pdu.sscop_null = MBUF_STRIP32(msg->m);
1969 (void)MBUF_STRIP32(msg->m);
1970
1971 TIMER_STOP(sscop, cc);
1972
1973 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0);
1974
1975 sscop_set_state(sscop, SSCOP_IDLE);
1976 }
1977
1978 /*
1979 * P 35: OUT_PEND && TIMER_CC expiry
1980 * no arg
1981 */
1982 static void
1983 sscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused)
1984 {
1985 if(sscop->vt_cc >= sscop->maxcc) {
1986 MAAL_ERROR(sscop, 'O', 0);
1987 FREE_UU(uu_end);
1988 send_end(sscop, 1, NULL);
1989
1990 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
1991
1992 sscop_set_state(sscop, SSCOP_IDLE);
1993 } else {
1994 sscop->vt_cc++;
1995 send_bgn(sscop, sscop->uu_bgn);
1996 TIMER_RESTART(sscop, cc);
1997 }
1998 }
1999
2000 /*
2001 * P 35: OUT_PEND && RELEASE_REQ
2002 * arg is UU
2003 */
2004 static void
2005 sscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
2006 {
2007 SET_UU(uu_end, uu);
2008
2009 TIMER_STOP(sscop, cc);
2010 sscop->vt_cc = 1;
2011 send_end(sscop, 0, sscop->uu_end);
2012 TIMER_RESTART(sscop, cc);
2013
2014 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2015 }
2016
2017 /*
2018 * P 36: OUT_PEND && BGN PDU
2019 * arg is the received PDU (freed).
2020 */
2021 static void
2022 sscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
2023 {
2024 union pdu pdu;
2025
2026 pdu.sscop_null = MBUF_STRIP32(msg->m);
2027
2028 if(m_detect_retransmission(sscop, msg)) {
2029 SSCOP_MSG_FREE(msg);
2030 return;
2031 }
2032 (void)MBUF_STRIP32(msg->m);
2033
2034 TIMER_STOP(sscop, cc);
2035
2036 sscop->vt_ms = pdu.sscop_ns;
2037
2038 m_initialize_mr(sscop);
2039
2040 send_bgak(sscop, sscop->uu_bgak);
2041
2042 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
2043
2044 m_initialize_state(sscop);
2045
2046 m_set_data_xfer_timers(sscop);
2047
2048 sscop_set_state(sscop, SSCOP_READY);
2049 }
2050
2051 /*
2052 * p 37: IN_PEND && AA-ESTABLISH.response
2053 * arg is UU
2054 */
2055 static void
2056 sscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu)
2057 {
2058 u_int br = uu->rexmit;
2059
2060 SET_UU(uu_bgak, uu);
2061
2062 m_clear_transmitter(sscop);
2063 sscop->clear_buffers = br;
2064 m_initialize_mr(sscop);
2065 send_bgak(sscop, sscop->uu_bgak);
2066 m_initialize_state(sscop);
2067 m_set_data_xfer_timers(sscop);
2068
2069 sscop_set_state(sscop, SSCOP_READY);
2070 }
2071
2072 /*
2073 * p 37: IN_PEND && AA-RELEASE.request
2074 * arg is uu.
2075 */
2076 static void
2077 sscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
2078 {
2079 SET_UU(uu_bgrej, uu);
2080
2081 send_bgrej(sscop, sscop->uu_bgrej);
2082
2083 sscop_set_state(sscop, SSCOP_IDLE);
2084 }
2085
2086 /*
2087 * p 37: IN_PEND && BGN PDU
2088 * arg is pdu. (freed)
2089 */
2090 static void
2091 sscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
2092 {
2093 union pdu pdu;
2094
2095 pdu.sscop_null = MBUF_STRIP32(msg->m);
2096
2097 if(m_detect_retransmission(sscop, msg)) {
2098 SSCOP_MSG_FREE(msg);
2099 return;
2100 }
2101 (void)MBUF_STRIP32(msg->m);
2102
2103 sscop->vt_ms = pdu.sscop_ns;
2104
2105 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2106 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
2107 }
2108
2109 /*
2110 * p 37: IN_PEND && ER PDU
2111 * arg is pdu (freed).
2112 */
2113 static void
2114 sscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg)
2115 {
2116 MAAL_ERROR(sscop, 'L', 0);
2117 SSCOP_MSG_FREE(msg);
2118 }
2119
2120 /*
2121 * p 37: IN_PEND && ENDAK PDU
2122 * arg is pdu (freed).
2123 */
2124 static void
2125 sscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg)
2126 {
2127 MAAL_ERROR(sscop, 'F', 0);
2128
2129 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2130
2131 sscop_set_state(sscop, SSCOP_IDLE);
2132
2133 SSCOP_MSG_FREE(msg);
2134 }
2135
2136 /*
2137 * p 38: IN_PEND && BGAK PDU
2138 * arg is pdu (freed).
2139 */
2140 static void
2141 sscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
2142 {
2143 MAAL_ERROR(sscop, 'C', 0);
2144
2145 SSCOP_MSG_FREE(msg);
2146 }
2147
2148 /*
2149 * p 38: IN_PEND && BGREJ PDU
2150 * arg is pdu (freed).
2151 */
2152 static void
2153 sscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2154 {
2155 MAAL_ERROR(sscop, 'D', 0);
2156
2157 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2158
2159 SSCOP_MSG_FREE(msg);
2160
2161 sscop_set_state(sscop, SSCOP_IDLE);
2162 }
2163
2164 /*
2165 * p 38: IN_PEND && SD PDU
2166 * arg is pdu (freed).
2167 */
2168 static void
2169 sscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg)
2170 {
2171 MAAL_ERROR(sscop, 'A', 0);
2172
2173 SSCOP_MSG_FREE(msg);
2174
2175 FREE_UU(uu_end);
2176 send_end(sscop, 1, NULL);
2177
2178 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2179
2180 sscop_set_state(sscop, SSCOP_IDLE);
2181 }
2182
2183 /*
2184 * p 38: IN_PEND && USTAT PDU
2185 * arg is pdu (freed).
2186 */
2187 static void
2188 sscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg)
2189 {
2190 MAAL_ERROR(sscop, 'I', 0);
2191
2192 SSCOP_MSG_FREE(msg);
2193
2194 FREE_UU(uu_end);
2195 send_end(sscop, 1, NULL);
2196
2197 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2198
2199 sscop_set_state(sscop, SSCOP_IDLE);
2200 }
2201
2202 /*
2203 * p 38: IN_PEND && STAT PDU
2204 * arg is pdu (freed).
2205 */
2206 static void
2207 sscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg)
2208 {
2209 MAAL_ERROR(sscop, 'H', 0);
2210
2211 SSCOP_MSG_FREE(msg);
2212
2213 FREE_UU(uu_end);
2214 send_end(sscop, 1, NULL);
2215
2216 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2217
2218 sscop_set_state(sscop, SSCOP_IDLE);
2219 }
2220
2221 /*
2222 * p 38: IN_PEND && POLL PDU
2223 * arg is pdu (freed).
2224 */
2225 static void
2226 sscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg)
2227 {
2228 MAAL_ERROR(sscop, 'G', 0);
2229
2230 SSCOP_MSG_FREE(msg);
2231
2232 FREE_UU(uu_end);
2233 send_end(sscop, 1, NULL);
2234
2235 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2236
2237 sscop_set_state(sscop, SSCOP_IDLE);
2238 }
2239
2240 /*
2241 * p 39: IN_PEND && ERAK PDU
2242 * arg is pdu (freed).
2243 */
2244 static void
2245 sscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg)
2246 {
2247 SSCOP_MSG_FREE(msg);
2248 MAAL_ERROR(sscop, 'M', 0);
2249 }
2250
2251 /*
2252 * p 39: IN_PEND & RS PDU
2253 * arg is pdu (freed).
2254 */
2255 static void
2256 sscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg)
2257 {
2258 SSCOP_MSG_FREE(msg);
2259 MAAL_ERROR(sscop, 'J', 0);
2260 }
2261
2262 /*
2263 * p 39: IN_PEND & RSAK PDU
2264 * arg is pdu (freed).
2265 */
2266 static void
2267 sscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg)
2268 {
2269 SSCOP_MSG_FREE(msg);
2270 MAAL_ERROR(sscop, 'K', 0);
2271 }
2272
2273 /*
2274 * p 39: IN_PEND && END PDU
2275 * arg is pdu (freed).
2276 * no uui
2277 */
2278 static void
2279 sscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg)
2280 {
2281 union pdu pdu;
2282
2283 pdu.sscop_null = MBUF_STRIP32(msg->m);
2284 (void)MBUF_STRIP32(msg->m);
2285
2286 send_endak(sscop);
2287
2288 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2289 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2290
2291 sscop_set_state(sscop, SSCOP_IDLE);
2292 }
2293
2294 /*
2295 * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request
2296 * no arg.
2297 * no uui.
2298 */
2299 static void
2300 sscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu)
2301 {
2302 SET_UU(uu_bgn, uu);
2303
2304 TIMER_STOP(sscop, cc);
2305 m_clear_transmitter(sscop);
2306 sscop->clear_buffers = 1;
2307 sscop->vt_cc = 1;
2308 sscop->vt_sq++;
2309 m_initialize_mr(sscop);
2310 send_bgn(sscop, sscop->uu_bgn);
2311 TIMER_RESTART(sscop, cc);
2312
2313 sscop_set_state(sscop, SSCOP_OUT_PEND);
2314 }
2315
2316 /*
2317 * p 41: OUT_DIS_PEND && END PDU
2318 * arg is pdu (freed).
2319 */
2320 static void
2321 sscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg)
2322 {
2323 union pdu pdu;
2324
2325 pdu.sscop_null = MBUF_STRIP32(msg->m);
2326 (void)MBUF_STRIP32(msg->m);
2327
2328 TIMER_STOP(sscop, cc);
2329 send_endak(sscop);
2330
2331 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
2332
2333 sscop_set_state(sscop, SSCOP_IDLE);
2334 }
2335
2336 /*
2337 * p 41: OUT_DIS_PEND && ENDAK PDU
2338 * p 41: OUT_DIS_PEND && BGREJ PDU
2339 * arg is pdu (freed)
2340 */
2341 static void
2342 sscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg)
2343 {
2344 union pdu pdu;
2345
2346 pdu.sscop_null = MBUF_STRIP32(msg->m);
2347 (void)MBUF_STRIP32(msg->m);
2348
2349 TIMER_STOP(sscop, cc);
2350
2351 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
2352
2353 sscop_set_state(sscop, SSCOP_IDLE);
2354 }
2355
2356 /*
2357 * p 41: OUT_DIS_PEND && TIMER CC expiry
2358 * no arg
2359 */
2360 static void
2361 sscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
2362 {
2363 if(sscop->vt_cc >= sscop->maxcc) {
2364 MAAL_ERROR(sscop, 'O', 0);
2365 AAL_SIG(sscop, SSCOP_RELEASE_confirm);
2366 sscop_set_state(sscop, SSCOP_IDLE);
2367 } else {
2368 sscop->vt_cc++;
2369 send_end(sscop, sscop->last_end_src, sscop->uu_end);
2370 TIMER_RESTART(sscop, cc);
2371 }
2372 }
2373
2374 /*
2375 * p 42: OUT_DIS_PEND && BGN PDU
2376 * arg is pdu (freed).
2377 */
2378 static void
2379 sscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg)
2380 {
2381 union pdu pdu;
2382
2383 pdu.sscop_null = MBUF_STRIP32(msg->m);
2384
2385 if(m_detect_retransmission(sscop, msg)) {
2386 FREE_UU(uu_bgak);
2387 send_bgak(sscop, NULL);
2388 send_end(sscop, sscop->last_end_src, sscop->uu_end);
2389 SSCOP_MSG_FREE(msg);
2390
2391 } else {
2392 (void)MBUF_STRIP32(msg->m);
2393
2394 TIMER_STOP(sscop, cc);
2395 sscop->vt_ms = pdu.sscop_ns;
2396 AAL_SIG(sscop, SSCOP_RELEASE_confirm);
2397 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2398 msg, pdu.sscop_pl, 0);
2399 sscop_set_state(sscop, SSCOP_IN_PEND);
2400 }
2401 }
2402
2403 /*
2404 * p 43: OUT_RESYNC_PEND && BGN PDU
2405 * arg is pdu (freed).
2406 */
2407 static void
2408 sscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg)
2409 {
2410 union pdu pdu;
2411
2412 pdu.sscop_null = MBUF_STRIP32(msg->m);
2413
2414 if(m_detect_retransmission(sscop, msg)) {
2415 send_bgak(sscop, sscop->uu_bgak);
2416 send_rs(sscop, 1, sscop->uu_rs);
2417 SSCOP_MSG_FREE(msg);
2418 } else {
2419 (void)MBUF_STRIP32(msg->m);
2420
2421 TIMER_STOP(sscop, cc);
2422 sscop->vt_ms = pdu.sscop_ns;
2423 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2424 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2425 msg, pdu.sscop_pl, 0);
2426 sscop_set_state(sscop, SSCOP_IN_PEND);
2427 }
2428 }
2429
2430 /*
2431 * p 43: OUT_RESYNC_PEND && ENDAK PDU
2432 * arg is pdu (freed).
2433 */
2434 static void
2435 sscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg)
2436 {
2437 SSCOP_MSG_FREE(msg);
2438 TIMER_STOP(sscop, cc);
2439 MAAL_ERROR(sscop, 'F', 0);
2440 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2441 sscop_set_state(sscop, SSCOP_IDLE);
2442 }
2443
2444 /*
2445 * p 43: OUT_RESYNC_PEND && BGREJ PDU
2446 * arg is pdu (freed).
2447 */
2448 static void
2449 sscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2450 {
2451 SSCOP_MSG_FREE(msg);
2452 TIMER_STOP(sscop, cc);
2453 MAAL_ERROR(sscop, 'D', 0);
2454 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2455 sscop_set_state(sscop, SSCOP_IDLE);
2456 }
2457
2458 /*
2459 * p 43: OUT_RESYNC_PEND && END PDU
2460 * arg is pdu (freed).
2461 * no UU-data
2462 */
2463 static void
2464 sscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg)
2465 {
2466 union pdu pdu;
2467
2468 pdu.sscop_null = MBUF_STRIP32(msg->m);
2469 (void)MBUF_STRIP32(msg->m);
2470
2471 TIMER_STOP(sscop, cc);
2472 send_endak(sscop);
2473 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl,
2474 (u_int)pdu.sscop_s);
2475 sscop_set_state(sscop, SSCOP_IDLE);
2476 }
2477
2478 /*
2479 * p 44: OUT_RESYNC && TIMER CC expiry
2480 */
2481 static void
2482 sscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused)
2483 {
2484 if(sscop->vt_cc == sscop->maxcc) {
2485 MAAL_ERROR(sscop, 'O', 0);
2486 FREE_UU(uu_end);
2487 send_end(sscop, 1, NULL);
2488 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2489 sscop_set_state(sscop, SSCOP_IDLE);
2490 } else {
2491 sscop->vt_cc++;
2492 send_rs(sscop, 1, sscop->uu_rs);
2493 TIMER_RESTART(sscop, cc);
2494 }
2495 }
2496
2497 /*
2498 * p 44: OUT_RESYNC && AA-RELEASE.request
2499 * arg is UU
2500 */
2501 static void
2502 sscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu)
2503 {
2504 SET_UU(uu_end, uu);
2505
2506 TIMER_STOP(sscop, cc);
2507 sscop->vt_cc = 1;
2508 send_end(sscop, 0, sscop->uu_end);
2509 TIMER_RESTART(sscop, cc);
2510 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2511 }
2512
2513 /*
2514 * p 45: OUT_RESYNC && RS PDU
2515 * arg is pdu (freed).
2516 */
2517 static void
2518 sscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg)
2519 {
2520 union pdu pdu;
2521
2522 pdu.sscop_null = MBUF_STRIP32(msg->m);
2523
2524 if(m_detect_retransmission(sscop, msg)) {
2525 SSCOP_MSG_FREE(msg);
2526 return;
2527 }
2528 (void)MBUF_STRIP32(msg->m);
2529
2530 TIMER_STOP(sscop, cc);
2531 sscop->vt_ms = pdu.sscop_ns;
2532 m_initialize_mr(sscop);
2533 send_rsak(sscop);
2534 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0);
2535 m_initialize_state(sscop);
2536 m_set_data_xfer_timers(sscop);
2537 sscop_set_state(sscop, SSCOP_READY);
2538 }
2539
2540 /*
2541 * p 45: OUT_RESYNC && RSAK PDU
2542 * arg is pdu (freed).
2543 */
2544 static void
2545 sscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg)
2546 {
2547 union pdu pdu;
2548
2549 pdu.sscop_null = MBUF_STRIP32(msg->m);
2550
2551 SSCOP_MSG_FREE(msg);
2552
2553 TIMER_STOP(sscop, cc);
2554 sscop->vt_ms = pdu.sscop_ns;
2555 AAL_SIG(sscop, SSCOP_RESYNC_confirm);
2556 m_initialize_state(sscop);
2557 m_set_data_xfer_timers(sscop);
2558 sscop_set_state(sscop, SSCOP_READY);
2559 }
2560
2561 /*
2562 * p 46: IN_RESYNC_PEND && AA-RESYNC.response
2563 */
2564 static void
2565 sscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused)
2566 {
2567 m_initialize_mr(sscop);
2568 send_rsak(sscop);
2569 m_clear_transmitter(sscop);
2570 m_initialize_state(sscop);
2571 m_set_data_xfer_timers(sscop);
2572 sscop_set_state(sscop, SSCOP_READY);
2573 }
2574
2575 /*
2576 * p 46: IN_RESYNC_PEND && AA-RELEASE.request
2577 * arg is uu
2578 */
2579 static void
2580 sscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu)
2581 {
2582 SET_UU(uu_end, uu);
2583
2584 sscop->vt_cc = 1;
2585 send_end(sscop, 0, sscop->uu_end);
2586 TIMER_RESTART(sscop, cc);
2587 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2588 }
2589
2590 /*
2591 * p 46: IN_RESYNC_PEND && ENDAK PDU
2592 * arg is pdu (freed).
2593 */
2594 static void
2595 sscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg)
2596 {
2597 SSCOP_MSG_FREE(msg);
2598 MAAL_ERROR(sscop, 'F', 0);
2599 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2600 sscop_set_state(sscop, SSCOP_IDLE);
2601 }
2602
2603 /*
2604 * p 46: IN_RESYNC_PEND && BGREJ PDU
2605 * arg is pdu (freed).
2606 */
2607 static void
2608 sscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2609 {
2610 SSCOP_MSG_FREE(msg);
2611 MAAL_ERROR(sscop, 'D', 0);
2612 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2613 sscop_set_state(sscop, SSCOP_IDLE);
2614 }
2615
2616 /*
2617 * p 46: IN_RESYNC_PEND && END PDU
2618 * arg is pdu (freed).
2619 */
2620 static void
2621 sscop_insync_end(struct sscop *sscop, struct sscop_msg *msg)
2622 {
2623 union pdu pdu;
2624
2625 pdu.sscop_null = MBUF_STRIP32(msg->m);
2626 (void)MBUF_STRIP32(msg->m);
2627
2628 send_endak(sscop);
2629 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2630 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2631 sscop_set_state(sscop, SSCOP_IDLE);
2632 }
2633
2634 /*
2635 * p 47: IN_RESYNC_PEND && ER PDU
2636 * arg is pdu (freed).
2637 */
2638 static void
2639 sscop_insync_er(struct sscop *sscop, struct sscop_msg *msg)
2640 {
2641 SSCOP_MSG_FREE(msg);
2642 MAAL_ERROR(sscop, 'L', 0);
2643 }
2644
2645 /*
2646 * p 47: IN_RESYNC_PEND && BGN PDU
2647 * arg is pdu (freed).
2648 */
2649 static void
2650 sscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg)
2651 {
2652 union pdu pdu;
2653
2654 pdu.sscop_null = MBUF_STRIP32(msg->m);
2655
2656 if(m_detect_retransmission(sscop, msg)) {
2657 MAAL_ERROR(sscop, 'B', 0);
2658 SSCOP_MSG_FREE(msg);
2659 return;
2660 }
2661 (void)MBUF_STRIP32(msg->m);
2662
2663 sscop->vt_ms = pdu.sscop_ns;
2664 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2665 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
2666
2667 sscop_set_state(sscop, SSCOP_IN_PEND);
2668 }
2669
2670 /*
2671 * p 47: IN_RESYNC_PEND && SD PDU
2672 * arg is pdu (freed).
2673 */
2674 static void
2675 sscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg)
2676 {
2677 SSCOP_MSG_FREE(msg);
2678 MAAL_ERROR(sscop, 'A', 0);
2679 FREE_UU(uu_end);
2680 send_end(sscop, 1, NULL);
2681 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2682 sscop_set_state(sscop, SSCOP_IDLE);
2683 }
2684
2685 /*
2686 * p 47: IN_RESYNC_PEND && POLL PDU
2687 * arg is pdu (freed).
2688 */
2689 static void
2690 sscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg)
2691 {
2692 SSCOP_MSG_FREE(msg);
2693 MAAL_ERROR(sscop, 'G', 0);
2694 FREE_UU(uu_end);
2695 send_end(sscop, 1, NULL);
2696 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2697 sscop_set_state(sscop, SSCOP_IDLE);
2698 }
2699
2700 /*
2701 * p 47: IN_RESYNC_PEND && STAT PDU
2702 * arg is pdu (freed).
2703 */
2704 static void
2705 sscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg)
2706 {
2707 SSCOP_MSG_FREE(msg);
2708 MAAL_ERROR(sscop, 'H', 0);
2709 FREE_UU(uu_end);
2710 send_end(sscop, 1, NULL);
2711 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2712 sscop_set_state(sscop, SSCOP_IDLE);
2713 }
2714
2715 /*
2716 * p 47: IN_RESYNC_PEND && USTAT PDU
2717 * arg is pdu (freed).
2718 */
2719 static void
2720 sscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg)
2721 {
2722 SSCOP_MSG_FREE(msg);
2723 MAAL_ERROR(sscop, 'I', 0);
2724 FREE_UU(uu_end);
2725 send_end(sscop, 1, NULL);
2726 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2727 sscop_set_state(sscop, SSCOP_IDLE);
2728 }
2729
2730 /*
2731 * p 48: IN_RESYNC_PEND && BGAK PDU
2732 * arg is pdu (freed).
2733 */
2734 static void
2735 sscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg)
2736 {
2737 MAAL_ERROR(sscop, 'C', 0);
2738 SSCOP_MSG_FREE(msg);
2739 }
2740
2741 /*
2742 * p 48: IN_RESYNC_PEND && ERAK PDU
2743 * arg is pdu (freed).
2744 */
2745 static void
2746 sscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg)
2747 {
2748 MAAL_ERROR(sscop, 'M', 0);
2749 SSCOP_MSG_FREE(msg);
2750 }
2751
2752 /*
2753 * p 48: IN_RESYNC_PEND && RS PDU
2754 * arg is pdu (freed).
2755 */
2756 static void
2757 sscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg)
2758 {
2759 union pdu pdu;
2760
2761 pdu.sscop_null = MBUF_STRIP32(msg->m);
2762
2763 if(m_detect_retransmission(sscop, msg)) {
2764 SSCOP_MSG_FREE(msg);
2765 return;
2766 }
2767 SSCOP_MSG_FREE(msg);
2768 MAAL_ERROR(sscop, 'J', 0);
2769 }
2770
2771 /*
2772 * p 48: IN_RESYNC_PEND && RSAK PDU
2773 * arg is pdu (freed).
2774 */
2775 static void
2776 sscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg)
2777 {
2778 MAAL_ERROR(sscop, 'K', 0);
2779 SSCOP_MSG_FREE(msg);
2780 }
2781
2782
2783 /*
2784 * p 49: OUT_REC_PEND && AA-DATA.request
2785 * arg is message (queued).
2786 */
2787 static void
2788 sscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg)
2789 {
2790 if(!sscop->clear_buffers) {
2791 MSGQ_APPEND(&sscop->xq, msg);
2792 sscop_signal(sscop, SIG_PDU_Q, msg);
2793 } else {
2794 SSCOP_MSG_FREE(msg);
2795 }
2796 }
2797
2798 /*
2799 * p 49: OUT_REC_PEND && BGAK PDU
2800 * arg is pdu (freed)
2801 */
2802 static void
2803 sscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
2804 {
2805 MAAL_ERROR(sscop, 'C', 0);
2806
2807 SSCOP_MSG_FREE(msg);
2808 }
2809
2810 /*
2811 * p 49: OUT_REC_PEND && ERAK PDU
2812 * arg is pdu (freed)
2813 */
2814 static void
2815 sscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg)
2816 {
2817 union pdu pdu;
2818
2819 pdu.sscop_null = MBUF_STRIP32(msg->m);
2820
2821 TIMER_STOP(sscop, cc);
2822 sscop->vt_ms = pdu.sscop_ns;
2823 m_deliver_data(sscop);
2824
2825 AAL_SIG(sscop, SSCOP_RECOVER_indication);
2826
2827 sscop_set_state(sscop, SSCOP_REC_PEND);
2828
2829 SSCOP_MSG_FREE(msg);
2830 }
2831
2832 /*
2833 * p 49: OUT_REC_PEND && END PDU
2834 * arg is pdu (freed)
2835 */
2836 static void
2837 sscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg)
2838 {
2839 union pdu pdu;
2840
2841 pdu.sscop_null = MBUF_STRIP32(msg->m);
2842 (void)MBUF_STRIP32(msg->m);
2843
2844 TIMER_STOP(sscop, cc);
2845 send_endak(sscop);
2846 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
2847 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
2848
2849 MSGQ_CLEAR(&sscop->rbuf);
2850
2851 sscop_set_state(sscop, SSCOP_IDLE);
2852 }
2853
2854 /*
2855 * p 49: OUT_REC_PEND && ENDAK PDU
2856 * arg is pdu (freed)
2857 */
2858 static void
2859 sscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg)
2860 {
2861 MAAL_ERROR(sscop, 'F', 0);
2862 TIMER_STOP(sscop, cc);
2863 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2864 MSGQ_CLEAR(&sscop->rbuf);
2865
2866 sscop_set_state(sscop, SSCOP_IDLE);
2867
2868 SSCOP_MSG_FREE(msg);
2869 }
2870
2871 /*
2872 * p 49: OUT_REC_PEND && BGREJ PDU
2873 * arg is pdu (freed)
2874 */
2875 static void
2876 sscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
2877 {
2878 MAAL_ERROR(sscop, 'D', 0);
2879 TIMER_STOP(sscop, cc);
2880 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2881 MSGQ_CLEAR(&sscop->rbuf);
2882
2883 sscop_set_state(sscop, SSCOP_IDLE);
2884
2885 SSCOP_MSG_FREE(msg);
2886 }
2887
2888 /*
2889 * p 50: OUT_REC_PEND && TIMER CC expiry
2890 * no arg.
2891 */
2892 static void
2893 sscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
2894 {
2895 if(sscop->vt_cc >= sscop->maxcc) {
2896 MAAL_ERROR(sscop, 'O', 0);
2897 FREE_UU(uu_end);
2898 send_end(sscop, 1, NULL);
2899 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
2900 MSGQ_CLEAR(&sscop->rbuf);
2901 sscop_set_state(sscop, SSCOP_IDLE);
2902 } else {
2903 sscop->vt_cc++;
2904 send_er(sscop);
2905 TIMER_RESTART(sscop, cc);
2906 }
2907 }
2908
2909 /*
2910 * p 50: OUT_REC_PEND && SSCOP_RELEASE_request
2911 * arg is UU
2912 */
2913 static void
2914 sscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
2915 {
2916 SET_UU(uu_end, uu);
2917
2918 TIMER_STOP(sscop, cc);
2919 sscop->vt_cc = 1;
2920 send_end(sscop, 0, sscop->uu_end);
2921 MSGQ_CLEAR(&sscop->rbuf);
2922 TIMER_RESTART(sscop, cc);
2923
2924 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
2925 }
2926
2927 /*
2928 * p 51: OUT_REC_PEND && AA-RESYNC.request
2929 * arg is uu
2930 */
2931 static void
2932 sscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
2933 {
2934 SET_UU(uu_rs, uu);
2935
2936 TIMER_STOP(sscop, cc);
2937 sscop->vt_cc = 1;
2938 sscop->vt_sq++;
2939 m_initialize_mr(sscop);
2940 send_rs(sscop, 0, sscop->uu_rs);
2941 m_clear_transmitter(sscop);
2942 MSGQ_CLEAR(&sscop->rbuf);
2943 TIMER_RESTART(sscop, cc);
2944 }
2945
2946 /*
2947 * p 51: OUT_REC_PEND && BGN PDU
2948 * arg is pdu (freed).
2949 * no uui
2950 */
2951 static void
2952 sscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
2953 {
2954 union pdu pdu;
2955
2956 pdu.sscop_null = MBUF_STRIP32(msg->m);
2957
2958 if(m_detect_retransmission(sscop, msg)) {
2959 MAAL_ERROR(sscop, 'B', 0);
2960 SSCOP_MSG_FREE(msg);
2961 } else {
2962 (void)MBUF_STRIP32(msg->m);
2963
2964 TIMER_STOP(sscop, cc);
2965 sscop->vt_ms = pdu.sscop_ns;
2966 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
2967 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
2968 msg, pdu.sscop_pl, 0);
2969 MSGQ_CLEAR(&sscop->rbuf);
2970
2971 sscop_set_state(sscop, SSCOP_IN_PEND);
2972 }
2973 }
2974
2975 /*
2976 * p 51: OUT_REC_PEND && ER PDU
2977 * arg is pdu (freed).
2978 */
2979 static void
2980 sscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg)
2981 {
2982 union pdu pdu;
2983
2984 pdu.sscop_null = MBUF_STRIP32(msg->m);
2985
2986 if(m_detect_retransmission(sscop, msg)) {
2987 MAAL_ERROR(sscop, 'L', 0);
2988 } else {
2989 TIMER_STOP(sscop, cc);
2990 sscop->vt_ms = pdu.sscop_ns;
2991 m_initialize_mr(sscop);
2992 send_erak(sscop);
2993 m_deliver_data(sscop);
2994
2995 AAL_SIG(sscop, SSCOP_RECOVER_indication);
2996
2997 sscop_set_state(sscop, SSCOP_REC_PEND);
2998 }
2999
3000 SSCOP_MSG_FREE(msg);
3001 }
3002
3003 /*
3004 * p 52: OUT_REC_PEND && SD PDU queued
3005 * no arg.
3006 */
3007 static void
3008 sscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3009 {
3010 sscop_save_signal(sscop, SIG_PDU_Q, msg);
3011 }
3012
3013 /*
3014 * p 52: OUT_REC_PEND && RSAK PDU
3015 * arg is pdu (freed).
3016 */
3017 static void
3018 sscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3019 {
3020 SSCOP_MSG_FREE(msg);
3021 MAAL_ERROR(sscop, 'K', 0);
3022 }
3023
3024 /*
3025 * p 52: OUT_REC_PEND && RS PDU
3026 * arg is pdu (freed).
3027 */
3028 static void
3029 sscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg)
3030 {
3031 union pdu pdu;
3032
3033 pdu.sscop_null = MBUF_STRIP32(msg->m);
3034
3035 if(m_detect_retransmission(sscop, msg)) {
3036 SSCOP_MSG_FREE(msg);
3037 MAAL_ERROR(sscop, 'J', 0);
3038 return;
3039 }
3040 (void)MBUF_STRIP32(msg->m);
3041
3042 TIMER_STOP(sscop, cc);
3043 sscop->vt_ms = pdu.sscop_ns;
3044 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3045 MSGQ_CLEAR(&sscop->rbuf);
3046 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3047 }
3048
3049 /*
3050 * p 53: REC_PEND && BGAK PDU
3051 * arg is pdu (freed)
3052 */
3053 static void
3054 sscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg)
3055 {
3056 MAAL_ERROR(sscop, 'C', 0);
3057
3058 SSCOP_MSG_FREE(msg);
3059 }
3060
3061 /*
3062 * p 53: REC_PEND && END PDU
3063 * arg is pdu (freed)
3064 * no uui
3065 */
3066 static void
3067 sscop_rec_end(struct sscop *sscop, struct sscop_msg *msg)
3068 {
3069 union pdu pdu;
3070
3071 pdu.sscop_null = MBUF_STRIP32(msg->m);
3072 (void)MBUF_STRIP32(msg->m);
3073
3074 send_endak(sscop);
3075 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3076 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3077
3078 sscop_set_state(sscop, SSCOP_IDLE);
3079 }
3080
3081 /*
3082 * p 53: REC_PEND && ENDAK PDU
3083 * arg is pdu (freed)
3084 */
3085 static void
3086 sscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg)
3087 {
3088 MAAL_ERROR(sscop, 'F', 0);
3089 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3090 sscop_set_state(sscop, SSCOP_IDLE);
3091 SSCOP_MSG_FREE(msg);
3092 }
3093
3094 /*
3095 * p 53: REC_PEND && BGREJ PDU
3096 * arg is pdu (freed)
3097 */
3098 static void
3099 sscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3100 {
3101 MAAL_ERROR(sscop, 'D', 0);
3102 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3103 sscop_set_state(sscop, SSCOP_IDLE);
3104 SSCOP_MSG_FREE(msg);
3105 }
3106
3107 /*
3108 * p 54: REC_PEND && RELEASE
3109 * arg is UU
3110 */
3111 static void
3112 sscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu)
3113 {
3114 SET_UU(uu_end, uu);
3115
3116 sscop->vt_cc = 1;
3117 send_end(sscop, 0, sscop->uu_end);
3118 TIMER_RESTART(sscop, cc);
3119
3120 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3121 }
3122
3123 /*
3124 * p 54: REC_PEND && RSAK PDU
3125 * arg is pdu (freed).
3126 */
3127 static void
3128 sscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3129 {
3130 MAAL_ERROR(sscop, 'K', 0);
3131 SSCOP_MSG_FREE(msg);
3132 }
3133
3134
3135 /*
3136 * p 54: REC_PEND && RS PDU
3137 * arg is pdu (freed).
3138 */
3139 static void
3140 sscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg)
3141 {
3142 union pdu pdu;
3143
3144 pdu.sscop_null = MBUF_STRIP32(msg->m);
3145
3146 if(m_detect_retransmission(sscop, msg)) {
3147 SSCOP_MSG_FREE(msg);
3148 MAAL_ERROR(sscop, 'J', 0);
3149 return;
3150 }
3151 (void)MBUF_STRIP32(msg->m);
3152
3153 sscop->vt_ms = pdu.sscop_ns;
3154 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3155
3156 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3157 }
3158
3159 /*
3160 * p 54: REC_PEND && RECOVER response
3161 * no arg
3162 */
3163 static void
3164 sscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
3165 {
3166 if(!sscop->clear_buffers) {
3167 MSGQ_CLEAR(&sscop->xbuf);
3168 }
3169 m_initialize_state(sscop);
3170 m_set_data_xfer_timers(sscop);
3171
3172 sscop_set_state(sscop, SSCOP_READY);
3173 }
3174
3175 /*
3176 * p 54: REC_PEND && RESYNC request
3177 * arg is uu
3178 */
3179 static void
3180 sscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3181 {
3182 SET_UU(uu_rs, uu);
3183
3184 m_clear_transmitter(sscop);
3185 sscop->vt_cc = 1;
3186 sscop->vt_sq++;
3187 m_initialize_mr(sscop);
3188 send_rs(sscop, 0, sscop->uu_rs);
3189 TIMER_RESTART(sscop, cc);
3190
3191 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3192 }
3193
3194 /*
3195 * p 55: REC_PEND && SD PDU queued
3196 * no arg
3197 */
3198 static void
3199 sscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3200 {
3201 sscop_save_signal(sscop, SIG_PDU_Q, msg);
3202 }
3203
3204 /*
3205 * p 55: REC_PEND && ER PDU
3206 * arg is pdu (freed).
3207 */
3208 static void
3209 sscop_rec_er(struct sscop *sscop, struct sscop_msg *msg)
3210 {
3211 union pdu pdu;
3212
3213 pdu.sscop_null = MBUF_STRIP32(msg->m);
3214
3215 if(m_detect_retransmission(sscop, msg)) {
3216 send_erak(sscop);
3217 } else {
3218 MAAL_ERROR(sscop, 'L', 0);
3219 }
3220 SSCOP_MSG_FREE(msg);
3221 }
3222
3223 /*
3224 * p 55: REC_PEND && BGN PDU
3225 * arg is pdu (freed)
3226 * no uui
3227 */
3228 static void
3229 sscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg)
3230 {
3231 union pdu pdu;
3232
3233 pdu.sscop_null = MBUF_STRIP32(msg->m);
3234
3235 if(m_detect_retransmission(sscop, msg)) {
3236 MAAL_ERROR(sscop, 'B', 0);
3237 SSCOP_MSG_FREE(msg);
3238 return;
3239 }
3240 (void)MBUF_STRIP32(msg->m);
3241
3242 sscop->vt_ms = pdu.sscop_ns;
3243 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3244 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3245
3246 sscop_set_state(sscop, SSCOP_IN_PEND);
3247 }
3248
3249 /*
3250 * p 55: REC_PEND && STAT PDU
3251 * arg is pdu (freed)
3252 */
3253 static void
3254 sscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg)
3255 {
3256 MAAL_ERROR(sscop, 'H', 0);
3257 FREE_UU(uu_end);
3258 send_end(sscop, 1, NULL);
3259 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3260 sscop_set_state(sscop, SSCOP_IDLE);
3261 SSCOP_MSG_FREE(msg);
3262 }
3263
3264 /*
3265 * p 55: REC_PEND && USTAT PDU
3266 * arg is pdu (freed)
3267 */
3268 static void
3269 sscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg)
3270 {
3271 MAAL_ERROR(sscop, 'I', 0);
3272 FREE_UU(uu_end);
3273 send_end(sscop, 1, NULL);
3274 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3275 sscop_set_state(sscop, SSCOP_IDLE);
3276 SSCOP_MSG_FREE(msg);
3277 }
3278
3279 /*
3280 * p 56: IN_REC_PEND && AA-RECOVER.response
3281 * no arg
3282 */
3283 static void
3284 sscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
3285 {
3286 if(!sscop->clear_buffers) {
3287 MSGQ_CLEAR(&sscop->xbuf);
3288 }
3289 m_initialize_mr(sscop);
3290 send_erak(sscop);
3291 m_initialize_state(sscop);
3292 m_set_data_xfer_timers(sscop);
3293
3294 sscop_set_state(sscop, SSCOP_READY);
3295 }
3296
3297 /*
3298 * p 56: IN_REC_PEND && SD PDU queued
3299 * no arg
3300 */
3301 static void
3302 sscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
3303 {
3304 sscop_save_signal(sscop, SIG_PDU_Q, msg);
3305 }
3306
3307 /*
3308 * p 56: IN_REC_PEND && AA-RELEASE.request
3309 * arg is UU
3310 */
3311 static void
3312 sscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
3313 {
3314 SET_UU(uu_end, uu);
3315
3316 sscop->vt_cc = 1;
3317 send_end(sscop, 0, sscop->uu_end);
3318 TIMER_RESTART(sscop, cc);
3319
3320 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3321 }
3322
3323 /*
3324 * p 56: IN_REC_PEND && END PDU
3325 * arg is pdu (freed).
3326 * no uui
3327 */
3328 static void
3329 sscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg)
3330 {
3331 union pdu pdu;
3332
3333 pdu.sscop_null = MBUF_STRIP32(msg->m);
3334 (void)MBUF_STRIP32(msg->m);
3335
3336 send_endak(sscop);
3337 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3338 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3339
3340 sscop_set_state(sscop, SSCOP_IDLE);
3341 }
3342
3343 /*
3344 * p 56: IN_REC_PEND && RESYNC_REQ
3345 */
3346 static void
3347 sscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3348 {
3349 SET_UU(uu_rs, uu);
3350
3351 m_clear_transmitter(sscop);
3352 sscop->vt_cc = 1;
3353 sscop->vt_sq++;
3354 m_initialize_mr(sscop);
3355 send_rs(sscop, 0, sscop->uu_rs);
3356 TIMER_RESTART(sscop, cc);
3357
3358 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3359 }
3360
3361
3362 /*
3363 * p 57: IN_REC_PEND && ENDAK PDU
3364 * arg is pdu (freed)
3365 */
3366 static void
3367 sscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg)
3368 {
3369 MAAL_ERROR(sscop, 'F', 0);
3370 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3371 SSCOP_MSG_FREE(msg);
3372 sscop_set_state(sscop, SSCOP_IDLE);
3373 }
3374
3375 /*
3376 * p 57: IN_REC_PEND && BGREJ PDU
3377 * arg is pdu (freed)
3378 */
3379 static void
3380 sscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3381 {
3382 MAAL_ERROR(sscop, 'D', 0);
3383 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3384 SSCOP_MSG_FREE(msg);
3385 sscop_set_state(sscop, SSCOP_IDLE);
3386 }
3387
3388 /*
3389 * p 57: IN_REC_PEND && USTAT PDU
3390 * arg is pdu (freed)
3391 */
3392 static void
3393 sscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg)
3394 {
3395 MAAL_ERROR(sscop, 'I', 0);
3396 FREE_UU(uu_end);
3397 send_end(sscop, 1, NULL);
3398 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3399 SSCOP_MSG_FREE(msg);
3400 sscop_set_state(sscop, SSCOP_IDLE);
3401 }
3402
3403 /*
3404 * p 57: IN_REC_PEND && STAT PDU
3405 * arg is pdu (freed)
3406 */
3407 static void
3408 sscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg)
3409 {
3410 MAAL_ERROR(sscop, 'H', 0);
3411 FREE_UU(uu_end);
3412 send_end(sscop, 1, NULL);
3413 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3414 SSCOP_MSG_FREE(msg);
3415 sscop_set_state(sscop, SSCOP_IDLE);
3416 }
3417
3418 /*
3419 * p 57: IN_REC_PEND && POLL PDU
3420 * arg is pdu (freed)
3421 */
3422 static void
3423 sscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg)
3424 {
3425 MAAL_ERROR(sscop, 'G', 0);
3426 FREE_UU(uu_end);
3427 send_end(sscop, 1, NULL);
3428 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3429 SSCOP_MSG_FREE(msg);
3430 sscop_set_state(sscop, SSCOP_IDLE);
3431 }
3432
3433 /*
3434 * p 57: IN_REC_PEND && SD PDU
3435 * arg is pdu (freed)
3436 */
3437 static void
3438 sscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg)
3439 {
3440 MAAL_ERROR(sscop, 'A', 0);
3441 FREE_UU(uu_end);
3442 send_end(sscop, 1, NULL);
3443 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3444 SSCOP_MSG_FREE(msg);
3445 sscop_set_state(sscop, SSCOP_IDLE);
3446 }
3447
3448 /*
3449 * p 58: IN_REC_PEND && RSAK PDU
3450 * arg is pdu (freed).
3451 */
3452 static void
3453 sscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
3454 {
3455 SSCOP_MSG_FREE(msg);
3456 MAAL_ERROR(sscop, 'K', 0);
3457 }
3458
3459 /*
3460 * p 58: IN_REC_PEND && RS PDU
3461 * arg is pdu (freed).
3462 */
3463 static void
3464 sscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg)
3465 {
3466 union pdu pdu;
3467
3468 pdu.sscop_null = MBUF_STRIP32(msg->m);
3469
3470 if(m_detect_retransmission(sscop, msg)) {
3471 SSCOP_MSG_FREE(msg);
3472 MAAL_ERROR(sscop, 'J', 0);
3473 return;
3474 }
3475 (void)MBUF_STRIP32(msg->m);
3476
3477 sscop->vt_ms = pdu.sscop_ns;
3478 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3479
3480 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3481 }
3482
3483 /*
3484 * p 59: IN_REC_PEND && ER PDU
3485 * arg is pdu (freed)
3486 */
3487 static void
3488 sscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg)
3489 {
3490 union pdu pdu;
3491
3492 pdu.sscop_null = MBUF_STRIP32(msg->m);
3493
3494 if(!m_detect_retransmission(sscop, msg)) {
3495 MAAL_ERROR(sscop, 'L', 0);
3496 }
3497
3498 SSCOP_MSG_FREE(msg);
3499 }
3500
3501 /*
3502 * p 59: IN_REC_PEND && BGN PDU
3503 * arg is pdu (freed).
3504 * no uui
3505 */
3506 static void
3507 sscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
3508 {
3509 union pdu pdu;
3510
3511 pdu.sscop_null = MBUF_STRIP32(msg->m);
3512
3513 if(m_detect_retransmission(sscop, msg)) {
3514 MAAL_ERROR(sscop, 'B', 0);
3515 SSCOP_MSG_FREE(msg);
3516 return;
3517 }
3518 (void)MBUF_STRIP32(msg->m);
3519
3520 sscop->vt_ms = pdu.sscop_ns;
3521 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3522 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3523
3524 sscop_set_state(sscop, SSCOP_IN_PEND);
3525 }
3526
3527 /*
3528 * p 59: IN_REC_PEND && BGAK PDU
3529 * arg is pdu (freed)
3530 * no uui
3531 */
3532 static void
3533 sscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
3534 {
3535 MAAL_ERROR(sscop, 'C', 0);
3536 SSCOP_MSG_FREE(msg);
3537 }
3538
3539 /*
3540 * p 59: IN_REC_PEND && ERAK PDU
3541 * arg is pdu (freed)
3542 * no uui
3543 */
3544 static void
3545 sscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg)
3546 {
3547 MAAL_ERROR(sscop, 'M', 0);
3548 SSCOP_MSG_FREE(msg);
3549 }
3550
3551 /*
3552 * p 60: READY && RESYNC request
3553 * arg is UU
3554 */
3555 static void
3556 sscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu)
3557 {
3558 SET_UU(uu_rs, uu);
3559
3560 m_reset_data_xfer_timers(sscop);
3561 sscop->vt_cc = 1;
3562 sscop->vt_sq++;
3563 m_initialize_mr(sscop);
3564 send_rs(sscop, 0, sscop->uu_rs);
3565 m_release_buffers(sscop);
3566 TIMER_RESTART(sscop, cc);
3567
3568 sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
3569 }
3570
3571
3572 /*
3573 * p 60: READY && AA-RELEASE.request
3574 * arg is uu.
3575 */
3576 static void
3577 sscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu)
3578 {
3579 SET_UU(uu_end, uu);
3580
3581 m_reset_data_xfer_timers(sscop);
3582 sscop->vt_cc = 1;
3583 send_end(sscop, 0, sscop->uu_end);
3584 m_prepare_retrieval(sscop);
3585 TIMER_RESTART(sscop, cc);
3586
3587 sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
3588 }
3589
3590 /*
3591 * p 61: READY && ER PDU
3592 * arg is pdu (freed).
3593 */
3594 static void
3595 sscop_ready_er(struct sscop *sscop, struct sscop_msg *msg)
3596 {
3597 union pdu pdu;
3598
3599 pdu.sscop_null = MBUF_STRIP32(msg->m);
3600
3601 if(m_detect_retransmission(sscop, msg)) {
3602 TIMER_RESTART(sscop, nr);
3603 send_erak(sscop);
3604 } else {
3605 m_reset_data_xfer_timers(sscop);
3606 sscop->vt_ms = pdu.sscop_ns;
3607 m_prepare_recovery(sscop);
3608 m_deliver_data(sscop);
3609
3610 AAL_SIG(sscop, SSCOP_RECOVER_indication);
3611
3612 sscop_set_state(sscop, SSCOP_IN_REC_PEND);
3613 }
3614
3615 SSCOP_MSG_FREE(msg);
3616 }
3617
3618 /*
3619 * p 61: READY && BGN PDU
3620 * arg is pdu (freed)
3621 */
3622 static void
3623 sscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg)
3624 {
3625 union pdu pdu;
3626
3627 pdu.sscop_null = MBUF_STRIP32(msg->m);
3628
3629 if(m_detect_retransmission(sscop, msg)) {
3630 TIMER_RESTART(sscop, nr);
3631 send_bgak(sscop, sscop->uu_bgak);
3632 SSCOP_MSG_FREE(msg);
3633 return;
3634 }
3635 (void)MBUF_STRIP32(msg->m);
3636
3637 m_reset_data_xfer_timers(sscop);
3638 sscop->vt_ms = pdu.sscop_ns;
3639
3640 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
3641 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
3642
3643 m_prepare_retrieval(sscop);
3644
3645 sscop_set_state(sscop, SSCOP_IN_PEND);
3646 }
3647
3648 /*
3649 * p 62: READY && ENDAK PDU
3650 * arg is pdu (freed)
3651 */
3652 static void
3653 sscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg)
3654 {
3655 m_reset_data_xfer_timers(sscop);
3656 MAAL_ERROR(sscop, 'F', 0);
3657 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3658 m_prepare_retrieval(sscop);
3659 SSCOP_MSG_FREE(msg);
3660 sscop_set_state(sscop, SSCOP_IDLE);
3661 }
3662
3663 /*
3664 * p 62: READY && BGREJ PDU
3665 * arg is pdu (freed)
3666 */
3667 static void
3668 sscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg)
3669 {
3670 m_reset_data_xfer_timers(sscop);
3671 MAAL_ERROR(sscop, 'D', 0);
3672 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3673 m_prepare_retrieval(sscop);
3674 SSCOP_MSG_FREE(msg);
3675 sscop_set_state(sscop, SSCOP_IDLE);
3676 }
3677
3678 /*
3679 * p 62: READY && RS PDU
3680 * arg is pdu (freed)
3681 */
3682 static void
3683 sscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg)
3684 {
3685 union pdu pdu;
3686
3687 pdu.sscop_null = MBUF_STRIP32(msg->m);
3688
3689 if(m_detect_retransmission(sscop, msg)) {
3690 SSCOP_MSG_FREE(msg);
3691 TIMER_RESTART(sscop, nr);
3692 send_rsak(sscop);
3693 return;
3694 }
3695 (void)MBUF_STRIP32(msg->m);
3696
3697 m_reset_data_xfer_timers(sscop);
3698 sscop->vt_ms = pdu.sscop_ns;
3699 AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
3700 m_prepare_retrieval(sscop);
3701
3702 sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
3703 }
3704
3705 /*
3706 * p 62: READY && END PDU
3707 * arg is pdu (freed)
3708 */
3709 static void
3710 sscop_ready_end(struct sscop *sscop, struct sscop_msg *msg)
3711 {
3712 union pdu pdu;
3713
3714 pdu.sscop_null = MBUF_STRIP32(msg->m);
3715 (void)MBUF_STRIP32(msg->m);
3716
3717 m_reset_data_xfer_timers(sscop);
3718 send_endak(sscop);
3719 AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
3720 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
3721 m_prepare_retrieval(sscop);
3722
3723 sscop_set_state(sscop, SSCOP_IDLE);
3724 }
3725
3726 /*
3727 * p 63: READY && POLL expiry
3728 */
3729 static void
3730 sscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused)
3731 {
3732 sscop->vt_ps++;
3733 send_poll(sscop);
3734 sscop->vt_pd = 0;
3735 m_set_poll_timer(sscop);
3736 }
3737
3738 /*
3739 * p 63: READY && KEEP_ALIVE expiry
3740 */
3741 static void
3742 sscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused)
3743 {
3744 sscop->vt_ps++;
3745 send_poll(sscop);
3746 sscop->vt_pd = 0;
3747 m_set_poll_timer(sscop);
3748 }
3749
3750 /*
3751 * p 63: READY && IDLE expiry
3752 */
3753 static void
3754 sscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused)
3755 {
3756 TIMER_RESTART(sscop, nr);
3757 sscop->vt_ps++;
3758 send_poll(sscop);
3759 sscop->vt_pd = 0;
3760 m_set_poll_timer(sscop);
3761 }
3762
3763 /*
3764 * p 63: READY && NO_RESPONSE expiry
3765 * no arg
3766 */
3767 static void
3768 sscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused)
3769 {
3770 m_reset_data_xfer_timers(sscop);
3771 MAAL_ERROR(sscop, 'P', 0);
3772 FREE_UU(uu_end);
3773 send_end(sscop, 1, NULL);
3774 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
3775 m_prepare_retrieval(sscop);
3776 sscop_set_state(sscop, SSCOP_IDLE);
3777 }
3778
3779 /*
3780 * p 63: READY && AA-DATA.request
3781 * arg is message (queued).
3782 */
3783 static void
3784 sscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg)
3785 {
3786 MSGQ_APPEND(&sscop->xq, msg);
3787
3788 sscop_signal(sscop, SIG_PDU_Q, msg);
3789 }
3790
3791 /*
3792 * p 64: READY && SD PDU queued up
3793 * arg is unused.
3794 */
3795 static void
3796 sscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused)
3797 {
3798 struct sscop_msg *msg;
3799
3800 if(sscop->rxq != 0) {
3801 TAILQ_FOREACH(msg, &sscop->xbuf, link)
3802 if(msg->rexmit)
3803 break;
3804 ASSERT(msg != NULL);
3805 msg->rexmit = 0;
3806 sscop->rxq--;
3807 send_sd(sscop, msg->m, msg->seqno);
3808 msg->poll_seqno = sscop->vt_ps;
3809 if(sscop->poll_after_rex && sscop->rxq == 0)
3810 goto poll; /* -> A */
3811 else
3812 goto maybe_poll; /* -> B */
3813
3814 }
3815 if(MSGQ_EMPTY(&sscop->xq))
3816 return;
3817
3818 if(sscop->vt_s >= sscop->vt_ms) {
3819 /* Send windows closed */
3820 TIMER_STOP(sscop, idle);
3821 TIMER_RESTART(sscop, nr);
3822 goto poll; /* -> A */
3823
3824 } else {
3825 msg = MSGQ_GET(&sscop->xq);
3826 msg->seqno = sscop->vt_s;
3827 send_sd(sscop, msg->m, msg->seqno);
3828 msg->poll_seqno = sscop->vt_ps;
3829 sscop->vt_s++;
3830 MSGQ_APPEND(&sscop->xbuf, msg);
3831 goto maybe_poll; /* -> B */
3832 }
3833
3834 /*
3835 * p 65: Poll handling
3836 */
3837 maybe_poll: /* label B */
3838 sscop->vt_pd++;
3839 if(TIMER_ISACT(sscop, poll)) {
3840 if(sscop->vt_pd < sscop->maxpd)
3841 return;
3842 } else {
3843 if(TIMER_ISACT(sscop, idle)) {
3844 TIMER_STOP(sscop, idle);
3845 TIMER_RESTART(sscop, nr);
3846 } else {
3847 TIMER_STOP(sscop, ka);
3848 }
3849 if(sscop->vt_pd < sscop->maxpd) {
3850 TIMER_RESTART(sscop, poll);
3851 return;
3852 }
3853 }
3854 poll: /* label A */
3855 sscop->vt_ps++;
3856 send_poll(sscop);
3857 sscop->vt_pd = 0;
3858 TIMER_RESTART(sscop, poll);
3859 }
3860
3861 /*
3862 * p 67: common recovery start
3863 */
3864 static void
3865 sscop_recover(struct sscop *sscop)
3866 {
3867 sscop->vt_cc = 1;
3868 sscop->vt_sq++;
3869
3870 m_initialize_mr(sscop);
3871 send_er(sscop);
3872 m_prepare_recovery(sscop);
3873
3874 TIMER_RESTART(sscop, cc);
3875
3876 sscop_set_state(sscop, SSCOP_OUT_REC_PEND);
3877 }
3878
3879 /*
3880 * p 66: READY && SD PDU
3881 * arg is received message.
3882 */
3883 static void
3884 sscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg)
3885 {
3886 union pdu pdu;
3887 u_int sn;
3888
3889 pdu.sscop_null = MBUF_STRIP32(msg->m);
3890 msg->seqno = pdu.sscop_ns;
3891
3892 /* Fix padding */
3893 MBUF_UNPAD(msg->m, pdu.sscop_pl);
3894
3895 if(msg->seqno >= sscop->vr_mr) {
3896 /* message outside window */
3897 if(sscop->vr_h < sscop->vr_mr) {
3898 send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1);
3899 sscop->vr_h = sscop->vr_mr;
3900 }
3901 SSCOP_MSG_FREE(msg);
3902 return;
3903 }
3904
3905 if(msg->seqno == sscop->vr_r) {
3906 if(msg->seqno == sscop->vr_h) {
3907 sscop->vr_r = msg->seqno + 1;
3908 sscop->vr_h = msg->seqno + 1;
3909
3910 AAL_DATA(sscop, SSCOP_DATA_indication,
3911 msg->m, msg->seqno);
3912 msg->m = NULL;
3913 SSCOP_MSG_FREE(msg);
3914
3915 return;
3916 }
3917 for(;;) {
3918 AAL_DATA(sscop, SSCOP_DATA_indication,
3919 msg->m, msg->seqno);
3920 msg->m = NULL;
3921 SSCOP_MSG_FREE(msg);
3922
3923 sscop->vr_r++;
3924 if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL)
3925 break;
3926 sn = msg->seqno;
3927 ASSERT(sn >= sscop->vr_r);
3928 if(sn != sscop->vr_r)
3929 break;
3930 msg = MSGQ_GET(&sscop->rbuf);
3931 }
3932 return;
3933 }
3934
3935 /* Messages were lost */
3936
3937 /* XXX Flow control */
3938 if(msg->seqno == sscop->vr_h) {
3939 QINSERT(&sscop->rbuf, msg);
3940 sscop->vr_h++;
3941 return;
3942 }
3943 if(sscop->vr_h < msg->seqno) {
3944 QINSERT(&sscop->rbuf, msg);
3945 send_ustat(sscop, sscop->vr_h, msg->seqno, -1);
3946 sscop->vr_h = msg->seqno + 1;
3947 return;
3948 }
3949
3950 if(QFIND(&sscop->rbuf, msg->seqno) == NULL) {
3951 QINSERT(&sscop->rbuf, msg);
3952 return;
3953 }
3954
3955 /* error: start recovery */
3956 SSCOP_MSG_FREE(msg);
3957 m_reset_data_xfer_timers(sscop);
3958 MAAL_ERROR(sscop, 'Q', 0);
3959 sscop_recover(sscop);
3960 }
3961
3962 /*
3963 * p 67: READY && POLL PDU
3964 */
3965 static void
3966 sscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg)
3967 {
3968 union pdu pdu;
3969 union seqno seqno;
3970 u_int sn, nps;
3971 struct SSCOP_MBUF_T *m;
3972
3973 pdu.sscop_null = MBUF_STRIP32(msg->m);
3974 seqno.sscop_null = MBUF_STRIP32(msg->m);
3975
3976 if((u_int)pdu.sscop_ns < sscop->vr_h) {
3977 SSCOP_MSG_FREE(msg);
3978 m_reset_data_xfer_timers(sscop);
3979 MAAL_ERROR(sscop, 'Q', 0);
3980 sscop_recover(sscop);
3981 return;
3982 }
3983 nps = seqno.sscop_n;
3984
3985 if((u_int)pdu.sscop_ns > sscop->vr_mr)
3986 sscop->vr_h = sscop->vr_mr;
3987 else
3988 sscop->vr_h = pdu.sscop_ns;
3989
3990 SSCOP_MSG_FREE(msg);
3991
3992 /* build stat pdu */
3993 if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
3994 FAILURE("sscop: cannot allocate STAT");
3995 return;
3996 }
3997 sn = sscop->vr_r;
3998
3999 while(sn != sscop->vr_h) {
4000 /* loop through burst we already have */
4001 for(;;) {
4002 if(sn >= sscop->vr_h) {
4003 seqno.sscop_null = 0;
4004 seqno.sscop_n = sn;
4005 MBUF_APPEND32(m, seqno.sscop_null);
4006 goto out;
4007 }
4008 if(QFIND(&sscop->rbuf, sn) == NULL)
4009 break;
4010 sn++;
4011 }
4012
4013 /* start of a hole */
4014 seqno.sscop_null = 0;
4015 seqno.sscop_n = sn;
4016 MBUF_APPEND32(m, seqno.sscop_null);
4017 if(MBUF_LEN(m)/4 >= sscop->maxstat) {
4018 send_stat(sscop, nps, m);
4019 if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
4020 FAILURE("sscop: cannot allocate STAT");
4021 return;
4022 }
4023 seqno.sscop_null = 0;
4024 seqno.sscop_n = sn;
4025 MBUF_APPEND32(m, seqno.sscop_null);
4026 }
4027 do {
4028 sn++;
4029 } while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn));
4030 seqno.sscop_null = 0;
4031 seqno.sscop_n = sn;
4032 MBUF_APPEND32(m, seqno.sscop_null);
4033 }
4034 out:
4035 send_stat(sscop, nps, m);
4036 }
4037
4038 /*
4039 * p 69: READY && USTAT PDU
4040 * arg is msg (freed)
4041 */
4042 static void
4043 sscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg)
4044 {
4045 union pdu pdu;
4046 union seqno nmr, sq1, sq2;
4047 u_int cnt;
4048
4049 pdu.sscop_null = MBUF_STRIP32(msg->m);
4050 nmr.sscop_null = MBUF_STRIP32(msg->m);
4051 sq2.sscop_null = MBUF_STRIP32(msg->m);
4052 sq1.sscop_null = MBUF_STRIP32(msg->m);
4053
4054 SSCOP_MSG_FREE(msg);
4055
4056 cnt = sq1.sscop_n - sq2.sscop_n;
4057
4058 if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) {
4059 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4060 "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
4061 "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
4062 goto err_f;
4063 }
4064
4065 /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
4066 * next in sequence-SD-number of the receiver and means, it has all
4067 * messages below N(R). Remove all message below N(R) from the
4068 * transmission buffer. It may already be removed because of an
4069 * earlier selective ACK in a STAT message.
4070 */
4071 while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) {
4072 ASSERT(msg->seqno >= sscop->vt_a);
4073 MSGQ_REMOVE(&sscop->xbuf, msg);
4074 SSCOP_MSG_FREE(msg);
4075 }
4076
4077 /* Update the in-sequence acknowledge and the send window */
4078 sscop->vt_a = pdu.sscop_ns;
4079 sscop->vt_ms = nmr.sscop_n;
4080
4081 /* check, that the range of requested re-transmissions is between
4082 * the in-sequence-ack and the highest up-to-now transmitted SD
4083 */
4084 if(sq1.sscop_n >= sq2.sscop_n
4085 || (u_int)sq1.sscop_n < sscop->vt_a
4086 || (u_int)sq2.sscop_n >= sscop->vt_s) {
4087 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4088 "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:"
4089 " seq1=%u seq2=%u VT(A)=%u VT(S)=%u",
4090 sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s));
4091 goto err_f;
4092 }
4093
4094 /*
4095 * Retransmit all messages from seq1 to seq2-1
4096 */
4097 do {
4098 /*
4099 * The message may not be in the transmit buffer if it was
4100 * already acked by a STAT. This means, the receiver is
4101 * confused.
4102 */
4103 if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) {
4104 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4105 "USTAT: message %u not found in xmit buffer",
4106 sq1.sscop_n));
4107 goto err_f;
4108 }
4109
4110 /*
4111 * If it is not yet in the re-transmission queue, put it there
4112 */
4113 if(!msg->rexmit) {
4114 msg->rexmit = 1;
4115 sscop->rxq++;
4116 sscop_signal(sscop, SIG_PDU_Q, msg);
4117 }
4118 sq1.sscop_n++;
4119 } while(sq1.sscop_n != sq2.sscop_n);
4120
4121 /*
4122 * report the re-transmission to the management
4123 */
4124 MAAL_ERROR(sscop, 'V', cnt);
4125 return;
4126
4127 err_f:
4128 m_reset_data_xfer_timers(sscop);
4129 MAAL_ERROR(sscop, 'T', 0);
4130 sscop_recover(sscop);
4131 }
4132
4133 /*
4134 * p 70: READY && STAT PDU
4135 * arg is msg (freed).
4136 */
4137 static void
4138 sscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg)
4139 {
4140 union pdu pdu;
4141 union seqno nps, nmr;
4142 u_int len, seq1, seq2, cnt;
4143 struct sscop_msg *m;
4144
4145 pdu.sscop_null = MBUF_STRIP32(msg->m);
4146 nmr.sscop_null = MBUF_STRIP32(msg->m);
4147 nps.sscop_null = MBUF_STRIP32(msg->m);
4148
4149 len = MBUF_LEN(msg->m) / 4;
4150
4151 if((u_int)nps.sscop_n < sscop->vt_pa
4152 || (u_int)nps.sscop_n > sscop->vt_ps) {
4153 SSCOP_MSG_FREE(msg);
4154 m_reset_data_xfer_timers(sscop);
4155 MAAL_ERROR(sscop, 'R', 0);
4156 sscop_recover(sscop);
4157 return;
4158 }
4159
4160 if((u_int)pdu.sscop_ns < sscop->vt_a
4161 || (u_int)pdu.sscop_ns > sscop->vt_s) {
4162 /*
4163 * The in-sequence acknowledge, i.e. the receivers's next
4164 * expected in-sequence msg is outside the window between
4165 * the transmitters in-sequence ack and highest seqno -
4166 * the receiver seems to be confused.
4167 */
4168 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4169 "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
4170 "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
4171 err_H:
4172 SSCOP_MSG_FREE(msg);
4173 m_reset_data_xfer_timers(sscop);
4174 MAAL_ERROR(sscop, 'S', 0);
4175 sscop_recover(sscop);
4176 return;
4177 }
4178
4179 /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
4180 * next in sequence-SD-number of the receiver and means, it has all
4181 * messages below N(R). Remove all message below N(R) from the
4182 * transmission buffer. It may already be removed because of an
4183 * earlier selective ACK in a STAT message.
4184 */
4185 while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL
4186 && m->seqno < (u_int)pdu.sscop_ns) {
4187 ASSERT(m->seqno >= sscop->vt_a);
4188 MSGQ_REMOVE(&sscop->xbuf, m);
4189 SSCOP_MSG_FREE(m);
4190 }
4191
4192 /*
4193 * Update in-sequence ack, poll-ack and send window.
4194 */
4195 sscop->vt_a = pdu.sscop_ns;
4196 sscop->vt_pa = nps.sscop_n;
4197 sscop->vt_ms = nmr.sscop_n;
4198
4199 cnt = 0;
4200 if(len > 1) {
4201 seq1 = MBUF_GET32(msg->m);
4202 len--;
4203 if(seq1 >= sscop->vt_s) {
4204 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
4205 "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u",
4206 seq1, sscop->vt_s));
4207 goto err_H;
4208 }
4209
4210 for(;;) {
4211 seq2 = MBUF_GET32(msg->m);
4212 len--;
4213 if(seq1 >= seq2 || seq2 > sscop->vt_s) {
4214 VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
4215 sscop->aarg, "STAT: seq1 >= seq2 or "
4216 "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
4217 seq1, seq2, sscop->vt_s));
4218 goto err_H;
4219 }
4220
4221 do {
4222 /*
4223 * The receiver requests the re-transmission
4224 * of some message, but has acknowledged it
4225 * already in an earlier STAT (it isn't in the
4226 * transmitt buffer anymore).
4227 */
4228 if((m = QFIND(&sscop->xbuf, seq1)) == NULL) {
4229 VERBERR(sscop, SSCOP_DBG_ERR,
4230 (sscop, sscop->aarg, "STAT: message"
4231 " %u not found in xmit buffer",
4232 seq1));
4233 goto err_H;
4234 }
4235 if(m->poll_seqno < (u_int)nps.sscop_n
4236 && (u_int)nps.sscop_n <= sscop->vt_ps)
4237 if(!m->rexmit) {
4238 m->rexmit = 1;
4239 sscop->rxq++;
4240 cnt++;
4241 sscop_signal(sscop, SIG_PDU_Q, msg);
4242 }
4243 } while(++seq1 < seq2);
4244
4245 if(len == 0)
4246 break;
4247
4248 seq2 = MBUF_GET32(msg->m);
4249 len--;
4250
4251 if(seq1 >= seq2 || seq2 > sscop->vt_s) {
4252 VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
4253 sscop->aarg, "STAT: seq1 >= seq2 or "
4254 "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
4255 seq1, seq2, sscop->vt_s));
4256 goto err_H;
4257 }
4258
4259 /* OK now the sucessful transmitted messages. Note, that
4260 * some messages may already be out of the buffer because
4261 * of earlier STATS */
4262 do {
4263 if(sscop->clear_buffers) {
4264 if((m = QFIND(&sscop->xbuf, seq1)) != NULL) {
4265 MSGQ_REMOVE(&sscop->xbuf, m);
4266 SSCOP_MSG_FREE(m);
4267 }
4268 }
4269 } while(++seq1 != seq2);
4270
4271 if(len == 0)
4272 break;
4273 }
4274 MAAL_ERROR(sscop, 'V', cnt);
4275 }
4276 SSCOP_MSG_FREE(msg);
4277
4278 /* label L: */
4279 if(sscop->vt_s >= sscop->vt_ms) {
4280 /*
4281 * The receiver has closed the window: report to management
4282 */
4283 if(sscop->credit) {
4284 sscop->credit = 0;
4285 MAAL_ERROR(sscop, 'W', 0);
4286 }
4287 } else if(!sscop->credit) {
4288 /*
4289 * The window was forcefully closed above, but
4290 * now re-opened. Report to management.
4291 */
4292 sscop->credit = 1;
4293 MAAL_ERROR(sscop, 'X', 0);
4294 }
4295
4296 if(TIMER_ISACT(sscop, poll)) {
4297 TIMER_RESTART(sscop, nr);
4298 } else if(!TIMER_ISACT(sscop, idle)) {
4299 TIMER_STOP(sscop, ka);
4300 TIMER_STOP(sscop, nr);
4301 TIMER_RESTART(sscop, idle);
4302 }
4303 }
4304
4305 /*
4306 * P. 73: any state & UDATA_REQUEST
4307 * arg is pdu (queued)
4308 */
4309 static void
4310 sscop_udata_req(struct sscop *sscop, struct sscop_msg *msg)
4311 {
4312 MSGQ_APPEND(&sscop->uxq, msg);
4313 sscop_signal(sscop, SIG_UPDU_Q, msg);
4314 }
4315
4316 /*
4317 * P. 73: any state & MDATA_REQUEST
4318 * arg is pdu (queued)
4319 */
4320 static void
4321 sscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg)
4322 {
4323 MSGQ_APPEND(&sscop->mxq, msg);
4324 sscop_signal(sscop, SIG_MPDU_Q, msg);
4325 }
4326
4327 /*
4328 * P. 74: any state & UDATA queued
4329 * no arg.
4330 */
4331 static void
4332 sscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused)
4333 {
4334 struct sscop_msg *msg;
4335
4336 if(sscop->ll_busy)
4337 return;
4338 while((msg = MSGQ_GET(&sscop->uxq)) != NULL) {
4339 send_ud(sscop, msg->m);
4340 msg->m = NULL;
4341 SSCOP_MSG_FREE(msg);
4342 }
4343 }
4344
4345 /*
4346 * P. 74: any state & MDATA queued
4347 * no arg.
4348 */
4349 static void
4350 sscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused)
4351 {
4352 struct sscop_msg *msg;
4353
4354 if(sscop->ll_busy)
4355 return;
4356 while((msg = MSGQ_GET(&sscop->mxq)) != NULL) {
4357 send_md(sscop, msg->m);
4358 msg->m = NULL;
4359 SSCOP_MSG_FREE(msg);
4360 }
4361 }
4362
4363 /*
4364 * p 73: MD PDU
4365 * arg is PDU
4366 */
4367 static void
4368 sscop_md(struct sscop *sscop, struct sscop_msg *msg)
4369 {
4370 union pdu pdu;
4371
4372 pdu.sscop_null = MBUF_STRIP32(msg->m);
4373
4374 MBUF_UNPAD(msg->m, pdu.sscop_pl);
4375
4376 MAAL_DATA(sscop, msg->m);
4377 msg->m = NULL;
4378 SSCOP_MSG_FREE(msg);
4379 }
4380
4381 /*
4382 * p 73: UD PDU
4383 * arg is PDU
4384 */
4385 static void
4386 sscop_ud(struct sscop *sscop, struct sscop_msg *msg)
4387 {
4388 union pdu pdu;
4389
4390 pdu.sscop_null = MBUF_STRIP32(msg->m);
4391
4392 MBUF_UNPAD(msg->m, pdu.sscop_pl);
4393
4394 AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0);
4395 msg->m = NULL;
4396 SSCOP_MSG_FREE(msg);
4397 }
4398
4399
4400 /*
4401 * p 33: IDLE & RETRIEVE
4402 * p 39: IN_PEND & RETRIEVE
4403 * p 42: OUT_DIS_PEND & RETRIEVE
4404 * p 48: IN_RESYNC_PEND & RETRIEVE
4405 * p 53: REC_PEND & RETRIEVE
4406 * p 58: IN_REC_PEND & RETRIEVE
4407 */
4408 static void
4409 sscop_retrieve(struct sscop *sscop, struct sscop_msg *msg)
4410 {
4411 m_data_retrieval(sscop, msg->rexmit);
4412 SSCOP_MSG_FREE(msg);
4413 }
4414
4415 /************************************************************/
4416 /*
4417 * GENERAL EVENT HANDLING
4418 */
4419
4420 /*
4421 * State/event matrix.
4422 *
4423 * Entries marked with Z are not specified in Q.2110, but are added for
4424 * the sake of stability.
4425 */
4426 static struct {
4427 void (*func)(struct sscop *, struct sscop_msg *);
4428 int (*cond)(struct sscop *);
4429 } state_matrix[SSCOP_NSTATES][SIG_NUM] = {
4430 /* SSCOP_IDLE */ {
4431 /* SIG_BGN */ { sscop_idle_bgn, NULL },
4432 /* SIG_BGAK */ { sscop_idle_bgak, NULL },
4433 /* SIG_END */ { sscop_idle_end, NULL },
4434 /* SIG_ENDAK */ { sscop_ignore_pdu, NULL },
4435 /* SIG_RS */ { sscop_idle_rs, NULL },
4436 /* SIG_RSAK */ { sscop_idle_rsak, NULL },
4437 /* SIG_BGREJ */ { sscop_idle_bgrej, NULL },
4438 /* SIG_SD */ { sscop_idle_sd, NULL },
4439 /* SIG_ER */ { sscop_idle_er, NULL },
4440 /* SIG_POLL */ { sscop_idle_poll, NULL },
4441 /* SIG_STAT */ { sscop_idle_stat, NULL },
4442 /* SIG_USTAT */ { sscop_idle_ustat, NULL },
4443 /* SIG_UD */ { sscop_ud, NULL },
4444 /* SIG_MD */ { sscop_md, NULL },
4445 /* SIG_ERAK */ { sscop_idle_erak, NULL },
4446 /* SIG_T_CC */ { NULL, NULL },
4447 /* SIG_T_POLL */ { NULL, NULL },
4448 /* SIG_T_KA */ { NULL, NULL },
4449 /* SIG_T_NR */ { NULL, NULL },
4450 /* SIG_T_IDLE */ { NULL, NULL },
4451 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4452 /* SIG_USER_DATA */ { NULL, NULL },
4453 /* SIG_ESTAB_REQ */ { sscop_idle_establish_req, NULL },
4454 /* SIG_ESTAB_RESP */ { NULL, NULL },
4455 /* SIG_RELEASE_REQ */ { NULL, NULL },
4456 /* SIG_RECOVER */ { NULL, NULL },
4457 /* SIG_SYNC_REQ */ { NULL, NULL },
4458 /* SIG_SYNC_RESP */ { NULL, NULL },
4459 /* SIG_UDATA */ { sscop_udata_req, NULL },
4460 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4461 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4462 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4463 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4464 },
4465 /* SSCOP_OUT_PEND */ {
4466 /* SIG_BGN */ { sscop_outpend_bgn, NULL },
4467 /* SIG_BGAK */ { sscop_outpend_bgak, NULL },
4468 /* SIG_END */ { sscop_ignore_pdu, NULL },
4469 /* SIG_ENDAK */ { sscop_ignore_pdu, NULL },
4470 /* SIG_RS */ { sscop_ignore_pdu, NULL },
4471 /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
4472 /* SIG_BGREJ */ { sscop_outpend_bgrej, NULL },
4473 /* SIG_SD */ { sscop_ignore_pdu, NULL },
4474 /* SIG_ER */ { sscop_ignore_pdu, NULL },
4475 /* SIG_POLL */ { sscop_ignore_pdu, NULL },
4476 /* SIG_STAT */ { sscop_ignore_pdu, NULL },
4477 /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
4478 /* SIG_UD */ { sscop_ud, NULL },
4479 /* SIG_MD */ { sscop_md, NULL },
4480 /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
4481 /* SIG_T_CC */ { sscop_outpend_tcc, NULL },
4482 /* SIG_T_POLL */ { NULL, NULL },
4483 /* SIG_T_KA */ { NULL, NULL },
4484 /* SIG_T_NR */ { NULL, NULL },
4485 /* SIG_T_IDLE */ { NULL, NULL },
4486 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4487 /* SIG_USER_DATA */ { NULL, NULL },
4488 /* SIG_ESTAB_REQ */ { NULL, NULL },
4489 /* SIG_ESTAB_RESP */ { NULL, NULL },
4490 /* SIG_RELEASE_REQ */ { sscop_outpend_release_req, NULL },
4491 /* SIG_RECOVER */ { NULL, NULL },
4492 /* SIG_SYNC_REQ */ { NULL, NULL },
4493 /* SIG_SYNC_RESP */ { NULL, NULL },
4494 /* SIG_UDATA */ { sscop_udata_req, NULL },
4495 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4496 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4497 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4498 /* SIG_RETRIEVE */ { NULL, NULL },
4499 },
4500 /* SSCOP_IN_PEND */ {
4501 /* SIG_BGN */ { sscop_inpend_bgn, NULL },
4502 /* SIG_BGAK */ { sscop_inpend_bgak, NULL },
4503 /* SIG_END */ { sscop_inpend_end, NULL },
4504 /* SIG_ENDAK */ { sscop_inpend_endak, NULL },
4505 /* SIG_RS */ { sscop_inpend_rs, NULL },
4506 /* SIG_RSAK */ { sscop_inpend_rsak, NULL },
4507 /* SIG_BGREJ */ { sscop_inpend_bgrej, NULL },
4508 /* SIG_SD */ { sscop_inpend_sd, NULL },
4509 /* SIG_ER */ { sscop_inpend_er, NULL },
4510 /* SIG_POLL */ { sscop_inpend_poll, NULL },
4511 /* SIG_STAT */ { sscop_inpend_stat, NULL },
4512 /* SIG_USTAT */ { sscop_inpend_ustat, NULL },
4513 /* SIG_UD */ { sscop_ud, NULL },
4514 /* SIG_MD */ { sscop_md, NULL },
4515 /* SIG_ERAK */ { sscop_inpend_erak, NULL },
4516 /* SIG_T_CC */ { NULL, NULL },
4517 /* SIG_T_POLL */ { NULL, NULL },
4518 /* SIG_T_KA */ { NULL, NULL },
4519 /* SIG_T_NR */ { NULL, NULL },
4520 /* SIG_T_IDLE */ { NULL, NULL },
4521 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4522 /* SIG_USER_DATA */ { NULL, NULL },
4523 /* SIG_ESTAB_REQ */ { NULL, NULL },
4524 /* SIG_ESTAB_RESP */ { sscop_inpend_establish_resp, NULL },
4525 /* SIG_RELEASE_REQ */ { sscop_inpend_release_req, NULL },
4526 /* SIG_RECOVER */ { NULL, NULL },
4527 /* SIG_SYNC_REQ */ { NULL, NULL },
4528 /* SIG_SYNC_RESP */ { NULL, NULL },
4529 /* SIG_UDATA */ { sscop_udata_req, NULL },
4530 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4531 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4532 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4533 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4534 },
4535 /* SSCOP_OUT_DIS_PEND */ {
4536 /* SIG_BGN */ { sscop_outdis_bgn, NULL },
4537 /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
4538 /* SIG_END */ { sscop_outdis_end, NULL },
4539 /* SIG_ENDAK */ { sscop_outdis_endak, NULL },
4540 /* SIG_RS */ { sscop_ignore_pdu, NULL },
4541 /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
4542 /* SIG_BGREJ */ { sscop_outdis_endak, NULL },
4543 /* SIG_SD */ { sscop_ignore_pdu, NULL },
4544 /* SIG_ER */ { sscop_ignore_pdu, NULL },
4545 /* SIG_POLL */ { sscop_ignore_pdu, NULL },
4546 /* SIG_STAT */ { sscop_ignore_pdu, NULL },
4547 /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
4548 /* SIG_UD */ { sscop_ud, NULL },
4549 /* SIG_MD */ { sscop_md, NULL },
4550 /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
4551 /* SIG_T_CC */ { sscop_outdis_cc, NULL },
4552 /* SIG_T_POLL */ { NULL, NULL },
4553 /* SIG_T_KA */ { NULL, NULL },
4554 /* SIG_T_NR */ { NULL, NULL },
4555 /* SIG_T_IDLE */ { NULL, NULL },
4556 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4557 /* SIG_USER_DATA */ { NULL, NULL },
4558 /* SIG_ESTAB_REQ */ { sscop_outdis_establish_req, NULL },
4559 /* SIG_ESTAB_RESP */ { NULL, NULL },
4560 /* SIG_RELEASE_REQ */ { NULL, NULL },
4561 /* SIG_RECOVER */ { NULL, NULL },
4562 /* SIG_SYNC_REQ */ { NULL, NULL },
4563 /* SIG_SYNC_RESP */ { NULL, NULL },
4564 /* SIG_UDATA */ { sscop_udata_req, NULL },
4565 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4566 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4567 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4568 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4569 },
4570 /* SSCOP_OUT_RESYNC_PEND */ {
4571 /* SIG_BGN */ { sscop_outsync_bgn, NULL },
4572 /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
4573 /* SIG_END */ { sscop_outsync_end, NULL },
4574 /* SIG_ENDAK */ { sscop_outsync_endak, NULL },
4575 /* SIG_RS */ { sscop_outsync_rs, NULL },
4576 /* SIG_RSAK */ { sscop_outsync_rsak, NULL },
4577 /* SIG_BGREJ */ { sscop_outsync_bgrej, NULL },
4578 /* SIG_SD */ { sscop_ignore_pdu, NULL },
4579 /* SIG_ER */ { sscop_ignore_pdu, NULL },
4580 /* SIG_POLL */ { sscop_ignore_pdu, NULL },
4581 /* SIG_STAT */ { sscop_ignore_pdu, NULL },
4582 /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
4583 /* SIG_UD */ { sscop_ud, NULL },
4584 /* SIG_MD */ { sscop_md, NULL },
4585 /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
4586 /* SIG_T_CC */ { sscop_outsync_cc, NULL },
4587 /* SIG_T_POLL */ { NULL, NULL },
4588 /* SIG_T_KA */ { NULL, NULL },
4589 /* SIG_T_NR */ { NULL, NULL },
4590 /* SIG_T_IDLE */ { NULL, NULL },
4591 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4592 /* SIG_USER_DATA */ { NULL, NULL },
4593 /* SIG_ESTAB_REQ */ { NULL, NULL },
4594 /* SIG_ESTAB_RESP */ { NULL, NULL },
4595 /* SIG_RELEASE_REQ */ { sscop_outsync_release_req, NULL },
4596 /* SIG_RECOVER */ { NULL, NULL },
4597 /* SIG_SYNC_REQ */ { NULL, NULL },
4598 /* SIG_SYNC_RESP */ { NULL, NULL },
4599 /* SIG_UDATA */ { sscop_udata_req, NULL },
4600 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4601 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4602 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4603 /* SIG_RETRIEVE */ { NULL, NULL },
4604 },
4605 /* SSCOP_IN_RESYNC_PEND */ {
4606 /* SIG_BGN */ { sscop_insync_bgn, NULL },
4607 /* SIG_BGAK */ { sscop_insync_bgak, NULL },
4608 /* SIG_END */ { sscop_insync_end, NULL },
4609 /* SIG_ENDAK */ { sscop_insync_endak, NULL },
4610 /* SIG_RS */ { sscop_insync_rs, NULL },
4611 /* SIG_RSAK */ { sscop_insync_rsak, NULL },
4612 /* SIG_BGREJ */ { sscop_insync_bgrej, NULL },
4613 /* SIG_SD */ { sscop_insync_sd, NULL },
4614 /* SIG_ER */ { sscop_insync_er, NULL },
4615 /* SIG_POLL */ { sscop_insync_poll, NULL },
4616 /* SIG_STAT */ { sscop_insync_stat, NULL },
4617 /* SIG_USTAT */ { sscop_insync_ustat, NULL },
4618 /* SIG_UD */ { sscop_ud, NULL },
4619 /* SIG_MD */ { sscop_md, NULL },
4620 /* SIG_ERAK */ { sscop_insync_erak, NULL },
4621 /* SIG_T_CC */ { NULL, NULL },
4622 /* SIG_T_POLL */ { NULL, NULL },
4623 /* SIG_T_KA */ { NULL, NULL },
4624 /* SIG_T_NR */ { NULL, NULL },
4625 /* SIG_T_IDLE */ { NULL, NULL },
4626 /* SIG_PDU_Q */ { sscop_flush_pduq, NULL },
4627 /* SIG_USER_DATA */ { NULL, NULL },
4628 /* SIG_ESTAB_REQ */ { NULL, NULL },
4629 /* SIG_ESTAB_RESP */ { NULL, NULL },
4630 /* SIG_RELEASE_REQ */ { sscop_insync_release_req, NULL },
4631 /* SIG_RECOVER */ { NULL, NULL },
4632 /* SIG_SYNC_REQ */ { NULL, NULL },
4633 /* SIG_SYNC_RESP */ { sscop_insync_sync_resp, NULL },
4634 /* SIG_UDATA */ { sscop_udata_req, NULL },
4635 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4636 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4637 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4638 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4639 },
4640 /* SSCOP_OUT_REC_PEND */ {
4641 /* SIG_BGN */ { sscop_outrec_bgn, NULL },
4642 /* SIG_BGAK */ { sscop_outrec_bgak, NULL },
4643 /* SIG_END */ { sscop_outrec_end, NULL },
4644 /* SIG_ENDAK */ { sscop_outrec_endak, NULL },
4645 /* SIG_RS */ { sscop_outrec_rs, NULL },
4646 /* SIG_RSAK */ { sscop_outrec_rsak, NULL },
4647 /* SIG_BGREJ */ { sscop_outrec_bgrej, NULL },
4648 /* SIG_SD */ { sscop_ignore_pdu, NULL },
4649 /* SIG_ER */ { sscop_outrec_er, NULL },
4650 /* SIG_POLL */ { sscop_ignore_pdu, NULL },
4651 /* SIG_STAT */ { sscop_ignore_pdu, NULL },
4652 /* SIG_USTAT */ { sscop_ignore_pdu, NULL },
4653 /* SIG_UD */ { sscop_ud, NULL },
4654 /* SIG_MD */ { sscop_md, NULL },
4655 /* SIG_ERAK */ { sscop_outrec_erak, NULL },
4656 /* SIG_T_CC */ { sscop_outrec_cc, NULL },
4657 /* SIG_T_POLL */ { NULL, NULL },
4658 /* SIG_T_KA */ { NULL, NULL },
4659 /* SIG_T_NR */ { NULL, NULL },
4660 /* SIG_T_IDLE */ { NULL, NULL },
4661 /* SIG_PDU_Q */ { sscop_outrec_pduq, NULL },
4662 /* SIG_USER_DATA */ { sscop_outrec_userdata, NULL },
4663 /* SIG_ESTAB_REQ */ { NULL, NULL },
4664 /* SIG_ESTAB_RESP */ { NULL, NULL },
4665 /* SIG_RELEASE_REQ */ { sscop_outrec_release_req, NULL },
4666 /* SIG_RECOVER */ { NULL, NULL },
4667 /* SIG_SYNC_REQ */ { sscop_outrec_sync_req, NULL },
4668 /* SIG_SYNC_RESP */ { NULL, NULL },
4669 /* SIG_UDATA */ { sscop_udata_req, NULL },
4670 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4671 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4672 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4673 /* SIG_RETRIEVE */ { NULL, NULL },
4674 },
4675 /* SSCOP_REC_PEND */ {
4676 /* SIG_BGN */ { sscop_rec_bgn, NULL },
4677 /* SIG_BGAK */ { sscop_rec_bgak, NULL },
4678 /* SIG_END */ { sscop_rec_end, NULL },
4679 /* SIG_ENDAK */ { sscop_rec_endak, NULL },
4680 /* SIG_RS */ { sscop_rec_rs, NULL },
4681 /* SIG_RSAK */ { sscop_rec_rsak, NULL },
4682 /* SIG_BGREJ */ { sscop_rec_bgrej, NULL },
4683 /* SIG_SD */ { sscop_ignore_pdu, NULL },
4684 /* SIG_ER */ { sscop_rec_er, NULL },
4685 /* SIG_POLL */ { sscop_ignore_pdu, NULL },
4686 /* SIG_STAT */ { sscop_rec_stat, NULL },
4687 /* SIG_USTAT */ { sscop_rec_ustat, NULL },
4688 /* SIG_UD */ { sscop_ud, NULL },
4689 /* SIG_MD */ { sscop_md, NULL },
4690 /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
4691 /* SIG_T_CC */ { NULL, NULL },
4692 /* SIG_T_POLL */ { NULL, NULL },
4693 /* SIG_T_KA */ { NULL, NULL },
4694 /* SIG_T_NR */ { NULL, NULL },
4695 /* SIG_T_IDLE */ { NULL, NULL },
4696 /* SIG_PDU_Q */ { sscop_rec_pduq, NULL },
4697 /* SIG_USER_DATA */ { NULL, NULL },
4698 /* SIG_ESTAB_REQ */ { NULL, NULL },
4699 /* SIG_ESTAB_RESP */ { NULL, NULL },
4700 /* SIG_RELEASE_REQ */ { sscop_rec_release_req, NULL },
4701 /* SIG_RECOVER */ { sscop_rec_recover, NULL },
4702 /* SIG_SYNC_REQ */ { sscop_rec_sync_req, NULL },
4703 /* SIG_SYNC_RESP */ { NULL, NULL },
4704 /* SIG_UDATA */ { sscop_udata_req, NULL },
4705 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4706 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4707 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4708 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4709 },
4710 /* SSCOP_IN_REC_PEND */ {
4711 /* SIG_BGN */ { sscop_inrec_bgn, NULL },
4712 /* SIG_BGAK */ { sscop_inrec_bgak, NULL },
4713 /* SIG_END */ { sscop_inrec_end, NULL },
4714 /* SIG_ENDAK */ { sscop_inrec_endak, NULL },
4715 /* SIG_RS */ { sscop_inrec_rs, NULL },
4716 /* SIG_RSAK */ { sscop_inrec_rsak, NULL },
4717 /* SIG_BGREJ */ { sscop_inrec_bgrej, NULL },
4718 /* SIG_SD */ { sscop_inrec_sd, NULL },
4719 /* SIG_ER */ { sscop_inrec_er, NULL },
4720 /* SIG_POLL */ { sscop_inrec_poll, NULL },
4721 /* SIG_STAT */ { sscop_inrec_stat, NULL },
4722 /* SIG_USTAT */ { sscop_inrec_ustat, NULL },
4723 /* SIG_UD */ { sscop_ud, NULL },
4724 /* SIG_MD */ { sscop_md, NULL },
4725 /* SIG_ERAK */ { sscop_inrec_erak, NULL },
4726 /* SIG_T_CC */ { NULL, NULL },
4727 /* SIG_T_POLL */ { NULL, NULL },
4728 /* SIG_T_KA */ { NULL, NULL },
4729 /* SIG_T_NR */ { NULL, NULL },
4730 /* SIG_T_IDLE */ { NULL, NULL },
4731 /* SIG_PDU_Q */ { sscop_inrec_pduq, NULL },
4732 /* SIG_USER_DATA */ { NULL, NULL },
4733 /* SIG_ESTAB_REQ */ { NULL, NULL },
4734 /* SIG_ESTAB_RESP */ { NULL, NULL },
4735 /* SIG_RELEASE_REQ */ { sscop_inrec_release_req, NULL },
4736 /* SIG_RECOVER */ { sscop_inrec_recover, NULL },
4737 /* SIG_SYNC_REQ */ { sscop_inrec_sync_req, NULL },
4738 /* SIG_SYNC_RESP */ { NULL, NULL },
4739 /* SIG_UDATA */ { sscop_udata_req, NULL },
4740 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4741 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4742 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4743 /* SIG_RETRIEVE */ { sscop_retrieve, NULL },
4744 },
4745 /* SSCOP_READY */ {
4746 /* SIG_BGN */ { sscop_ready_bgn, NULL },
4747 /* SIG_BGAK */ { sscop_ignore_pdu, NULL },
4748 /* SIG_END */ { sscop_ready_end, NULL },
4749 /* SIG_ENDAK */ { sscop_ready_endak, NULL },
4750 /* SIG_RS */ { sscop_ready_rs, NULL },
4751 /* SIG_RSAK */ { sscop_ignore_pdu, NULL },
4752 /* SIG_BGREJ */ { sscop_ready_bgrej, NULL },
4753 /* SIG_SD */ { sscop_ready_sd, NULL },
4754 /* SIG_ER */ { sscop_ready_er, NULL },
4755 /* SIG_POLL */ { sscop_ready_poll, NULL },
4756 /* SIG_STAT */ { sscop_ready_stat, NULL },
4757 /* SIG_USTAT */ { sscop_ready_ustat, NULL },
4758 /* SIG_UD */ { sscop_ud, NULL },
4759 /* SIG_MD */ { sscop_md, NULL },
4760 /* SIG_ERAK */ { sscop_ignore_pdu, NULL },
4761 /* SIG_T_CC */ { NULL, NULL },
4762 /* SIG_T_POLL */ { sscop_ready_tpoll, NULL },
4763 /* SIG_T_KA */ { sscop_ready_tka, NULL },
4764 /* SIG_T_NR */ { sscop_ready_nr, NULL },
4765 /* SIG_T_IDLE */ { sscop_ready_tidle, NULL },
4766 /* SIG_PDU_Q */ { sscop_ready_pduq, c_ready_pduq },
4767 /* SIG_USER_DATA */ { sscop_ready_userdata, NULL },
4768 /* SIG_ESTAB_REQ */ { NULL, NULL },
4769 /* SIG_ESTAB_RESP */ { NULL, NULL },
4770 /* SIG_RELEASE_REQ */ { sscop_ready_release_req, NULL },
4771 /* SIG_RECOVER */ { NULL, NULL },
4772 /* SIG_SYNC_REQ */ { sscop_ready_sync_req, NULL },
4773 /* SIG_SYNC_RESP */ { NULL, NULL },
4774 /* SIG_UDATA */ { sscop_udata_req, NULL },
4775 /* SIG_MDATA */ { sscop_mdata_req, NULL },
4776 /* SIG_UPDU_Q */ { sscop_upduq, NULL },
4777 /* SIG_MPDU_Q */ { sscop_mpduq, NULL },
4778 /* SIG_RETRIEVE */ { NULL, NULL },
4779 }
4780 };
4781
4782 /*
4783 * Try to execute a signal. It is executed if
4784 * - it is illegal (in this case it is effectively ignored)
4785 * - it has no condition
4786 * - its condition is true
4787 * If it has a condition and that is false, the function does nothing and
4788 * returns 0.
4789 * If the signal gets executed, the signal function is responsible to release
4790 * the message (if any).
4791 */
4792 static int
4793 sig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4794 {
4795 void (*func)(struct sscop *, struct sscop_msg *);
4796 int (*cond)(struct sscop *);
4797
4798 func = state_matrix[sscop->state][sig].func;
4799 cond = state_matrix[sscop->state][sig].cond;
4800
4801 if(func == NULL) {
4802 VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg,
4803 "no handler for %s in state %s - ignored",
4804 events[sig], states[sscop->state]));
4805 SSCOP_MSG_FREE(msg);
4806 return 1;
4807 }
4808 if(cond == NULL || (*cond)(sscop)) {
4809 VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
4810 "executing %s in %s", events[sig],
4811 states[sscop->state]));
4812 (*func)(sscop, msg);
4813 return 1;
4814 }
4815 VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
4816 "delaying %s in %s", events[sig],
4817 states[sscop->state]));
4818
4819 return 0;
4820 }
4821
4822 /*
4823 * Deliver a signal to the given sscop
4824 * If it is delivered from inside a signal handler - queue it. If not,
4825 * execute it. After execution loop through the queue and execute all
4826 * pending signals. Signals, that cannot be executed because of entry
4827 * conditions are skipped.
4828 */
4829 static void
4830 sscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4831 {
4832 struct sscop_sig *s;
4833
4834 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
4835 "got signal %s in state %s%s", events[sig],
4836 states[sscop->state], sscop->in_sig ? " -- queuing" : ""));
4837
4838 SIG_ALLOC(s);
4839 if(s == NULL) {
4840 FAILURE("sscop: cannot allocate signal");
4841 SSCOP_MSG_FREE(msg);
4842 return;
4843 }
4844 s->sig = sig;
4845 s->msg = msg;
4846 SIGQ_APPEND(&sscop->sigs, s);
4847
4848 if(!sscop->in_sig)
4849 handle_sigs(sscop);
4850 }
4851
4852 /*
4853 * Loop through the signal queue until we can't execute any signals.
4854 */
4855 static void
4856 handle_sigs(struct sscop *sscop)
4857 {
4858 struct sscop_sig *s;
4859 sscop_sigq_head_t dsigs, q;
4860 int exec;
4861
4862 sscop->in_sig++;
4863
4864 /*
4865 * Copy the current signal queue to the local one and empty
4866 * the signal queue. Then loop through the signals. After one
4867 * pass we have a list of delayed signals because of entry
4868 * conditions and a new list of signals. Merge them. Repeat until
4869 * the signal queue is either empty or contains only delayed signals.
4870 */
4871 SIGQ_INIT(&q);
4872 SIGQ_INIT(&dsigs);
4873 do {
4874 exec = 0;
4875
4876 /*
4877 * Copy signal list and make sscop list empty
4878 */
4879 SIGQ_MOVE(&sscop->sigs, &q);
4880
4881 /*
4882 * Loop through the list
4883 */
4884 while((s = SIGQ_GET(&q)) != NULL) {
4885 if(sig_exec(sscop, s->sig, s->msg)) {
4886 exec = 1;
4887 SIG_FREE(s);
4888 } else {
4889 SIGQ_APPEND(&dsigs, s);
4890 }
4891 }
4892
4893 /*
4894 * Merge lists by inserting delayed signals in front of
4895 * the signal list. preserving the order.
4896 */
4897 SIGQ_PREPEND(&dsigs, &sscop->sigs);
4898 } while(exec);
4899 sscop->in_sig--;
4900 }
4901
4902 /*
4903 * Save a signal that should be executed only if state changes.
4904 */
4905 static void
4906 sscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
4907 {
4908 struct sscop_sig *s;
4909
4910 SIG_ALLOC(s);
4911 if(s == NULL) {
4912 FAILURE("sscop: cannot allocate signal");
4913 SSCOP_MSG_FREE(msg);
4914 return;
4915 }
4916 s->sig = sig;
4917 s->msg = msg;
4918 SIGQ_APPEND(&sscop->saved_sigs, s);
4919 }
4920
4921 /*
4922 * Set a new state. If signals are waiting for a state change - append them to
4923 * the signal queue, so they get executed.
4924 */
4925 static void
4926 sscop_set_state(struct sscop *sscop, u_int nstate)
4927 {
4928 VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg,
4929 "changing state from %s to %s",
4930 states[sscop->state], states[nstate]));
4931
4932 sscop->state = nstate;
4933 SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs);
4934 }
4935
4936 void
4937 sscop_setdebug(struct sscop *sscop, u_int n)
4938 {
4939 sscop->debug = n;
4940 }
4941
4942 u_int
4943 sscop_getdebug(const struct sscop *sscop)
4944 {
4945 return (sscop->debug);
4946 }
Cache object: b17071b7673f54bb59b2f2f86298bd76
|