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