xref: /original-bsd/sys/netccitt/pk_output.c (revision 9a66e37f)
1 /*
2  * Copyright (c) University of British Columbia, 1984
3  * Copyright (C) Computer Science Department IV,
4  * 		 University of Erlangen-Nuremberg, Germany, 1992
5  * Copyright (c) 1991, 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by the
9  * Laboratory for Computation Vision and the Computer Science Department
10  * of the the University of British Columbia and the Computer Science
11  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
12  *
13  * %sccs.include.redist.c%
14  *
15  *	@(#)pk_output.c	8.2 (Berkeley) 09/22/94
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/mbuf.h>
21 #include <sys/socket.h>
22 #include <sys/socketvar.h>
23 #include <sys/protosw.h>
24 #include <sys/errno.h>
25 
26 #include <net/if.h>
27 
28 #include <netccitt/x25.h>
29 #include <netccitt/pk.h>
30 #include <netccitt/pk_var.h>
31 
32 struct mbuf_cache pk_output_cache = {0 }, pk_input_cache;
33 struct	mbuf *nextpk ();
34 
pk_output(lcp)35 pk_output (lcp)
36 register struct pklcd *lcp;
37 {
38 	register struct x25_packet *xp;
39 	register struct mbuf *m;
40 	register struct pkcb *pkp = lcp -> lcd_pkp;
41 
42 	if (lcp == 0 || pkp == 0) {
43 		printf ("pk_output: zero arg\n");
44 		return;
45 	}
46 
47 	while ((m = nextpk (lcp)) != NULL) {
48 		xp = mtod (m, struct x25_packet *);
49 
50 		switch (pk_decode (xp) + lcp -> lcd_state) {
51 		/*
52 		 *  All the work is already done - just set the state and
53 		 *  pass to peer.
54 		 */
55 		case CALL + READY:
56 			lcp -> lcd_state = SENT_CALL;
57 			lcp -> lcd_timer = pk_t21;
58 			break;
59 
60 		/*
61 		 *  Just set the state to allow packet to flow and send the
62 		 *  confirmation.
63 		 */
64 		case CALL_ACCEPTED + RECEIVED_CALL:
65 			lcp -> lcd_state = DATA_TRANSFER;
66 			break;
67 
68 		/*
69 		 *  Just set the state. Keep the LCD around till the clear
70 		 *  confirmation is returned.
71 		 */
72 		case CLEAR + RECEIVED_CALL:
73 		case CLEAR + SENT_CALL:
74 		case CLEAR + DATA_TRANSFER:
75 			lcp -> lcd_state = SENT_CLEAR;
76 			lcp -> lcd_retry = 0;
77 			/* fall through */
78 
79 		case CLEAR + SENT_CLEAR:
80 			lcp -> lcd_timer = pk_t23;
81 			lcp -> lcd_retry++;
82 			break;
83 
84 		case CLEAR_CONF + RECEIVED_CLEAR:
85 		case CLEAR_CONF + SENT_CLEAR:
86 		case CLEAR_CONF + READY:
87 			lcp -> lcd_state = READY;
88 			break;
89 
90 		case DATA + DATA_TRANSFER:
91 			SPS(xp, lcp -> lcd_ssn);
92 			lcp -> lcd_input_window =
93 				(lcp -> lcd_rsn + 1) % MODULUS;
94 			SPR(xp, lcp -> lcd_input_window);
95 			lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
96 			lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS;
97 			if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS))
98 				lcp -> lcd_window_condition = TRUE;
99 			break;
100 
101 		case INTERRUPT + DATA_TRANSFER:
102 #ifdef ancient_history
103 			xp -> packet_data = 0;
104 #endif
105 			lcp -> lcd_intrconf_pending = TRUE;
106 			break;
107 
108 		case INTERRUPT_CONF + DATA_TRANSFER:
109 			break;
110 
111 		case RR + DATA_TRANSFER:
112 		case RNR + DATA_TRANSFER:
113 			lcp -> lcd_input_window =
114 				(lcp -> lcd_rsn + 1) % MODULUS;
115 			SPR(xp, lcp -> lcd_input_window);
116 			lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
117 			break;
118 
119 		case RESET + DATA_TRANSFER:
120 			lcp -> lcd_reset_condition = TRUE;
121 			break;
122 
123 		case RESET_CONF + DATA_TRANSFER:
124 			lcp -> lcd_reset_condition = FALSE;
125 			break;
126 
127 		/*
128 		 *  A restart should be only generated internally. Therefore
129 		 *  all logic for restart is in the pk_restart routine.
130 		 */
131 		case RESTART + READY:
132 			lcp -> lcd_timer = pk_t20;
133 			break;
134 
135 		/*
136 		 *  Restarts are all  handled internally.  Therefore all the
137 		 *  logic for the incoming restart packet is handled in  the
138 		 *  pk_input routine.
139 		 */
140 		case RESTART_CONF + READY:
141 			break;
142 
143 		default:
144 			m_freem (m);
145 			return;
146 		}
147 
148 		/* Trace the packet. */
149 		pk_trace (pkp -> pk_xcp, m, "P-Out");
150 
151 		/* Pass the packet on down to the link layer */
152 		if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) {
153 			m->m_flags |= 0x08;
154 			mbuf_cache(&pk_input_cache, m);
155 		}
156 		(*pkp -> pk_lloutput) (pkp -> pk_llnext, m, pkp -> pk_rt);
157 	}
158 }
159 
160 /*
161  *  This procedure returns the next packet to send or null. A
162  *  packet is composed of one or more mbufs.
163  */
164 
165 struct mbuf *
nextpk(lcp)166 nextpk (lcp)
167 struct pklcd *lcp;
168 {
169 	register struct mbuf *m, *n;
170 	struct socket *so = lcp -> lcd_so;
171 	register struct sockbuf *sb = (so ? &so -> so_snd : &lcp -> lcd_sb);
172 
173 	if (lcp -> lcd_template) {
174 		m = lcp -> lcd_template;
175 		lcp -> lcd_template = NULL;
176 	} else {
177 		if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition ||
178 				lcp -> lcd_reset_condition)
179 			return (NULL);
180 
181 		if ((m = sb -> sb_mb) == 0)
182 			return (NULL);
183 
184  		sb -> sb_mb = m -> m_nextpkt;
185  		m->m_act = 0;
186 		for (n = m; n; n = n -> m_next)
187 			sbfree (sb, n);
188 	}
189 	return (m);
190 }
191