3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/q2110_sigcpcs.c,v 1.4 2000/01/17 20:49:49 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/q2110_sigcpcs.c,v 1.6 2004/07/23 14:14:30 joerg Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * ITU-T Q.2110 - Process CPCS-signals (SSCOP PDUs)
38 #include <netproto/atm/kern_include.h>
41 #include "sscop_misc.h"
42 #include "sscop_pdu.h"
43 #include "sscop_var.h"
48 static void sscop_bgn_outconn (struct sscop *, KBuffer *, caddr_t);
49 static void sscop_bgn_inconn (struct sscop *, KBuffer *, caddr_t);
50 static void sscop_bgn_ready (struct sscop *, KBuffer *, caddr_t);
51 static void sscop_bgrej_outrecov (struct sscop *, KBuffer *, caddr_t);
52 static void sscop_end_outrecov (struct sscop *, KBuffer *, caddr_t);
53 static void sscop_end_ready (struct sscop *, KBuffer *, caddr_t);
54 static void sscop_endak_outrecov (struct sscop *, KBuffer *, caddr_t);
55 static void sscop_rs_outresyn (struct sscop *, KBuffer *, caddr_t);
56 static void sscop_rs_inresyn (struct sscop *, KBuffer *, caddr_t);
57 static void sscop_rs_outrecov (struct sscop *, KBuffer *, caddr_t);
58 static void sscop_rs_ready (struct sscop *, KBuffer *, caddr_t);
59 static void sscop_er_error (struct sscop *, KBuffer *, caddr_t);
60 static void sscop_er_idle (struct sscop *, KBuffer *, caddr_t);
61 static void sscop_er_outrecov (struct sscop *, KBuffer *, caddr_t);
62 static void sscop_er_recovrsp (struct sscop *, KBuffer *, caddr_t);
63 static void sscop_er_inrecov (struct sscop *, KBuffer *, caddr_t);
64 static void sscop_er_ready (struct sscop *, KBuffer *, caddr_t);
65 static void sscop_erak_error (struct sscop *, KBuffer *, caddr_t);
66 static void sscop_erak_idle (struct sscop *, KBuffer *, caddr_t);
67 static void sscop_erak_outrecov (struct sscop *, KBuffer *, caddr_t);
68 static void sscop_sd_ready (struct sscop *, KBuffer *, caddr_t);
69 static void sscop_poll_ready (struct sscop *, KBuffer *, caddr_t);
73 * PDU type state lookup tables
76 static void (*sscop_bgn_tab[SOS_NUMSTATES])
77 (struct sscop *, KBuffer *, caddr_t) = {
79 sscop_bgn_idle, /* SOS_IDLE */
80 sscop_bgn_outconn, /* SOS_OUTCONN */
81 sscop_bgn_inconn, /* SOS_INCONN */
82 sscop_bgn_outdisc, /* SOS_OUTDISC */
83 sscop_bgn_outresyn, /* SOS_OUTRESYN */
84 sscop_bgn_inresyn, /* SOS_INRESYN */
85 sscop_bgn_inresyn, /* SOS_OUTRECOV */
86 sscop_bgn_inresyn, /* SOS_RECOVRSP */
87 sscop_bgn_inresyn, /* SOS_INRECOV */
88 sscop_bgn_ready, /* SOS_READY */
89 sscop_noop /* SOS_TERM */
93 static void (*sscop_bgak_tab[SOS_NUMSTATES])
94 (struct sscop *, KBuffer *, caddr_t) = {
96 sscop_bgak_idle, /* SOS_IDLE */
97 sscop_bgak_outconn, /* SOS_OUTCONN */
98 sscop_bgak_error, /* SOS_INCONN */
99 sscop_noop, /* SOS_OUTDISC */
100 sscop_noop, /* SOS_OUTRESYN */
101 sscop_bgak_error, /* SOS_INRESYN */
102 sscop_bgak_error, /* SOS_OUTRECOV */
103 sscop_bgak_error, /* SOS_RECOVRSP */
104 sscop_bgak_error, /* SOS_INRECOV */
105 sscop_noop, /* SOS_READY */
106 sscop_noop /* SOS_TERM */
110 static void (*sscop_bgrej_tab[SOS_NUMSTATES])
111 (struct sscop *, KBuffer *, caddr_t) = {
113 sscop_bgrej_error, /* SOS_IDLE */
114 sscop_bgrej_outconn, /* SOS_OUTCONN */
115 sscop_bgrej_inconn, /* SOS_INCONN */
116 sscop_endak_outdisc, /* SOS_OUTDISC */
117 sscop_bgrej_outresyn, /* SOS_OUTRESYN */
118 sscop_bgrej_inconn, /* SOS_INRESYN */
119 sscop_bgrej_outrecov, /* SOS_OUTRECOV */
120 sscop_bgrej_inconn, /* SOS_RECOVRSP */
121 sscop_bgrej_inconn, /* SOS_INRECOV */
122 sscop_bgrej_ready, /* SOS_READY */
123 sscop_noop /* SOS_TERM */
127 static void (*sscop_end_tab[SOS_NUMSTATES])
128 (struct sscop *, KBuffer *, caddr_t) = {
130 sscop_end_idle, /* SOS_IDLE */
131 sscop_noop, /* SOS_OUTCONN */
132 sscop_end_inconn, /* SOS_INCONN */
133 sscop_end_outdisc, /* SOS_OUTDISC */
134 sscop_end_inconn, /* SOS_OUTRESYN */
135 sscop_end_inconn, /* SOS_INRESYN */
136 sscop_end_outrecov, /* SOS_OUTRECOV */
137 sscop_end_inconn, /* SOS_RECOVRSP */
138 sscop_end_inconn, /* SOS_INRECOV */
139 sscop_end_ready, /* SOS_READY */
140 sscop_noop /* SOS_TERM */
144 static void (*sscop_endak_tab[SOS_NUMSTATES])
145 (struct sscop *, KBuffer *, caddr_t) = {
147 sscop_noop, /* SOS_IDLE */
148 sscop_noop, /* SOS_OUTCONN */
149 sscop_endak_inconn, /* SOS_INCONN */
150 sscop_endak_outdisc, /* SOS_OUTDISC */
151 sscop_endak_inconn, /* SOS_OUTRESYN */
152 sscop_endak_inconn, /* SOS_INRESYN */
153 sscop_endak_outrecov, /* SOS_OUTRECOV */
154 sscop_endak_inconn, /* SOS_RECOVRSP */
155 sscop_endak_inconn, /* SOS_INRECOV */
156 sscop_endak_ready, /* SOS_READY */
157 sscop_noop /* SOS_TERM */
161 static void (*sscop_rs_tab[SOS_NUMSTATES])
162 (struct sscop *, KBuffer *, caddr_t) = {
164 sscop_rs_idle, /* SOS_IDLE */
165 sscop_noop, /* SOS_OUTCONN */
166 sscop_rs_error, /* SOS_INCONN */
167 sscop_noop, /* SOS_OUTDISC */
168 sscop_rs_outresyn, /* SOS_OUTRESYN */
169 sscop_rs_inresyn, /* SOS_INRESYN */
170 sscop_rs_outrecov, /* SOS_OUTRECOV */
171 sscop_rs_outrecov, /* SOS_RECOVRSP */
172 sscop_rs_outrecov, /* SOS_INRECOV */
173 sscop_rs_ready, /* SOS_READY */
174 sscop_noop /* SOS_TERM */
178 static void (*sscop_rsak_tab[SOS_NUMSTATES])
179 (struct sscop *, KBuffer *, caddr_t) = {
181 sscop_rsak_idle, /* SOS_IDLE */
182 sscop_noop, /* SOS_OUTCONN */
183 sscop_rsak_error, /* SOS_INCONN */
184 sscop_noop, /* SOS_OUTDISC */
185 sscop_rsak_outresyn, /* SOS_OUTRESYN */
186 sscop_rsak_error, /* SOS_INRESYN */
187 sscop_rsak_error, /* SOS_OUTRECOV */
188 sscop_rsak_error, /* SOS_RECOVRSP */
189 sscop_rsak_error, /* SOS_INRECOV */
190 sscop_noop, /* SOS_READY */
191 sscop_noop /* SOS_TERM */
195 static void (*sscop_er_tab[SOS_NUMSTATES])
196 (struct sscop *, KBuffer *, caddr_t) = {
198 sscop_er_idle, /* SOS_IDLE */
199 sscop_noop, /* SOS_OUTCONN */
200 sscop_er_error, /* SOS_INCONN */
201 sscop_noop, /* SOS_OUTDISC */
202 sscop_noop, /* SOS_OUTRESYN */
203 sscop_er_error, /* SOS_INRESYN */
204 sscop_er_outrecov, /* SOS_OUTRECOV */
205 sscop_er_recovrsp, /* SOS_RECOVRSP */
206 sscop_er_inrecov, /* SOS_INRECOV */
207 sscop_er_ready, /* SOS_READY */
208 sscop_noop /* SOS_TERM */
212 static void (*sscop_erak_tab[SOS_NUMSTATES])
213 (struct sscop *, KBuffer *, caddr_t) = {
215 sscop_erak_idle, /* SOS_IDLE */
216 sscop_noop, /* SOS_OUTCONN */
217 sscop_erak_error, /* SOS_INCONN */
218 sscop_noop, /* SOS_OUTDISC */
219 sscop_noop, /* SOS_OUTRESYN */
220 sscop_erak_error, /* SOS_INRESYN */
221 sscop_erak_outrecov, /* SOS_OUTRECOV */
222 sscop_noop, /* SOS_RECOVRSP */
223 sscop_erak_error, /* SOS_INRECOV */
224 sscop_noop, /* SOS_READY */
225 sscop_noop /* SOS_TERM */
229 static void (*sscop_sd_tab[SOS_NUMSTATES])
230 (struct sscop *, KBuffer *, caddr_t) = {
232 sscop_sd_idle, /* SOS_IDLE */
233 sscop_noop, /* SOS_OUTCONN */
234 sscop_sd_inconn, /* SOS_INCONN */
235 sscop_noop, /* SOS_OUTDISC */
236 sscop_noop, /* SOS_OUTRESYN */
237 sscop_sd_inconn, /* SOS_INRESYN */
238 sscop_noop, /* SOS_OUTRECOV */
239 sscop_noop, /* SOS_RECOVRSP */
240 sscop_sd_inconn, /* SOS_INRECOV */
241 sscop_sd_ready, /* SOS_READY */
242 sscop_noop /* SOS_TERM */
246 static void (*sscop_poll_tab[SOS_NUMSTATES])
247 (struct sscop *, KBuffer *, caddr_t) = {
249 sscop_poll_idle, /* SOS_IDLE */
250 sscop_noop, /* SOS_OUTCONN */
251 sscop_poll_inconn, /* SOS_INCONN */
252 sscop_noop, /* SOS_OUTDISC */
253 sscop_noop, /* SOS_OUTRESYN */
254 sscop_poll_inconn, /* SOS_INRESYN */
255 sscop_noop, /* SOS_OUTRECOV */
256 sscop_noop, /* SOS_RECOVRSP */
257 sscop_poll_inconn, /* SOS_INRECOV */
258 sscop_poll_ready, /* SOS_READY */
259 sscop_noop /* SOS_TERM */
263 static void (*sscop_stat_tab[SOS_NUMSTATES])
264 (struct sscop *, KBuffer *, caddr_t) = {
266 sscop_stat_idle, /* SOS_IDLE */
267 sscop_noop, /* SOS_OUTCONN */
268 sscop_stat_inconn, /* SOS_INCONN */
269 sscop_noop, /* SOS_OUTDISC */
270 sscop_noop, /* SOS_OUTRESYN */
271 sscop_stat_inconn, /* SOS_INRESYN */
272 sscop_noop, /* SOS_OUTRECOV */
273 sscop_stat_inconn, /* SOS_RECOVRSP */
274 sscop_stat_inconn, /* SOS_INRECOV */
275 sscop_stat_ready, /* SOS_READY */
276 sscop_noop /* SOS_TERM */
280 static void (*sscop_ustat_tab[SOS_NUMSTATES])
281 (struct sscop *, KBuffer *, caddr_t) = {
283 sscop_ustat_idle, /* SOS_IDLE */
284 sscop_noop, /* SOS_OUTCONN */
285 sscop_ustat_inconn, /* SOS_INCONN */
286 sscop_noop, /* SOS_OUTDISC */
287 sscop_noop, /* SOS_OUTRESYN */
288 sscop_ustat_inconn, /* SOS_INRESYN */
289 sscop_noop, /* SOS_OUTRECOV */
290 sscop_ustat_inconn, /* SOS_RECOVRSP */
291 sscop_ustat_inconn, /* SOS_INRECOV */
292 sscop_ustat_ready, /* SOS_READY */
293 sscop_noop /* SOS_TERM */
297 static void (*sscop_ud_tab[SOS_NUMSTATES])
298 (struct sscop *, KBuffer *, caddr_t) = {
300 sscop_ud_all, /* SOS_IDLE */
301 sscop_ud_all, /* SOS_OUTCONN */
302 sscop_ud_all, /* SOS_INCONN */
303 sscop_ud_all, /* SOS_OUTDISC */
304 sscop_ud_all, /* SOS_OUTRESYN */
305 sscop_ud_all, /* SOS_INRESYN */
306 sscop_ud_all, /* SOS_OUTRECOV */
307 sscop_ud_all, /* SOS_RECOVRSP */
308 sscop_ud_all, /* SOS_INRECOV */
309 sscop_ud_all, /* SOS_READY */
310 sscop_noop /* SOS_TERM */
314 static void (*sscop_md_tab[SOS_NUMSTATES])
315 (struct sscop *, KBuffer *, caddr_t) = {
317 sscop_md_all, /* SOS_IDLE */
318 sscop_md_all, /* SOS_OUTCONN */
319 sscop_md_all, /* SOS_INCONN */
320 sscop_md_all, /* SOS_OUTDISC */
321 sscop_md_all, /* SOS_OUTRESYN */
322 sscop_md_all, /* SOS_INRESYN */
323 sscop_md_all, /* SOS_OUTRECOV */
324 sscop_md_all, /* SOS_RECOVRSP */
325 sscop_md_all, /* SOS_INRECOV */
326 sscop_md_all, /* SOS_READY */
327 sscop_noop /* SOS_TERM */
332 * PDU type lookup table
334 void (*(*sscop_q2110_pdutab[]))
335 (struct sscop *, KBuffer *, caddr_t) = {
356 * BGN PDU / SOS_OUTCONN Processor
359 * sop pointer to sscop connection block
360 * m pointer to PDU buffer (without trailer)
361 * trlr pointer to PDU trailer
368 sscop_bgn_outconn(sop, m, trlr)
373 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
377 * If retransmitted BGN, ignore it
379 if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
385 * Stop retransmit timer
387 sop->so_timer[SSCOP_T_CC] = 0;
390 * Initialize state variables
392 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
393 SEQ_SET(sop->so_rcvmax, sop->so_parm.sp_rcvwin);
394 q2110_init_state(sop);
397 * Return an ACK to peer
399 (void) sscop_send_bgak(sop);
402 * Notify user of connection establishment
404 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku,
405 sop->so_connvc, (int)m, 0, err);
408 sscop_abort(sop, "stack memory\n");
413 * Start data transfer timers
415 sop->so_timer[SSCOP_T_POLL] = sop->so_parm.sp_timepoll;
416 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
419 * OK, we're ready for data
421 sop->so_state = SOS_READY;
424 * See if transmit queues need servicing
426 if (sop->so_flags & SOF_XMITSRVC)
427 sscop_service_xmit(sop);
434 * BGN PDU / SOS_INCONN Processor
437 * sop pointer to sscop connection block
438 * m pointer to PDU buffer (without trailer)
439 * trlr pointer to PDU trailer
446 sscop_bgn_inconn(sop, m, trlr)
451 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
455 * If retransmitted BGN, ignore it
457 if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
463 * Initialize transmit window
465 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
468 * First, tell user current connection has been released
470 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
471 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_USER, err);
474 sscop_abort(sop, "stack memory\n");
479 * Now, tell user of new connection establishment
481 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
482 sop->so_connvc, (int)m, 0, err);
485 sscop_abort(sop, "stack memory\n");
494 * BGN PDU / SOS_READY Processor
497 * sop pointer to sscop connection block
498 * m pointer to PDU buffer (without trailer)
499 * trlr pointer to PDU trailer
506 sscop_bgn_ready(sop, m, trlr)
511 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
515 * If retransmitted BGN, just ACK it again
517 if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
519 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
520 (void) sscop_send_bgak(sop);
525 * Stop data transfer timers
527 sop->so_timer[SSCOP_T_POLL] = 0;
528 sop->so_timer[SSCOP_T_NORESP] = 0;
529 sop->so_timer[SSCOP_T_IDLE] = 0;
530 sop->so_flags &= ~SOF_KEEPALIVE;
533 * Initialize transmit window
535 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
538 * Clear out appropriate queues
540 q2110_prep_retrieve(sop);
543 * Tell user current connection has been released
545 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
546 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_USER, err);
549 sscop_abort(sop, "stack memory\n");
554 * Tell user of incoming connection
556 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
557 sop->so_connvc, (int)m, 0, err);
560 sscop_abort(sop, "stack memory\n");
565 * Wait for user's response
567 sop->so_state = SOS_INCONN;
574 * BGREJ PDU / SOS_OUTRECOV Processor
577 * sop pointer to sscop connection block
578 * m pointer to PDU buffer (without trailer)
579 * trlr pointer to PDU trailer
586 sscop_bgrej_outrecov(sop, m, trlr)
594 * Stop retransmit timer
596 sop->so_timer[SSCOP_T_CC] = 0;
599 * Report protocol error
601 sscop_bgrej_error(sop, m, trlr);
604 * Notify user of connection failure
606 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
607 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
609 sscop_abort(sop, "stack memory\n");
614 * Clear receiver buffer
616 sscop_rcvr_drain(sop);
621 sop->so_state = SOS_IDLE;
628 * END PDU / SOS_OUTRECOV Processor
631 * sop pointer to sscop connection block
632 * m pointer to PDU buffer (without trailer)
633 * trlr pointer to PDU trailer
640 sscop_end_outrecov(sop, m, trlr)
645 struct end_pdu *ep = (struct end_pdu *)trlr;
649 * Stop retransmit timer
651 sop->so_timer[SSCOP_T_CC] = 0;
656 (void) sscop_send_endak(sop);
661 if (ep->end_type & PT_SOURCE_SSCOP)
662 source = SSCOP_SOURCE_SSCOP;
664 source = SSCOP_SOURCE_USER;
667 * Notify user of connection termination
669 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
670 sop->so_connvc, (int)m, source, err);
673 sscop_abort(sop, "stack memory\n");
678 * Clear receiver buffer
680 sscop_rcvr_drain(sop);
685 sop->so_state = SOS_IDLE;
692 * END PDU / SOS_READY Processor
695 * sop pointer to sscop connection block
696 * m pointer to PDU buffer (without trailer)
697 * trlr pointer to PDU trailer
704 sscop_end_ready(sop, m, trlr)
709 struct end_pdu *ep = (struct end_pdu *)trlr;
713 * Stop data transfer timers
715 sop->so_timer[SSCOP_T_POLL] = 0;
716 sop->so_timer[SSCOP_T_NORESP] = 0;
717 sop->so_timer[SSCOP_T_IDLE] = 0;
718 sop->so_flags &= ~SOF_KEEPALIVE;
723 (void) sscop_send_endak(sop);
728 if (ep->end_type & PT_SOURCE_SSCOP)
729 source = SSCOP_SOURCE_SSCOP;
731 source = SSCOP_SOURCE_USER;
734 * Notify user of connection termination
736 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
737 sop->so_connvc, (int)m, source, err);
740 sscop_abort(sop, "stack memory\n");
745 * Clear out appropriate queues
747 q2110_prep_retrieve(sop);
752 sop->so_state = SOS_IDLE;
759 * ENDAK PDU / SOS_OUTRECOV Processor
762 * sop pointer to sscop connection block
763 * m pointer to PDU buffer (without trailer)
764 * trlr pointer to PDU trailer
771 sscop_endak_outrecov(sop, m, trlr)
779 * Stop retransmit timer
781 sop->so_timer[SSCOP_T_CC] = 0;
784 * Report protocol error
786 sscop_endak_error(sop, m, trlr);
789 * Notify user of connection failure
791 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
792 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
794 sscop_abort(sop, "stack memory\n");
799 * Clear receiver buffer
801 sscop_rcvr_drain(sop);
806 sop->so_state = SOS_IDLE;
813 * RS PDU / SOS_OUTRESYN Processor
816 * sop pointer to sscop connection block
817 * m pointer to PDU buffer (without trailer)
818 * trlr pointer to PDU trailer
825 sscop_rs_outresyn(sop, m, trlr)
830 struct rs_pdu *rp = (struct rs_pdu *)trlr;
834 * If retransmitted RS, ignore it
836 if (sscop_is_rexmit(sop, rp->rs_nsq)) {
842 * Stop retransmit timer
844 sop->so_timer[SSCOP_T_CC] = 0;
847 * Initialize state variables
849 SEQ_SET(sop->so_sendmax, ntohl(rp->rs_nmr));
850 SEQ_SET(sop->so_rcvmax, sop->so_parm.sp_rcvwin);
851 q2110_init_state(sop);
859 * Return an ACK to peer
861 (void) sscop_send_rsak(sop);
864 * Notify user of connection resynchronization
866 STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku,
867 sop->so_connvc, 0, 0, err);
869 sscop_abort(sop, "stack memory\n");
874 * Start data transfer timers
876 sop->so_timer[SSCOP_T_POLL] = sop->so_parm.sp_timepoll;
877 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
880 * OK, we're ready for data
882 sop->so_state = SOS_READY;
885 * See if transmit queues need servicing
887 if (sop->so_flags & SOF_XMITSRVC)
888 sscop_service_xmit(sop);
895 * RS PDU / SOS_INRESYN Processor
898 * sop pointer to sscop connection block
899 * m pointer to PDU buffer (without trailer)
900 * trlr pointer to PDU trailer
907 sscop_rs_inresyn(sop, m, trlr)
912 struct rs_pdu *rp = (struct rs_pdu *)trlr;
915 * If retransmitted RS, ignore it
917 if (sscop_is_rexmit(sop, rp->rs_nsq)) {
923 * Report error condition
925 sscop_rs_error(sop, m, trlr);
932 * RS PDU / SOS_OUTRECOV Processor
935 * sop pointer to sscop connection block
936 * m pointer to PDU buffer (without trailer)
937 * trlr pointer to PDU trailer
944 sscop_rs_outrecov(sop, m, trlr)
949 struct rs_pdu *rp = (struct rs_pdu *)trlr;
953 * If retransmitted RS, report an error
955 if (sscop_is_rexmit(sop, rp->rs_nsq)) {
956 sscop_rs_error(sop, m, trlr);
961 * Stop retransmit timer
963 sop->so_timer[SSCOP_T_CC] = 0;
966 * Initialize transmit window
968 SEQ_SET(sop->so_sendmax, ntohl(rp->rs_nmr));
971 * Notify user of connection resynchronization
973 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
974 sop->so_connvc, (int)m, 0, err);
977 sscop_abort(sop, "stack memory\n");
982 * Clear receiver buffer
984 sscop_rcvr_drain(sop);
987 * Wait for user response
989 sop->so_state = SOS_INRESYN;
996 * RS PDU / SOS_READY Processor
999 * sop pointer to sscop connection block
1000 * m pointer to PDU buffer (without trailer)
1001 * trlr pointer to PDU trailer
1008 sscop_rs_ready(sop, m, trlr)
1013 struct rs_pdu *rp = (struct rs_pdu *)trlr;
1017 * If retransmitted RS, just ACK it
1019 if (sscop_is_rexmit(sop, rp->rs_nsq)) {
1021 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
1022 sscop_send_rsak(sop);
1027 * Stop data transfer timers
1029 sop->so_timer[SSCOP_T_POLL] = 0;
1030 sop->so_timer[SSCOP_T_NORESP] = 0;
1031 sop->so_timer[SSCOP_T_IDLE] = 0;
1032 sop->so_flags &= ~SOF_KEEPALIVE;
1035 * Initialize transmit window
1037 SEQ_SET(sop->so_sendmax, ntohl(rp->rs_nmr));
1040 * Notify user of connection resynchronization
1042 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
1043 sop->so_connvc, (int)m, 0, err);
1046 sscop_abort(sop, "stack memory\n");
1051 * Clear out appropriate queues
1053 q2110_prep_retrieve(sop);
1056 * Wait for user response
1058 sop->so_state = SOS_INRESYN;
1064 * ER PDU / Protocol Error
1067 * sop pointer to sscop connection block
1068 * m pointer to PDU buffer (without trailer)
1069 * trlr pointer to PDU trailer
1076 sscop_er_error(sop, m, trlr)
1083 * Record error condition
1085 sscop_maa_error(sop, 'L');
1093 * ER PDU / SOS_IDLE Processor
1096 * sop pointer to sscop connection block
1097 * m pointer to PDU buffer (without trailer)
1098 * trlr pointer to PDU trailer
1105 sscop_er_idle(sop, m, trlr)
1112 * Record error condition
1114 sscop_er_error(sop, m, trlr);
1117 * Return an END to peer
1119 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1126 * ER PDU / SOS_OUTRECOV Processor
1129 * sop pointer to sscop connection block
1130 * m pointer to PDU buffer (without trailer)
1131 * trlr pointer to PDU trailer
1138 sscop_er_outrecov(sop, m, trlr)
1143 struct er_pdu *ep = (struct er_pdu *)trlr;
1147 * If retransmitted ER, report an error
1149 if (sscop_is_rexmit(sop, ep->er_nsq)) {
1150 sscop_er_error(sop, m, trlr);
1155 * Stop retransmit timer
1157 sop->so_timer[SSCOP_T_CC] = 0;
1160 * Initialize transmit window
1162 SEQ_SET(sop->so_sendmax, ntohl(ep->er_nmr));
1165 * Initialize receiver window
1167 SEQ_SET(sop->so_rcvmax, sop->so_parm.sp_rcvwin);
1177 (void) sscop_send_erak(sop);
1180 * Deliver any outstanding data to user
1182 q2110_deliver_data(sop);
1185 * Notify user of connection recovery
1187 STACK_CALL(SSCOP_RECOVER_IND, sop->so_upper, sop->so_toku,
1188 sop->so_connvc, 0, 0, err);
1190 sscop_abort(sop, "stack memory\n");
1195 * Wait for user response
1197 sop->so_state = SOS_RECOVRSP;
1204 * ER PDU / SOS_RECOVRSP Processor
1207 * sop pointer to sscop connection block
1208 * m pointer to PDU buffer (without trailer)
1209 * trlr pointer to PDU trailer
1216 sscop_er_recovrsp(sop, m, trlr)
1221 struct er_pdu *ep = (struct er_pdu *)trlr;
1224 * If retransmitted ER, just ACK it
1226 if (sscop_is_rexmit(sop, ep->er_nsq)) {
1228 (void) sscop_send_erak(sop);
1233 * Report error condition
1235 sscop_er_error(sop, m, trlr);
1242 * ER PDU / SOS_INRECOV Processor
1245 * sop pointer to sscop connection block
1246 * m pointer to PDU buffer (without trailer)
1247 * trlr pointer to PDU trailer
1254 sscop_er_inrecov(sop, m, trlr)
1259 struct er_pdu *ep = (struct er_pdu *)trlr;
1262 * If retransmitted ER, just ignore it
1264 if (sscop_is_rexmit(sop, ep->er_nsq)) {
1270 * Report error condition
1272 sscop_er_error(sop, m, trlr);
1279 * ER PDU / SOS_READY Processor
1282 * sop pointer to sscop connection block
1283 * m pointer to PDU buffer (without trailer)
1284 * trlr pointer to PDU trailer
1291 sscop_er_ready(sop, m, trlr)
1296 struct er_pdu *ep = (struct er_pdu *)trlr;
1300 * If retransmitted ER, just ACK it
1302 if (sscop_is_rexmit(sop, ep->er_nsq)) {
1304 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
1305 sscop_send_erak(sop);
1310 * Stop data transfer timers
1312 sop->so_timer[SSCOP_T_POLL] = 0;
1313 sop->so_timer[SSCOP_T_NORESP] = 0;
1314 sop->so_timer[SSCOP_T_IDLE] = 0;
1315 sop->so_flags &= ~SOF_KEEPALIVE;
1318 * Initialize transmit window
1320 SEQ_SET(sop->so_sendmax, ntohl(ep->er_nmr));
1328 * Clear out appropriate queues
1330 q2110_prep_recovery(sop);
1333 * Deliver any outstanding data to user
1335 q2110_deliver_data(sop);
1338 * Notify user of connection recovery
1340 STACK_CALL(SSCOP_RECOVER_IND, sop->so_upper, sop->so_toku,
1341 sop->so_connvc, 0, 0, err);
1343 sscop_abort(sop, "stack memory\n");
1348 * Wait for user response
1350 sop->so_state = SOS_INRECOV;
1357 * ERAK PDU / Protocol Error
1360 * sop pointer to sscop connection block
1361 * m pointer to PDU buffer (without trailer)
1362 * trlr pointer to PDU trailer
1369 sscop_erak_error(sop, m, trlr)
1376 * Record error condition
1378 sscop_maa_error(sop, 'M');
1386 * ERAK PDU / SOS_IDLE Processor
1389 * sop pointer to sscop connection block
1390 * m pointer to PDU buffer (without trailer)
1391 * trlr pointer to PDU trailer
1398 sscop_erak_idle(sop, m, trlr)
1405 * Record error condition
1407 sscop_erak_error(sop, m, trlr);
1410 * Return an END to peer
1412 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1419 * ERAK PDU / SOS_OUTRECOV Processor
1422 * sop pointer to sscop connection block
1423 * m pointer to PDU buffer (without trailer)
1424 * trlr pointer to PDU trailer
1431 sscop_erak_outrecov(sop, m, trlr)
1436 struct erak_pdu *ep = (struct erak_pdu *)trlr;
1440 * Stop retransmit timer
1442 sop->so_timer[SSCOP_T_CC] = 0;
1445 * Initialize transmit window
1447 SEQ_SET(sop->so_sendmax, ntohl(ep->erak_nmr));
1455 * Deliver any outstanding data to user
1457 q2110_deliver_data(sop);
1460 * Notify user of connection recovery
1462 STACK_CALL(SSCOP_RECOVER_IND, sop->so_upper, sop->so_toku,
1463 sop->so_connvc, 0, 0, err);
1465 sscop_abort(sop, "stack memory\n");
1470 * Wait for user response
1472 sop->so_state = SOS_RECOVRSP;
1479 * SD PDU / SOS_READY Processor
1482 * sop pointer to sscop connection block
1483 * m pointer to PDU buffer (without trailer)
1484 * trlr pointer to PDU trailer
1491 sscop_sd_ready(sop, m, trlr)
1496 struct sd_pdu *sp = (struct sd_pdu *)trlr;
1497 struct pdu_hdr *php;
1503 * Get PDU sequence number
1505 SEQ_SET(ns, ntohl(sp->sd_ns));
1508 * Ensure that the sequence number fits within the window
1510 if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
1512 * It doesn't, drop received data
1517 * If next highest PDU hasn't reached window end yet,
1518 * then send a USTAT to inform transmitter of this gap
1520 if (SEQ_LT(sop->so_rcvhigh, sop->so_rcvmax, sop->so_rcvnext)) {
1521 (void) sscop_send_ustat(sop, sop->so_rcvmax);
1522 sop->so_rcvhigh = sop->so_rcvmax;
1528 * If this is the next in-sequence PDU, hand it to user
1530 if (ns == sop->so_rcvnext) {
1531 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1532 sop->so_connvc, (int)m, ns, err);
1539 * Bump next expected sequence number
1541 SEQ_INCR(sop->so_rcvnext, 1);
1544 * Slide receive window down
1546 SEQ_INCR(sop->so_rcvmax, 1);
1549 * Is this the highest sequence PDU we've received??
1551 if (ns == sop->so_rcvhigh) {
1553 * Yes, bump the limit and exit
1555 sop->so_rcvhigh = sop->so_rcvnext;
1560 * This is a retransmitted PDU, so see if we have
1561 * more in-sequence PDUs already queued up
1563 while ((php = sop->so_recv_hd) &&
1564 (php->ph_ns == sop->so_rcvnext)) {
1567 * Yup we do, so remove next PDU from queue and
1568 * pass it up to the user as well
1570 sop->so_recv_hd = php->ph_recv_lk;
1571 if (sop->so_recv_hd == NULL)
1572 sop->so_recv_tl = NULL;
1573 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1574 sop->so_connvc, (int)php->ph_buf, php->ph_ns,
1578 * Should never happen, but...
1580 KB_FREEALL(php->ph_buf);
1581 sscop_abort(sop, "stack memory\n");
1586 * Bump next expected sequence number
1588 SEQ_INCR(sop->so_rcvnext, 1);
1591 * Slide receive window down
1593 SEQ_INCR(sop->so_rcvmax, 1);
1597 * Finished with data delivery...
1603 * We're gonna have to queue this PDU, so find space
1604 * for the PDU header
1606 KB_HEADROOM(m, space);
1609 * If there's not enough room in the received buffer,
1610 * allocate & link a new buffer for the header
1612 if (space < sizeof(struct pdu_hdr)) {
1614 KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
1619 KB_HEADSET(n, sizeof(struct pdu_hdr));
1628 * We can at least assume/require that the start of
1629 * the user data is aligned. Also note that we don't
1630 * include this header in the buffer len/offset fields.
1632 KB_DATASTART(m, php, struct pdu_hdr *);
1638 * Insert PDU into the receive queue
1640 if (sscop_recv_insert(sop, php)) {
1642 * Oops, a duplicate sequence number PDU is already on
1643 * the queue, somethings wrong here.
1645 sscop_maa_error(sop, 'Q');
1653 * Go into recovery mode
1655 q2110_error_recovery(sop);
1661 * Are we at the high-water mark??
1663 if (ns == sop->so_rcvhigh) {
1665 * Yes, just bump the mark
1667 SEQ_INCR(sop->so_rcvhigh, 1);
1673 * Are we beyond the high-water mark??
1675 if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1677 * Yes, then there's a missing PDU, so inform the transmitter
1679 (void) sscop_send_ustat(sop, ns);
1682 * Update high-water mark
1684 sop->so_rcvhigh = SEQ_ADD(ns, 1);
1692 * POLL PDU / SOS_READY Processor
1695 * sop pointer to sscop connection block
1696 * m pointer to PDU buffer (without trailer)
1697 * trlr pointer to PDU trailer
1704 sscop_poll_ready(sop, m, trlr)
1709 struct poll_pdu *pp = (struct poll_pdu *)trlr;
1712 pp->poll_ns = ntohl(pp->poll_ns);
1715 * If the poll sequence number is less than highest number
1716 * we've already seen, something's wrong
1718 if (SEQ_LT(pp->poll_ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1720 * Record error condition
1722 sscop_maa_error(sop, 'Q');
1730 * Go into recovery mode
1732 q2110_error_recovery(sop);
1738 * Set a new "next highest" sequence number expected
1740 if (SEQ_LT(pp->poll_ns, sop->so_rcvmax, sop->so_rcvnext))
1741 SEQ_SET(sop->so_rcvhigh, pp->poll_ns);
1743 sop->so_rcvhigh = sop->so_rcvmax;
1746 * Return a STAT PDU to peer
1748 SEQ_SET(nps, ntohl(pp->poll_nps));
1750 (void) sscop_send_stat(sop, nps);