141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 341709Ssklower * Copyright (c) 1990 The Regents of the University of California. 441709Ssklower * All rights reserved. 541709Ssklower * 641709Ssklower * This code is derived from software contributed to Berkeley by 741709Ssklower * the Laboratory for Computation Vision and the Computer Science Department 841709Ssklower * of the University of British Columbia. 941709Ssklower * 1041709Ssklower * %sccs.include.redist.c% 1141709Ssklower * 12*47269Ssklower * @(#)pk_output.c 7.8 (Berkeley) 03/12/91 1341709Ssklower */ 1441592Ssklower 1545165Ssklower #include "param.h" 1645165Ssklower #include "systm.h" 1745165Ssklower #include "mbuf.h" 1845165Ssklower #include "socket.h" 1945165Ssklower #include "socketvar.h" 2045165Ssklower #include "protosw.h" 2145165Ssklower #include "errno.h" 2241592Ssklower 2341592Ssklower #include "../net/if.h" 2441592Ssklower 2545165Ssklower #include "x25.h" 2645165Ssklower #include "pk.h" 2745165Ssklower #include "pk_var.h" 2841592Ssklower 2941592Ssklower struct mbuf *nextpk (); 3041592Ssklower 3141592Ssklower pk_output (lcp) 3241592Ssklower register struct pklcd *lcp; 3341592Ssklower { 3441592Ssklower register struct x25_packet *xp; 3541592Ssklower register struct mbuf *m; 3641592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp; 3741592Ssklower 3841592Ssklower if (lcp == 0 || pkp == 0) { 3941592Ssklower printf ("pk_output: zero arg\n"); 4041592Ssklower return; 4141592Ssklower } 4241592Ssklower 4341592Ssklower while ((m = nextpk (lcp)) != NULL) { 4441592Ssklower xp = mtod (m, struct x25_packet *); 4541592Ssklower 4641592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) { 4741592Ssklower /* 4841592Ssklower * All the work is already done - just set the state and 4941592Ssklower * pass to peer. 5041592Ssklower */ 5141592Ssklower case CALL + READY: 5241592Ssklower lcp -> lcd_state = SENT_CALL; 5341592Ssklower lcp -> lcd_timer = pk_t21; 5441592Ssklower break; 5541592Ssklower 5641592Ssklower /* 5741592Ssklower * Just set the state to allow packet to flow and send the 5841592Ssklower * confirmation. 5941592Ssklower */ 6041592Ssklower case CALL_ACCEPTED + RECEIVED_CALL: 6141592Ssklower lcp -> lcd_state = DATA_TRANSFER; 6241592Ssklower break; 6341592Ssklower 6441592Ssklower /* 6541592Ssklower * Just set the state. Keep the LCD around till the clear 6641592Ssklower * confirmation is returned. 6741592Ssklower */ 6841592Ssklower case CLEAR + RECEIVED_CALL: 6941592Ssklower case CLEAR + SENT_CALL: 7041592Ssklower case CLEAR + DATA_TRANSFER: 7141592Ssklower lcp -> lcd_state = SENT_CLEAR; 7241592Ssklower lcp -> lcd_retry = 0; 7341592Ssklower /* fall through */ 7441592Ssklower 7541592Ssklower case CLEAR + SENT_CLEAR: 7641592Ssklower lcp -> lcd_timer = pk_t23; 7741592Ssklower lcp -> lcd_retry++; 7841592Ssklower break; 7941592Ssklower 8041592Ssklower case CLEAR_CONF + RECEIVED_CLEAR: 8141592Ssklower case CLEAR_CONF + SENT_CLEAR: 8241592Ssklower case CLEAR_CONF + READY: 8341592Ssklower lcp -> lcd_state = READY; 8441592Ssklower break; 8541592Ssklower 8641592Ssklower case DATA + DATA_TRANSFER: 8741592Ssklower PS(xp) = lcp -> lcd_ssn; 8841592Ssklower PR(xp) = lcp -> lcd_input_window; 8941592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 9041592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 91*47269Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS)) 9241592Ssklower lcp -> lcd_window_condition = TRUE; 9341592Ssklower break; 9441592Ssklower 9541592Ssklower case INTERRUPT + DATA_TRANSFER: 9645895Ssklower #ifdef ancient_history 9741592Ssklower xp -> packet_data = 0; 9845895Ssklower #endif 9941592Ssklower lcp -> lcd_intrconf_pending = TRUE; 10041592Ssklower break; 10141592Ssklower 10241592Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 10341592Ssklower break; 10441592Ssklower 10541592Ssklower case RR + DATA_TRANSFER: 10641592Ssklower lcp -> lcd_input_window = (lcp -> lcd_input_window + 1) % MODULUS; 10741592Ssklower PR(xp) = lcp -> lcd_input_window; 10841592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 10941592Ssklower break; 11041592Ssklower 11141592Ssklower case RNR + DATA_TRANSFER: 11241592Ssklower PR(xp) = lcp -> lcd_input_window; 11341592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11441592Ssklower break; 11541592Ssklower 11641592Ssklower case RESET + DATA_TRANSFER: 11741592Ssklower lcp -> lcd_reset_condition = TRUE; 11841592Ssklower break; 11941592Ssklower 12041592Ssklower case RESET_CONF + DATA_TRANSFER: 12141592Ssklower lcp -> lcd_reset_condition = FALSE; 12241592Ssklower break; 12341592Ssklower 12441592Ssklower /* 12541592Ssklower * A restart should be only generated internally. Therefore 12641592Ssklower * all logic for restart is in the pk_restart routine. 12741592Ssklower */ 12841592Ssklower case RESTART + READY: 12941592Ssklower lcp -> lcd_timer = pk_t20; 13041592Ssklower break; 13141592Ssklower 13241592Ssklower /* 13341592Ssklower * Restarts are all handled internally. Therefore all the 13441592Ssklower * logic for the incoming restart packet is handled in the 13541592Ssklower * pk_input routine. 13641592Ssklower */ 13741592Ssklower case RESTART_CONF + READY: 13841592Ssklower break; 13941592Ssklower 14041592Ssklower default: 14141592Ssklower m_freem (m); 14241592Ssklower return; 14341592Ssklower } 14441592Ssklower 14541592Ssklower /* Trace the packet. */ 14645895Ssklower pk_trace (pkp -> pk_xcp, m, "P-Out"); 14741592Ssklower 14841592Ssklower /* Pass the packet on down to the link layer */ 14945297Ssklower (*pkp -> pk_lloutput) (pkp -> pk_llnext, m); 15041592Ssklower } 15141592Ssklower } 15241592Ssklower 15341592Ssklower /* 15441592Ssklower * This procedure returns the next packet to send or null. A 15541592Ssklower * packet is composed of one or more mbufs. 15641592Ssklower */ 15741592Ssklower 15841592Ssklower struct mbuf * 15941592Ssklower nextpk (lcp) 16041592Ssklower struct pklcd *lcp; 16141592Ssklower { 16243361Ssklower register struct mbuf *m, *n; 16343361Ssklower struct socket *so = lcp -> lcd_so; 16443361Ssklower register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb); 16541592Ssklower 16641592Ssklower if (lcp -> lcd_template) { 16745895Ssklower m = lcp -> lcd_template; 16841592Ssklower lcp -> lcd_template = NULL; 16941592Ssklower } else { 17041592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 17141592Ssklower lcp -> lcd_reset_condition) 17241592Ssklower return (NULL); 17341592Ssklower 17443361Ssklower if ((m = sb -> sb_mb) == 0) 17541592Ssklower return (NULL); 17641592Ssklower 17743361Ssklower sb -> sb_mb = m -> m_nextpkt; 17841592Ssklower m->m_act = 0; 17943361Ssklower for (n = m; n; n = n -> m_next) 18043361Ssklower sbfree (sb, n); 18141592Ssklower } 18241592Ssklower return (m); 18341592Ssklower } 184