141709Ssklower /*
241709Ssklower * Copyright (c) University of British Columbia, 1984
357024Ssklower * Copyright (C) Computer Science Department IV,
457024Ssklower * University of Erlangen-Nuremberg, Germany, 1992
563216Sbostic * Copyright (c) 1991, 1992, 1993
663216Sbostic * The Regents of the University of California. All rights reserved.
741709Ssklower *
857024Ssklower * This code is derived from software contributed to Berkeley by the
957024Ssklower * Laboratory for Computation Vision and the Computer Science Department
1057024Ssklower * of the the University of British Columbia and the Computer Science
1157024Ssklower * Department (IV) of the University of Erlangen-Nuremberg, Germany.
1241709Ssklower *
1341709Ssklower * %sccs.include.redist.c%
1441709Ssklower *
15*67780Ssklower * @(#)pk_output.c 8.2 (Berkeley) 09/22/94
1641709Ssklower */
1741592Ssklower
1856530Sbostic #include <sys/param.h>
1956530Sbostic #include <sys/systm.h>
2056530Sbostic #include <sys/mbuf.h>
2156530Sbostic #include <sys/socket.h>
2256530Sbostic #include <sys/socketvar.h>
2356530Sbostic #include <sys/protosw.h>
2456530Sbostic #include <sys/errno.h>
2541592Ssklower
2656530Sbostic #include <net/if.h>
2741592Ssklower
2856530Sbostic #include <netccitt/x25.h>
2956530Sbostic #include <netccitt/pk.h>
3056530Sbostic #include <netccitt/pk_var.h>
3141592Ssklower
3250427Ssklower struct mbuf_cache pk_output_cache = {0 }, pk_input_cache;
3341592Ssklower struct mbuf *nextpk ();
3441592Ssklower
pk_output(lcp)3541592Ssklower pk_output (lcp)
3641592Ssklower register struct pklcd *lcp;
3741592Ssklower {
3841592Ssklower register struct x25_packet *xp;
3941592Ssklower register struct mbuf *m;
4041592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp;
4141592Ssklower
4241592Ssklower if (lcp == 0 || pkp == 0) {
4341592Ssklower printf ("pk_output: zero arg\n");
4441592Ssklower return;
4541592Ssklower }
4641592Ssklower
4741592Ssklower while ((m = nextpk (lcp)) != NULL) {
4841592Ssklower xp = mtod (m, struct x25_packet *);
4941592Ssklower
5041592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) {
5141592Ssklower /*
5241592Ssklower * All the work is already done - just set the state and
5341592Ssklower * pass to peer.
5441592Ssklower */
5541592Ssklower case CALL + READY:
5641592Ssklower lcp -> lcd_state = SENT_CALL;
5741592Ssklower lcp -> lcd_timer = pk_t21;
5841592Ssklower break;
5941592Ssklower
6041592Ssklower /*
6141592Ssklower * Just set the state to allow packet to flow and send the
6241592Ssklower * confirmation.
6341592Ssklower */
6441592Ssklower case CALL_ACCEPTED + RECEIVED_CALL:
6541592Ssklower lcp -> lcd_state = DATA_TRANSFER;
6641592Ssklower break;
6741592Ssklower
6841592Ssklower /*
6941592Ssklower * Just set the state. Keep the LCD around till the clear
7041592Ssklower * confirmation is returned.
7141592Ssklower */
7241592Ssklower case CLEAR + RECEIVED_CALL:
7341592Ssklower case CLEAR + SENT_CALL:
7441592Ssklower case CLEAR + DATA_TRANSFER:
7541592Ssklower lcp -> lcd_state = SENT_CLEAR;
7641592Ssklower lcp -> lcd_retry = 0;
7741592Ssklower /* fall through */
7841592Ssklower
7941592Ssklower case CLEAR + SENT_CLEAR:
8041592Ssklower lcp -> lcd_timer = pk_t23;
8141592Ssklower lcp -> lcd_retry++;
8241592Ssklower break;
8341592Ssklower
8441592Ssklower case CLEAR_CONF + RECEIVED_CLEAR:
8541592Ssklower case CLEAR_CONF + SENT_CLEAR:
8641592Ssklower case CLEAR_CONF + READY:
8741592Ssklower lcp -> lcd_state = READY;
8841592Ssklower break;
8941592Ssklower
9041592Ssklower case DATA + DATA_TRANSFER:
9157024Ssklower SPS(xp, lcp -> lcd_ssn);
9249931Ssklower lcp -> lcd_input_window =
9349931Ssklower (lcp -> lcd_rsn + 1) % MODULUS;
9457024Ssklower SPR(xp, lcp -> lcd_input_window);
9541592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
9641592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS;
9747269Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS))
9841592Ssklower lcp -> lcd_window_condition = TRUE;
9941592Ssklower break;
10041592Ssklower
10141592Ssklower case INTERRUPT + DATA_TRANSFER:
10245895Ssklower #ifdef ancient_history
10341592Ssklower xp -> packet_data = 0;
10445895Ssklower #endif
10541592Ssklower lcp -> lcd_intrconf_pending = TRUE;
10641592Ssklower break;
10741592Ssklower
10841592Ssklower case INTERRUPT_CONF + DATA_TRANSFER:
10941592Ssklower break;
11041592Ssklower
11141592Ssklower case RR + DATA_TRANSFER:
11241592Ssklower case RNR + DATA_TRANSFER:
11349931Ssklower lcp -> lcd_input_window =
11449931Ssklower (lcp -> lcd_rsn + 1) % MODULUS;
11557024Ssklower SPR(xp, lcp -> lcd_input_window);
11641592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
11741592Ssklower break;
11841592Ssklower
11941592Ssklower case RESET + DATA_TRANSFER:
12041592Ssklower lcp -> lcd_reset_condition = TRUE;
12141592Ssklower break;
12241592Ssklower
12341592Ssklower case RESET_CONF + DATA_TRANSFER:
12441592Ssklower lcp -> lcd_reset_condition = FALSE;
12541592Ssklower break;
12641592Ssklower
12741592Ssklower /*
12841592Ssklower * A restart should be only generated internally. Therefore
12941592Ssklower * all logic for restart is in the pk_restart routine.
13041592Ssklower */
13141592Ssklower case RESTART + READY:
13241592Ssklower lcp -> lcd_timer = pk_t20;
13341592Ssklower break;
13441592Ssklower
13541592Ssklower /*
13641592Ssklower * Restarts are all handled internally. Therefore all the
13741592Ssklower * logic for the incoming restart packet is handled in the
13841592Ssklower * pk_input routine.
13941592Ssklower */
14041592Ssklower case RESTART_CONF + READY:
14141592Ssklower break;
14241592Ssklower
14341592Ssklower default:
14441592Ssklower m_freem (m);
14541592Ssklower return;
14641592Ssklower }
14741592Ssklower
14841592Ssklower /* Trace the packet. */
14945895Ssklower pk_trace (pkp -> pk_xcp, m, "P-Out");
15041592Ssklower
15141592Ssklower /* Pass the packet on down to the link layer */
15250427Ssklower if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) {
15350427Ssklower m->m_flags |= 0x08;
15450427Ssklower mbuf_cache(&pk_input_cache, m);
15550427Ssklower }
15657024Ssklower (*pkp -> pk_lloutput) (pkp -> pk_llnext, m, pkp -> pk_rt);
15741592Ssklower }
15841592Ssklower }
15941592Ssklower
16041592Ssklower /*
16141592Ssklower * This procedure returns the next packet to send or null. A
16241592Ssklower * packet is composed of one or more mbufs.
16341592Ssklower */
16441592Ssklower
16541592Ssklower struct mbuf *
nextpk(lcp)16641592Ssklower nextpk (lcp)
16741592Ssklower struct pklcd *lcp;
16841592Ssklower {
16943361Ssklower register struct mbuf *m, *n;
17043361Ssklower struct socket *so = lcp -> lcd_so;
171*67780Ssklower register struct sockbuf *sb = (so ? &so -> so_snd : &lcp -> lcd_sb);
17241592Ssklower
17341592Ssklower if (lcp -> lcd_template) {
17445895Ssklower m = lcp -> lcd_template;
17541592Ssklower lcp -> lcd_template = NULL;
17641592Ssklower } else {
17741592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition ||
17841592Ssklower lcp -> lcd_reset_condition)
17941592Ssklower return (NULL);
18041592Ssklower
18143361Ssklower if ((m = sb -> sb_mb) == 0)
18241592Ssklower return (NULL);
18341592Ssklower
18443361Ssklower sb -> sb_mb = m -> m_nextpkt;
18541592Ssklower m->m_act = 0;
18643361Ssklower for (n = m; n; n = n -> m_next)
18743361Ssklower sbfree (sb, n);
18841592Ssklower }
18941592Ssklower return (m);
19041592Ssklower }
191