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/qsaal1_sigcpcs.c,v 1.4 2000/01/17 20:49:49 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/qsaal1_sigcpcs.c,v 1.7 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * ITU-T Q.SAAL1 - 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_end_outresyn (struct sscop *, KBuffer *, caddr_t);
50 static void sscop_end_conresyn (struct sscop *, KBuffer *, caddr_t);
51 static void sscop_end_ready (struct sscop *, KBuffer *, caddr_t);
52 static void sscop_endak_outresyn (struct sscop *, KBuffer *, caddr_t);
53 static void sscop_rs_outresyn (struct sscop *, KBuffer *, caddr_t);
54 static void sscop_rs_ready (struct sscop *, KBuffer *, caddr_t);
55 static void sscop_rsak_conresyn (struct sscop *, KBuffer *, caddr_t);
56 static void sscop_sd_inresyn (struct sscop *, KBuffer *, caddr_t);
57 static void sscop_sd_conresyn (struct sscop *, KBuffer *, caddr_t);
58 static void sscop_sd_process (struct sscop *, KBuffer *, caddr_t, int);
59 static void sscop_sd_ready (struct sscop *, KBuffer *, caddr_t);
60 static void sscop_sdp_ready (struct sscop *, KBuffer *, caddr_t);
61 static void sscop_poll_inresyn (struct sscop *, KBuffer *, caddr_t);
62 static void sscop_poll_conresyn (struct sscop *, KBuffer *, caddr_t);
63 static void sscop_poll_ready (struct sscop *, KBuffer *, caddr_t);
64 static void sscop_stat_conresyn (struct sscop *, KBuffer *, caddr_t);
65 static void sscop_ustat_conresyn (struct sscop *, KBuffer *, caddr_t);
69 * PDU type state lookup tables
72 static void (*sscop_bgn_tab[SOS_NUMSTATES])
73 (struct sscop *, KBuffer *, caddr_t) = {
75 sscop_bgn_idle, /* SOS_IDLE */
76 sscop_bgn_outconn, /* SOS_OUTCONN */
77 sscop_noop, /* SOS_INCONN */
78 sscop_bgn_outdisc, /* SOS_OUTDISC */
79 sscop_bgn_outresyn, /* SOS_OUTRESYN */
80 sscop_bgn_inresyn, /* SOS_INRESYN */
81 sscop_bgn_outresyn, /* SOS_CONRESYN */
84 sscop_bgn_inresyn, /* SOS_READY */
85 sscop_noop /* SOS_TERM */
89 static void (*sscop_bgak_tab[SOS_NUMSTATES])
90 (struct sscop *, KBuffer *, caddr_t) = {
92 sscop_bgak_idle, /* SOS_IDLE */
93 sscop_bgak_outconn, /* SOS_OUTCONN */
94 sscop_bgak_error, /* SOS_INCONN */
95 sscop_noop, /* SOS_OUTDISC */
96 sscop_bgak_error, /* SOS_OUTRESYN */
97 sscop_bgak_error, /* SOS_INRESYN */
98 sscop_bgak_error, /* SOS_CONRESYN */
101 sscop_noop, /* SOS_READY */
102 sscop_noop /* SOS_TERM */
106 static void (*sscop_bgrej_tab[SOS_NUMSTATES])
107 (struct sscop *, KBuffer *, caddr_t) = {
109 sscop_bgrej_error, /* SOS_IDLE */
110 sscop_bgrej_outconn, /* SOS_OUTCONN */
111 sscop_bgrej_inconn, /* SOS_INCONN */
112 sscop_noop, /* SOS_OUTDISC */
113 sscop_bgrej_outresyn, /* SOS_OUTRESYN */
114 sscop_bgrej_ready, /* SOS_INRESYN */
115 sscop_bgrej_outresyn, /* SOS_CONRESYN */
118 sscop_bgrej_ready, /* SOS_READY */
119 sscop_noop /* SOS_TERM */
123 static void (*sscop_end_tab[SOS_NUMSTATES])
124 (struct sscop *, KBuffer *, caddr_t) = {
126 sscop_end_idle, /* SOS_IDLE */
127 sscop_noop, /* SOS_OUTCONN */
128 sscop_end_inconn, /* SOS_INCONN */
129 sscop_end_outdisc, /* SOS_OUTDISC */
130 sscop_end_outresyn, /* SOS_OUTRESYN */
131 sscop_end_ready, /* SOS_INRESYN */
132 sscop_end_conresyn, /* SOS_CONRESYN */
135 sscop_end_ready, /* SOS_READY */
136 sscop_noop /* SOS_TERM */
140 static void (*sscop_endak_tab[SOS_NUMSTATES])
141 (struct sscop *, KBuffer *, caddr_t) = {
143 sscop_noop, /* SOS_IDLE */
144 sscop_noop, /* SOS_OUTCONN */
145 sscop_endak_inconn, /* SOS_INCONN */
146 sscop_endak_outdisc, /* SOS_OUTDISC */
147 sscop_endak_outresyn, /* SOS_OUTRESYN */
148 sscop_endak_ready, /* SOS_INRESYN */
149 sscop_endak_outresyn, /* SOS_CONRESYN */
152 sscop_endak_ready, /* SOS_READY */
153 sscop_noop /* SOS_TERM */
157 static void (*sscop_rs_tab[SOS_NUMSTATES])
158 (struct sscop *, KBuffer *, caddr_t) = {
160 sscop_rs_idle, /* SOS_IDLE */
161 sscop_noop, /* SOS_OUTCONN */
162 sscop_rs_error, /* SOS_INCONN */
163 sscop_noop, /* SOS_OUTDISC */
164 sscop_rs_outresyn, /* SOS_OUTRESYN */
165 sscop_noop, /* SOS_INRESYN */
166 sscop_noop, /* SOS_CONRESYN */
169 sscop_rs_ready, /* SOS_READY */
170 sscop_noop /* SOS_TERM */
174 static void (*sscop_rsak_tab[SOS_NUMSTATES])
175 (struct sscop *, KBuffer *, caddr_t) = {
177 sscop_rsak_idle, /* SOS_IDLE */
178 sscop_noop, /* SOS_OUTCONN */
179 sscop_rsak_error, /* SOS_INCONN */
180 sscop_noop, /* SOS_OUTDISC */
181 sscop_rsak_outresyn, /* SOS_OUTRESYN */
182 sscop_rsak_error, /* SOS_INRESYN */
183 sscop_rsak_conresyn, /* SOS_CONRESYN */
186 sscop_rsak_error, /* SOS_READY */
187 sscop_noop /* SOS_TERM */
191 static void (*sscop_sd_tab[SOS_NUMSTATES])
192 (struct sscop *, KBuffer *, caddr_t) = {
194 sscop_sd_idle, /* SOS_IDLE */
195 sscop_noop, /* SOS_OUTCONN */
196 sscop_sd_inconn, /* SOS_INCONN */
197 sscop_noop, /* SOS_OUTDISC */
198 sscop_sd_ready, /* SOS_OUTRESYN */
199 sscop_sd_inresyn, /* SOS_INRESYN */
200 sscop_sd_conresyn, /* SOS_CONRESYN */
203 sscop_sd_ready, /* SOS_READY */
204 sscop_noop /* SOS_TERM */
208 static void (*sscop_sdp_tab[SOS_NUMSTATES])
209 (struct sscop *, KBuffer *, caddr_t) = {
211 sscop_sd_idle, /* SOS_IDLE */
212 sscop_noop, /* SOS_OUTCONN */
213 sscop_sd_inconn, /* SOS_INCONN */
214 sscop_noop, /* SOS_OUTDISC */
215 sscop_sdp_ready, /* SOS_OUTRESYN */
216 sscop_sd_inresyn, /* SOS_INRESYN */
217 sscop_sd_conresyn, /* SOS_CONRESYN */
220 sscop_sdp_ready, /* SOS_READY */
221 sscop_noop /* SOS_TERM */
225 static void (*sscop_poll_tab[SOS_NUMSTATES])
226 (struct sscop *, KBuffer *, caddr_t) = {
228 sscop_poll_idle, /* SOS_IDLE */
229 sscop_noop, /* SOS_OUTCONN */
230 sscop_poll_inconn, /* SOS_INCONN */
231 sscop_noop, /* SOS_OUTDISC */
232 sscop_poll_ready, /* SOS_OUTRESYN */
233 sscop_poll_inresyn, /* SOS_INRESYN */
234 sscop_poll_conresyn, /* SOS_CONRESYN */
237 sscop_poll_ready, /* SOS_READY */
238 sscop_noop /* SOS_TERM */
242 static void (*sscop_stat_tab[SOS_NUMSTATES])
243 (struct sscop *, KBuffer *, caddr_t) = {
245 sscop_stat_idle, /* SOS_IDLE */
246 sscop_noop, /* SOS_OUTCONN */
247 sscop_stat_inconn, /* SOS_INCONN */
248 sscop_noop, /* SOS_OUTDISC */
249 sscop_noop, /* SOS_OUTRESYN */
250 sscop_stat_ready, /* SOS_INRESYN */
251 sscop_stat_conresyn, /* SOS_CONRESYN */
254 sscop_stat_ready, /* SOS_READY */
255 sscop_noop /* SOS_TERM */
259 static void (*sscop_ustat_tab[SOS_NUMSTATES])
260 (struct sscop *, KBuffer *, caddr_t) = {
262 sscop_ustat_idle, /* SOS_IDLE */
263 sscop_noop, /* SOS_OUTCONN */
264 sscop_ustat_inconn, /* SOS_INCONN */
265 sscop_noop, /* SOS_OUTDISC */
266 sscop_noop, /* SOS_OUTRESYN */
267 sscop_ustat_ready, /* SOS_INRESYN */
268 sscop_ustat_conresyn, /* SOS_CONRESYN */
271 sscop_ustat_ready, /* SOS_READY */
272 sscop_noop /* SOS_TERM */
276 static void (*sscop_ud_tab[SOS_NUMSTATES])
277 (struct sscop *, KBuffer *, caddr_t) = {
279 sscop_ud_all, /* SOS_IDLE */
280 sscop_ud_all, /* SOS_OUTCONN */
281 sscop_ud_all, /* SOS_INCONN */
282 sscop_ud_all, /* SOS_OUTDISC */
283 sscop_ud_all, /* SOS_OUTRESYN */
284 sscop_ud_all, /* SOS_INRESYN */
285 sscop_ud_all, /* SOS_CONRESYN */
288 sscop_ud_all, /* SOS_READY */
289 sscop_noop /* SOS_TERM */
293 static void (*sscop_md_tab[SOS_NUMSTATES])
294 (struct sscop *, KBuffer *, caddr_t) = {
296 sscop_md_all, /* SOS_IDLE */
297 sscop_md_all, /* SOS_OUTCONN */
298 sscop_md_all, /* SOS_INCONN */
299 sscop_md_all, /* SOS_OUTDISC */
300 sscop_md_all, /* SOS_OUTRESYN */
301 sscop_md_all, /* SOS_INRESYN */
302 sscop_md_all, /* SOS_CONRESYN */
305 sscop_md_all, /* SOS_READY */
306 sscop_noop /* SOS_TERM */
311 * PDU type lookup table
313 void (*(*sscop_qsaal_pdutab[]))
314 (struct sscop *, KBuffer *, caddr_t) = {
335 * BGN PDU / SOS_OUTCONN Processor
338 * sop pointer to sscop connection block
339 * m pointer to PDU buffer (without trailer)
340 * trlr pointer to PDU trailer
347 sscop_bgn_outconn(struct sscop *sop, KBuffer *m, caddr_t trlr)
349 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
353 * Initialize transmit window
355 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
358 * Notify user of connection establishment
360 if (sop->so_flags & SOF_REESTAB) {
362 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
363 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
365 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
368 sop->so_flags &= ~SOF_REESTAB;
370 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku,
371 sop->so_connvc, (int)m, 0, err);
374 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
380 * Return an ACK to peer
382 sscop_send_bgak(sop);
385 * Stop retransmit timer
387 sop->so_timer[SSCOP_T_CC] = 0;
390 * Reset receiver variables
392 qsaal1_reset_rcvr(sop);
395 * Start polling timer
400 * Start lost poll/stat timer
402 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
405 * OK, we're ready for data
407 sop->so_state = SOS_READY;
410 * See if transmit queues need servicing
412 if (sop->so_flags & SOF_XMITSRVC)
413 sscop_service_xmit(sop);
420 * END PDU / SOS_OUTRESYN Processor
423 * sop pointer to sscop connection block
424 * m pointer to PDU buffer (without trailer)
425 * trlr pointer to PDU trailer
432 sscop_end_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
434 struct end_pdu *ep = (struct end_pdu *)trlr;
438 * Stop retransmit timer
440 sop->so_timer[SSCOP_T_CC] = 0;
445 sscop_send_endak(sop);
450 if (ep->end_type & PT_SOURCE_SSCOP)
451 source = SSCOP_SOURCE_SSCOP;
453 source = SSCOP_SOURCE_USER;
456 * Notify user of connection termination
458 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
459 sop->so_connvc, (int)m, source, err);
462 sscop_abort(sop, "sscop_end_outresyn: stack memory\n");
467 * Clear connection data
469 qsaal1_clear_connection(sop);
474 sop->so_state = SOS_IDLE;
481 * END PDU / SOS_CONRESYN Processor
484 * sop pointer to sscop connection block
485 * m pointer to PDU buffer (without trailer)
486 * trlr pointer to PDU trailer
493 sscop_end_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
498 * Stop retransmit timer
500 sop->so_timer[SSCOP_T_CC] = 0;
510 sscop_send_endak(sop);
513 * Notify user of connection termination
515 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
516 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
518 sscop_abort(sop, "sscop_end_conresyn: stack memory\n");
523 * Clear connection data
525 qsaal1_clear_connection(sop);
530 sop->so_state = SOS_IDLE;
537 * END PDU / SOS_READY Processor
540 * sop pointer to sscop connection block
541 * m pointer to PDU buffer (without trailer)
542 * trlr pointer to PDU trailer
549 sscop_end_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
551 struct end_pdu *ep = (struct end_pdu *)trlr;
557 sop->so_timer[SSCOP_T_POLL] = 0;
558 sop->so_flags &= ~SOF_KEEPALIVE;
561 * Stop lost poll/stat timer
563 sop->so_timer[SSCOP_T_NORESP] = 0;
568 sscop_send_endak(sop);
573 if (ep->end_type & PT_SOURCE_SSCOP)
574 source = SSCOP_SOURCE_SSCOP;
576 source = SSCOP_SOURCE_USER;
579 * Notify user of connection termination
581 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
582 sop->so_connvc, (int)m, source, err);
585 sscop_abort(sop, "sscop_end_ready: stack memory\n");
590 * Clear connection data
592 qsaal1_clear_connection(sop);
597 sop->so_state = SOS_IDLE;
604 * ENDAK PDU / SOS_OUTRESYN Processor
607 * sop pointer to sscop connection block
608 * m pointer to PDU buffer (without trailer)
609 * trlr pointer to PDU trailer
616 sscop_endak_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
621 * Stop retransmit timer
623 sop->so_timer[SSCOP_T_CC] = 0;
626 * Report protocol error
628 sscop_endak_error(sop, m, trlr);
631 * Notify user of connection failure
633 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
634 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
636 sscop_abort(sop, "sscop_endak_outresyn: stack memory\n");
641 * Clear connection data
643 qsaal1_clear_connection(sop);
648 sop->so_state = SOS_IDLE;
655 * RS PDU / SOS_OUTRESYN Processor
658 * sop pointer to sscop connection block
659 * m pointer to PDU buffer (without trailer)
660 * trlr pointer to PDU trailer
667 sscop_rs_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
672 * Notify user of resynchronization
674 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
675 sop->so_connvc, (int)m, 0, err);
678 sscop_abort(sop, "sscop_rs_outresyn: stack memory\n");
683 * Reset receiver state variables
685 qsaal1_reset_rcvr(sop);
688 * Wait for both peer and user responses
690 sop->so_state = SOS_CONRESYN;
697 * RS PDU / SOS_READY Processor
700 * sop pointer to sscop connection block
701 * m pointer to PDU buffer (without trailer)
702 * trlr pointer to PDU trailer
709 sscop_rs_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
714 * Notify user of resynchronization
716 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
717 sop->so_connvc, (int)m, 0, err);
720 sscop_abort(sop, "sscop_rs_ready: stack memory\n");
725 * Reset receiver state variables
727 qsaal1_reset_rcvr(sop);
730 * Wait for user response
732 sop->so_state = SOS_INRESYN;
739 * RSAK PDU / SOS_CONRESYN Processor
742 * sop pointer to sscop connection block
743 * m pointer to PDU buffer (without trailer)
744 * trlr pointer to PDU trailer
751 sscop_rsak_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
756 * Stop retransmit timer
758 sop->so_timer[SSCOP_T_CC] = 0;
766 * Notify user of resynchronization completion
768 STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku,
769 sop->so_connvc, 0, 0, err);
771 sscop_abort(sop, "sscop_rsak_conresyn: stack memory\n");
776 * Start the polling timer
781 * Start lost poll/stat timer
783 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
786 * Continue waiting for user response
788 sop->so_state = SOS_INRESYN;
791 * See if transmit queues need servicing
793 if (sop->so_flags & SOF_XMITSRVC)
794 sscop_service_xmit(sop);
801 * SD PDU / SOS_INRESYN Processor
804 * sop pointer to sscop connection block
805 * m pointer to PDU buffer (without trailer)
806 * trlr pointer to PDU trailer
813 sscop_sd_inresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
820 sop->so_timer[SSCOP_T_POLL] = 0;
821 sop->so_flags &= ~SOF_KEEPALIVE;
824 * Stop lost poll/stat timer
826 sop->so_timer[SSCOP_T_NORESP] = 0;
829 * Record error condition
831 sscop_sd_error(sop, m, trlr);
834 * Return an END to peer
836 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
839 * Notify user of connection failure
841 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
842 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
844 sscop_abort(sop, "sscop_sd_inresyn: stack memory\n");
849 * Clear connection data
851 qsaal1_clear_connection(sop);
854 * Go back to idle state
856 sop->so_state = SOS_IDLE;
863 * SD PDU / SOS_CONRESYN Processor
866 * sop pointer to sscop connection block
867 * m pointer to PDU buffer (without trailer)
868 * trlr pointer to PDU trailer
875 sscop_sd_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
880 * Stop retransmit timer
882 sop->so_timer[SSCOP_T_CC] = 0;
885 * Record error condition
887 sscop_sd_error(sop, m, trlr);
890 * Return an END to peer
892 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
895 * Notify user of connection failure
897 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
898 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
900 sscop_abort(sop, "sscop_sd_conresyn: stack memory\n");
905 * Clear connection data
907 qsaal1_clear_connection(sop);
910 * Go back to idle state
912 sop->so_state = SOS_IDLE;
919 * SD/SDP PDU Common Processor
922 * sop pointer to sscop connection block
923 * m pointer to PDU user data buffer chain
924 * trlr pointer to PDU trailer
925 * type PDU type (SD or SDP)
932 sscop_sd_process(struct sscop *sop, KBuffer *m, caddr_t trlr, int type)
936 struct poll_pdu poll;
943 * Get PDU sequence number(s)
946 sp = (struct sd_pdu *)trlr;
947 SEQ_SET(ns, ntohl(sp->sd_ns));
950 spp = (struct sdp_pdu *)trlr;
951 SEQ_SET(ns, ntohl(spp->sdp_ns));
952 SEQ_SET(nps, ntohl(spp->sdp_nps));
956 * Ensure that the sequence number fits within the window
958 if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
964 * If this is the next in-sequence PDU, hand it to user
966 if (ns == sop->so_rcvnext) {
967 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
968 sop->so_connvc, (int)m, ns, err);
975 * Bump next expected sequence number
977 SEQ_INCR(sop->so_rcvnext, 1);
980 * Slide receive window down
982 SEQ_INCR(sop->so_rcvmax, 1);
985 * Is this the highest sequence PDU we've received??
987 if (ns == sop->so_rcvhigh) {
989 * Yes, bump the limit and exit
991 sop->so_rcvhigh = sop->so_rcvnext;
998 * This is a retransmitted PDU, so see if we have
999 * more in-sequence PDUs already queued up
1001 while ((php = sop->so_recv_hd) &&
1002 (php->ph_ns == sop->so_rcvnext)) {
1005 * Yup we do, so remove next PDU from queue and
1006 * pass it up to the user as well
1008 sop->so_recv_hd = php->ph_recv_lk;
1009 if (sop->so_recv_hd == NULL)
1010 sop->so_recv_tl = NULL;
1011 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1012 sop->so_connvc, (int)php->ph_buf, php->ph_ns,
1016 * Should never happen, but...
1018 KB_FREEALL(php->ph_buf);
1020 "sscop_sd_process: stack memory\n");
1025 * Bump next expected sequence number
1027 SEQ_INCR(sop->so_rcvnext, 1);
1030 * Slide receive window down
1032 SEQ_INCR(sop->so_rcvmax, 1);
1036 * Finished with data...see if we need to poll
1044 * We're gonna have to queue this PDU, so find space
1045 * for the PDU header
1047 KB_HEADROOM(m, space);
1050 * If there's not enough room in the received buffer,
1051 * allocate & link a new buffer for the header
1053 if (space < sizeof(struct pdu_hdr)) {
1055 KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
1060 KB_HEADSET(n, sizeof(struct pdu_hdr));
1069 * We can at least assume/require that the start of
1070 * the user data is aligned. Also note that we don't
1071 * include this header in the buffer len/offset fields.
1073 KB_DATASTART(m, php, struct pdu_hdr *);
1079 * Insert PDU into the receive queue
1081 if (sscop_recv_insert(sop, php)) {
1083 * Oops, a duplicate sequence number PDU is already on
1084 * the queue, somethings wrong here.
1086 sscop_maa_error(sop, 'Q');
1094 * Reestablish a new connection
1096 qsaal1_reestablish(sop);
1102 * Are we at the high-water mark??
1104 if (ns == sop->so_rcvhigh) {
1106 * Yes, just bump the mark
1108 SEQ_INCR(sop->so_rcvhigh, 1);
1116 * Are we beyond the high-water mark??
1118 if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1120 * Yes, then there's a missing PDU, so inform the transmitter
1123 sscop_send_ustat(sop, ns);
1126 * Update high-water mark
1128 sop->so_rcvhigh = SEQ_ADD(ns, 1);
1136 * Do the "poll" part of an SDP PDU
1138 poll.poll_nps = htonl(nps);
1139 poll.poll_ns = htonl((PT_POLL << PT_TYPE_SHIFT) | ns);
1140 sscop_poll_ready(sop, NULL, (caddr_t)&poll);
1146 * SD PDU / SOS_READY Processor
1149 * sop pointer to sscop connection block
1150 * m pointer to PDU buffer (without trailer)
1151 * trlr pointer to PDU trailer
1158 sscop_sd_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1161 * Just call common SD/SDP processor
1163 sscop_sd_process(sop, m, trlr, PT_SD);
1170 * SDP PDU / SOS_READY Processor
1173 * sop pointer to sscop connection block
1174 * m pointer to PDU buffer (without trailer)
1175 * trlr pointer to PDU trailer
1182 sscop_sdp_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1185 * Just call common SD/SDP processor
1187 sscop_sd_process(sop, m, trlr, PT_SDP);
1194 * POLL PDU / SOS_INRESYN Processor
1197 * sop pointer to sscop connection block
1198 * m pointer to PDU buffer (without trailer)
1199 * trlr pointer to PDU trailer
1206 sscop_poll_inresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1213 sop->so_timer[SSCOP_T_POLL] = 0;
1214 sop->so_flags &= ~SOF_KEEPALIVE;
1217 * Stop lost poll/stat timer
1219 sop->so_timer[SSCOP_T_NORESP] = 0;
1222 * Report protocol error
1224 sscop_poll_error(sop, m, trlr);
1227 * Return an END to peer
1229 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1232 * Notify user of connection failure
1234 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1235 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1237 sscop_abort(sop, "sscop_poll_inresyn: stack memory\n");
1242 * Clear connection data
1244 qsaal1_clear_connection(sop);
1247 * Back to idle state
1249 sop->so_state = SOS_IDLE;
1256 * POLL PDU / SOS_CONRESYN Processor
1259 * sop pointer to sscop connection block
1260 * m pointer to PDU buffer (without trailer)
1261 * trlr pointer to PDU trailer
1268 sscop_poll_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1273 * Stop retransmit timer
1275 sop->so_timer[SSCOP_T_CC] = 0;
1278 * Record error condition
1280 sscop_poll_error(sop, m, trlr);
1283 * Return an END to peer
1285 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1288 * Notify user of connection failure
1290 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1291 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1293 sscop_abort(sop, "sscop_poll_conresyn: stack memory\n");
1298 * Clear connection data
1300 qsaal1_clear_connection(sop);
1303 * Go back to idle state
1305 sop->so_state = SOS_IDLE;
1312 * POLL PDU / SOS_READY Processor
1315 * sop pointer to sscop connection block
1316 * m pointer to PDU buffer (without trailer)
1317 * trlr pointer to PDU trailer
1324 sscop_poll_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1326 struct poll_pdu *pp = (struct poll_pdu *)trlr;
1329 pp->poll_ns = ntohl(pp->poll_ns);
1332 * If the poll sequence number is less than highest number
1333 * we've already seen, something's wrong - so attempt to
1334 * reestablish a new connection.
1336 if (SEQ_LT(pp->poll_ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1338 * Record error condition
1340 sscop_maa_error(sop, 'Q');
1348 * Reestablish a new connection
1350 qsaal1_reestablish(sop);
1356 * Set a new "next highest" sequence number expected
1358 if (SEQ_LT(pp->poll_ns, sop->so_rcvmax, sop->so_rcvnext))
1359 SEQ_SET(sop->so_rcvhigh, pp->poll_ns);
1361 sop->so_rcvhigh = sop->so_rcvmax;
1364 * Return a STAT PDU to peer
1366 SEQ_SET(nps, ntohl(pp->poll_nps));
1368 sscop_send_stat(sop, nps);
1375 * STAT PDU / SOS_CONRESYN Processor
1378 * sop pointer to sscop connection block
1379 * m pointer to PDU buffer (without trailer)
1380 * trlr pointer to PDU trailer
1387 sscop_stat_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1392 * Stop retransmit timer
1394 sop->so_timer[SSCOP_T_CC] = 0;
1397 * Record error condition
1399 sscop_stat_error(sop, m, trlr);
1402 * Return an END to peer
1404 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1407 * Notify user of connection failure
1409 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1410 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1412 sscop_abort(sop, "sscop_stat_conresyn: stack memory\n");
1417 * Clear connection data
1419 qsaal1_clear_connection(sop);
1422 * Go back to idle state
1424 sop->so_state = SOS_IDLE;
1431 * USTAT PDU / SOS_CONRESYN Processor
1434 * sop pointer to sscop connection block
1435 * m pointer to PDU buffer (without trailer)
1436 * trlr pointer to PDU trailer
1443 sscop_ustat_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1448 * Stop retransmit timer
1450 sop->so_timer[SSCOP_T_CC] = 0;
1453 * Record error condition
1455 sscop_ustat_error(sop, m, trlr);
1458 * Return an END to peer
1460 sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1463 * Notify user of connection failure
1465 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1466 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1468 sscop_abort(sop, "sscop_ustat_conresyn: stack memory\n");
1473 * Clear connection data
1475 qsaal1_clear_connection(sop);
1478 * Go back to idle state
1480 sop->so_state = SOS_IDLE;