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.2 2003/06/17 04:28:49 dillon Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * ITU-T Q.SAAL1 - Process CPCS-signals (SSCOP PDUs)
38 #include <netatm/kern_include.h>
40 #include <netatm/uni/sscop.h>
41 #include <netatm/uni/sscop_misc.h>
42 #include <netatm/uni/sscop_pdu.h>
43 #include <netatm/uni/sscop_var.h>
48 static void sscop_bgn_outconn __P((struct sscop *, KBuffer *, caddr_t));
49 static void sscop_end_outresyn __P((struct sscop *, KBuffer *, caddr_t));
50 static void sscop_end_conresyn __P((struct sscop *, KBuffer *, caddr_t));
51 static void sscop_end_ready __P((struct sscop *, KBuffer *, caddr_t));
52 static void sscop_endak_outresyn __P((struct sscop *, KBuffer *, caddr_t));
53 static void sscop_rs_outresyn __P((struct sscop *, KBuffer *, caddr_t));
54 static void sscop_rs_ready __P((struct sscop *, KBuffer *, caddr_t));
55 static void sscop_rsak_conresyn __P((struct sscop *, KBuffer *, caddr_t));
56 static void sscop_sd_inresyn __P((struct sscop *, KBuffer *, caddr_t));
57 static void sscop_sd_conresyn __P((struct sscop *, KBuffer *, caddr_t));
58 static void sscop_sd_process __P((struct sscop *, KBuffer *, caddr_t, int));
59 static void sscop_sd_ready __P((struct sscop *, KBuffer *, caddr_t));
60 static void sscop_sdp_ready __P((struct sscop *, KBuffer *, caddr_t));
61 static void sscop_poll_inresyn __P((struct sscop *, KBuffer *, caddr_t));
62 static void sscop_poll_conresyn __P((struct sscop *, KBuffer *, caddr_t));
63 static void sscop_poll_ready __P((struct sscop *, KBuffer *, caddr_t));
64 static void sscop_stat_conresyn __P((struct sscop *, KBuffer *, caddr_t));
65 static void sscop_ustat_conresyn __P((struct sscop *, KBuffer *, caddr_t));
69 * PDU type state lookup tables
72 static void (*sscop_bgn_tab[SOS_NUMSTATES])
73 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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 __P((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(sop, m, trlr)
352 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
356 * Initialize transmit window
358 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
361 * Notify user of connection establishment
363 if (sop->so_flags & SOF_REESTAB) {
365 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
366 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
368 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
371 sop->so_flags &= ~SOF_REESTAB;
373 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku,
374 sop->so_connvc, (int)m, 0, err);
377 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
383 * Return an ACK to peer
385 (void) sscop_send_bgak(sop);
388 * Stop retransmit timer
390 sop->so_timer[SSCOP_T_CC] = 0;
393 * Reset receiver variables
395 qsaal1_reset_rcvr(sop);
398 * Start polling timer
403 * Start lost poll/stat timer
405 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
408 * OK, we're ready for data
410 sop->so_state = SOS_READY;
413 * See if transmit queues need servicing
415 if (sop->so_flags & SOF_XMITSRVC)
416 sscop_service_xmit(sop);
423 * END PDU / SOS_OUTRESYN Processor
426 * sop pointer to sscop connection block
427 * m pointer to PDU buffer (without trailer)
428 * trlr pointer to PDU trailer
435 sscop_end_outresyn(sop, m, trlr)
440 struct end_pdu *ep = (struct end_pdu *)trlr;
444 * Stop retransmit timer
446 sop->so_timer[SSCOP_T_CC] = 0;
451 (void) sscop_send_endak(sop);
456 if (ep->end_type & PT_SOURCE_SSCOP)
457 source = SSCOP_SOURCE_SSCOP;
459 source = SSCOP_SOURCE_USER;
462 * Notify user of connection termination
464 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
465 sop->so_connvc, (int)m, source, err);
468 sscop_abort(sop, "sscop_end_outresyn: stack memory\n");
473 * Clear connection data
475 qsaal1_clear_connection(sop);
480 sop->so_state = SOS_IDLE;
487 * END PDU / SOS_CONRESYN Processor
490 * sop pointer to sscop connection block
491 * m pointer to PDU buffer (without trailer)
492 * trlr pointer to PDU trailer
499 sscop_end_conresyn(sop, m, trlr)
507 * Stop retransmit timer
509 sop->so_timer[SSCOP_T_CC] = 0;
519 (void) sscop_send_endak(sop);
522 * Notify user of connection termination
524 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
525 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
527 sscop_abort(sop, "sscop_end_conresyn: stack memory\n");
532 * Clear connection data
534 qsaal1_clear_connection(sop);
539 sop->so_state = SOS_IDLE;
546 * END PDU / SOS_READY Processor
549 * sop pointer to sscop connection block
550 * m pointer to PDU buffer (without trailer)
551 * trlr pointer to PDU trailer
558 sscop_end_ready(sop, m, trlr)
563 struct end_pdu *ep = (struct end_pdu *)trlr;
569 sop->so_timer[SSCOP_T_POLL] = 0;
570 sop->so_flags &= ~SOF_KEEPALIVE;
573 * Stop lost poll/stat timer
575 sop->so_timer[SSCOP_T_NORESP] = 0;
580 (void) sscop_send_endak(sop);
585 if (ep->end_type & PT_SOURCE_SSCOP)
586 source = SSCOP_SOURCE_SSCOP;
588 source = SSCOP_SOURCE_USER;
591 * Notify user of connection termination
593 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
594 sop->so_connvc, (int)m, source, err);
597 sscop_abort(sop, "sscop_end_ready: stack memory\n");
602 * Clear connection data
604 qsaal1_clear_connection(sop);
609 sop->so_state = SOS_IDLE;
616 * ENDAK PDU / SOS_OUTRESYN Processor
619 * sop pointer to sscop connection block
620 * m pointer to PDU buffer (without trailer)
621 * trlr pointer to PDU trailer
628 sscop_endak_outresyn(sop, m, trlr)
636 * Stop retransmit timer
638 sop->so_timer[SSCOP_T_CC] = 0;
641 * Report protocol error
643 sscop_endak_error(sop, m, trlr);
646 * Notify user of connection failure
648 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
649 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
651 sscop_abort(sop, "sscop_endak_outresyn: stack memory\n");
656 * Clear connection data
658 qsaal1_clear_connection(sop);
663 sop->so_state = SOS_IDLE;
670 * RS PDU / SOS_OUTRESYN Processor
673 * sop pointer to sscop connection block
674 * m pointer to PDU buffer (without trailer)
675 * trlr pointer to PDU trailer
682 sscop_rs_outresyn(sop, m, trlr)
690 * Notify user of resynchronization
692 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
693 sop->so_connvc, (int)m, 0, err);
696 sscop_abort(sop, "sscop_rs_outresyn: stack memory\n");
701 * Reset receiver state variables
703 qsaal1_reset_rcvr(sop);
706 * Wait for both peer and user responses
708 sop->so_state = SOS_CONRESYN;
715 * RS PDU / SOS_READY Processor
718 * sop pointer to sscop connection block
719 * m pointer to PDU buffer (without trailer)
720 * trlr pointer to PDU trailer
727 sscop_rs_ready(sop, m, trlr)
735 * Notify user of resynchronization
737 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
738 sop->so_connvc, (int)m, 0, err);
741 sscop_abort(sop, "sscop_rs_ready: stack memory\n");
746 * Reset receiver state variables
748 qsaal1_reset_rcvr(sop);
751 * Wait for user response
753 sop->so_state = SOS_INRESYN;
760 * RSAK PDU / SOS_CONRESYN Processor
763 * sop pointer to sscop connection block
764 * m pointer to PDU buffer (without trailer)
765 * trlr pointer to PDU trailer
772 sscop_rsak_conresyn(sop, m, trlr)
780 * Stop retransmit timer
782 sop->so_timer[SSCOP_T_CC] = 0;
790 * Notify user of resynchronization completion
792 STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku,
793 sop->so_connvc, 0, 0, err);
795 sscop_abort(sop, "sscop_rsak_conresyn: stack memory\n");
800 * Start the polling timer
805 * Start lost poll/stat timer
807 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
810 * Continue waiting for user response
812 sop->so_state = SOS_INRESYN;
815 * See if transmit queues need servicing
817 if (sop->so_flags & SOF_XMITSRVC)
818 sscop_service_xmit(sop);
825 * SD PDU / SOS_INRESYN Processor
828 * sop pointer to sscop connection block
829 * m pointer to PDU buffer (without trailer)
830 * trlr pointer to PDU trailer
837 sscop_sd_inresyn(sop, m, trlr)
847 sop->so_timer[SSCOP_T_POLL] = 0;
848 sop->so_flags &= ~SOF_KEEPALIVE;
851 * Stop lost poll/stat timer
853 sop->so_timer[SSCOP_T_NORESP] = 0;
856 * Record error condition
858 sscop_sd_error(sop, m, trlr);
861 * Return an END to peer
863 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
866 * Notify user of connection failure
868 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
869 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
871 sscop_abort(sop, "sscop_sd_inresyn: stack memory\n");
876 * Clear connection data
878 qsaal1_clear_connection(sop);
881 * Go back to idle state
883 sop->so_state = SOS_IDLE;
890 * SD PDU / SOS_CONRESYN Processor
893 * sop pointer to sscop connection block
894 * m pointer to PDU buffer (without trailer)
895 * trlr pointer to PDU trailer
902 sscop_sd_conresyn(sop, m, trlr)
910 * Stop retransmit timer
912 sop->so_timer[SSCOP_T_CC] = 0;
915 * Record error condition
917 sscop_sd_error(sop, m, trlr);
920 * Return an END to peer
922 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
925 * Notify user of connection failure
927 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
928 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
930 sscop_abort(sop, "sscop_sd_conresyn: stack memory\n");
935 * Clear connection data
937 qsaal1_clear_connection(sop);
940 * Go back to idle state
942 sop->so_state = SOS_IDLE;
949 * SD/SDP PDU Common Processor
952 * sop pointer to sscop connection block
953 * m pointer to PDU user data buffer chain
954 * trlr pointer to PDU trailer
955 * type PDU type (SD or SDP)
962 sscop_sd_process(sop, m, trlr, type)
970 struct poll_pdu poll;
977 * Get PDU sequence number(s)
980 sp = (struct sd_pdu *)trlr;
981 SEQ_SET(ns, ntohl(sp->sd_ns));
984 spp = (struct sdp_pdu *)trlr;
985 SEQ_SET(ns, ntohl(spp->sdp_ns));
986 SEQ_SET(nps, ntohl(spp->sdp_nps));
990 * Ensure that the sequence number fits within the window
992 if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
998 * If this is the next in-sequence PDU, hand it to user
1000 if (ns == sop->so_rcvnext) {
1001 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1002 sop->so_connvc, (int)m, ns, err);
1009 * Bump next expected sequence number
1011 SEQ_INCR(sop->so_rcvnext, 1);
1014 * Slide receive window down
1016 SEQ_INCR(sop->so_rcvmax, 1);
1019 * Is this the highest sequence PDU we've received??
1021 if (ns == sop->so_rcvhigh) {
1023 * Yes, bump the limit and exit
1025 sop->so_rcvhigh = sop->so_rcvnext;
1032 * This is a retransmitted PDU, so see if we have
1033 * more in-sequence PDUs already queued up
1035 while ((php = sop->so_recv_hd) &&
1036 (php->ph_ns == sop->so_rcvnext)) {
1039 * Yup we do, so remove next PDU from queue and
1040 * pass it up to the user as well
1042 sop->so_recv_hd = php->ph_recv_lk;
1043 if (sop->so_recv_hd == NULL)
1044 sop->so_recv_tl = NULL;
1045 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1046 sop->so_connvc, (int)php->ph_buf, php->ph_ns,
1050 * Should never happen, but...
1052 KB_FREEALL(php->ph_buf);
1054 "sscop_sd_process: stack memory\n");
1059 * Bump next expected sequence number
1061 SEQ_INCR(sop->so_rcvnext, 1);
1064 * Slide receive window down
1066 SEQ_INCR(sop->so_rcvmax, 1);
1070 * Finished with data...see if we need to poll
1078 * We're gonna have to queue this PDU, so find space
1079 * for the PDU header
1081 KB_HEADROOM(m, space);
1084 * If there's not enough room in the received buffer,
1085 * allocate & link a new buffer for the header
1087 if (space < sizeof(struct pdu_hdr)) {
1089 KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
1094 KB_HEADSET(n, sizeof(struct pdu_hdr));
1103 * We can at least assume/require that the start of
1104 * the user data is aligned. Also note that we don't
1105 * include this header in the buffer len/offset fields.
1107 KB_DATASTART(m, php, struct pdu_hdr *);
1113 * Insert PDU into the receive queue
1115 if (sscop_recv_insert(sop, php)) {
1117 * Oops, a duplicate sequence number PDU is already on
1118 * the queue, somethings wrong here.
1120 sscop_maa_error(sop, 'Q');
1128 * Reestablish a new connection
1130 qsaal1_reestablish(sop);
1136 * Are we at the high-water mark??
1138 if (ns == sop->so_rcvhigh) {
1140 * Yes, just bump the mark
1142 SEQ_INCR(sop->so_rcvhigh, 1);
1150 * Are we beyond the high-water mark??
1152 if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1154 * Yes, then there's a missing PDU, so inform the transmitter
1157 (void) sscop_send_ustat(sop, ns);
1160 * Update high-water mark
1162 sop->so_rcvhigh = SEQ_ADD(ns, 1);
1170 * Do the "poll" part of an SDP PDU
1172 poll.poll_nps = htonl(nps);
1173 poll.poll_ns = htonl((PT_POLL << PT_TYPE_SHIFT) | ns);
1174 sscop_poll_ready(sop, NULL, (caddr_t)&poll);
1180 * SD PDU / SOS_READY Processor
1183 * sop pointer to sscop connection block
1184 * m pointer to PDU buffer (without trailer)
1185 * trlr pointer to PDU trailer
1192 sscop_sd_ready(sop, m, trlr)
1198 * Just call common SD/SDP processor
1200 sscop_sd_process(sop, m, trlr, PT_SD);
1207 * SDP PDU / SOS_READY Processor
1210 * sop pointer to sscop connection block
1211 * m pointer to PDU buffer (without trailer)
1212 * trlr pointer to PDU trailer
1219 sscop_sdp_ready(sop, m, trlr)
1225 * Just call common SD/SDP processor
1227 sscop_sd_process(sop, m, trlr, PT_SDP);
1234 * POLL PDU / SOS_INRESYN Processor
1237 * sop pointer to sscop connection block
1238 * m pointer to PDU buffer (without trailer)
1239 * trlr pointer to PDU trailer
1246 sscop_poll_inresyn(sop, m, trlr)
1256 sop->so_timer[SSCOP_T_POLL] = 0;
1257 sop->so_flags &= ~SOF_KEEPALIVE;
1260 * Stop lost poll/stat timer
1262 sop->so_timer[SSCOP_T_NORESP] = 0;
1265 * Report protocol error
1267 sscop_poll_error(sop, m, trlr);
1270 * Return an END to peer
1272 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1275 * Notify user of connection failure
1277 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1278 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1280 sscop_abort(sop, "sscop_poll_inresyn: stack memory\n");
1285 * Clear connection data
1287 qsaal1_clear_connection(sop);
1290 * Back to idle state
1292 sop->so_state = SOS_IDLE;
1299 * POLL PDU / SOS_CONRESYN Processor
1302 * sop pointer to sscop connection block
1303 * m pointer to PDU buffer (without trailer)
1304 * trlr pointer to PDU trailer
1311 sscop_poll_conresyn(sop, m, trlr)
1319 * Stop retransmit timer
1321 sop->so_timer[SSCOP_T_CC] = 0;
1324 * Record error condition
1326 sscop_poll_error(sop, m, trlr);
1329 * Return an END to peer
1331 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1334 * Notify user of connection failure
1336 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1337 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1339 sscop_abort(sop, "sscop_poll_conresyn: stack memory\n");
1344 * Clear connection data
1346 qsaal1_clear_connection(sop);
1349 * Go back to idle state
1351 sop->so_state = SOS_IDLE;
1358 * POLL PDU / SOS_READY Processor
1361 * sop pointer to sscop connection block
1362 * m pointer to PDU buffer (without trailer)
1363 * trlr pointer to PDU trailer
1370 sscop_poll_ready(sop, m, trlr)
1375 struct poll_pdu *pp = (struct poll_pdu *)trlr;
1381 * If the poll sequence number is less than highest number
1382 * we've already seen, something's wrong - so attempt to
1383 * reestablish a new connection.
1385 if (SEQ_LT(pp->poll_ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1387 * Record error condition
1389 sscop_maa_error(sop, 'Q');
1397 * Reestablish a new connection
1399 qsaal1_reestablish(sop);
1405 * Set a new "next highest" sequence number expected
1407 if (SEQ_LT(pp->poll_ns, sop->so_rcvmax, sop->so_rcvnext))
1408 SEQ_SET(sop->so_rcvhigh, pp->poll_ns);
1410 sop->so_rcvhigh = sop->so_rcvmax;
1413 * Return a STAT PDU to peer
1415 SEQ_SET(nps, ntohl(pp->poll_nps));
1417 (void) sscop_send_stat(sop, nps);
1424 * STAT PDU / SOS_CONRESYN Processor
1427 * sop pointer to sscop connection block
1428 * m pointer to PDU buffer (without trailer)
1429 * trlr pointer to PDU trailer
1436 sscop_stat_conresyn(sop, m, trlr)
1444 * Stop retransmit timer
1446 sop->so_timer[SSCOP_T_CC] = 0;
1449 * Record error condition
1451 sscop_stat_error(sop, m, trlr);
1454 * Return an END to peer
1456 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1459 * Notify user of connection failure
1461 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1462 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1464 sscop_abort(sop, "sscop_stat_conresyn: stack memory\n");
1469 * Clear connection data
1471 qsaal1_clear_connection(sop);
1474 * Go back to idle state
1476 sop->so_state = SOS_IDLE;
1483 * USTAT PDU / SOS_CONRESYN Processor
1486 * sop pointer to sscop connection block
1487 * m pointer to PDU buffer (without trailer)
1488 * trlr pointer to PDU trailer
1495 sscop_ustat_conresyn(sop, m, trlr)
1503 * Stop retransmit timer
1505 sop->so_timer[SSCOP_T_CC] = 0;
1508 * Record error condition
1510 sscop_ustat_error(sop, m, trlr);
1513 * Return an END to peer
1515 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1518 * Notify user of connection failure
1520 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1521 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1523 sscop_abort(sop, "sscop_ustat_conresyn: stack memory\n");
1528 * Clear connection data
1530 qsaal1_clear_connection(sop);
1533 * Go back to idle state
1535 sop->so_state = SOS_IDLE;