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*49591Ssklower * @(#)pk_output.c 7.9 (Berkeley) 05/09/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 29*49591Ssklower struct mbuf_cache pk_output_cache = {0 }; 3041592Ssklower struct mbuf *nextpk (); 3141592Ssklower 3241592Ssklower pk_output (lcp) 3341592Ssklower register struct pklcd *lcp; 3441592Ssklower { 3541592Ssklower register struct x25_packet *xp; 3641592Ssklower register struct mbuf *m; 3741592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp; 3841592Ssklower 3941592Ssklower if (lcp == 0 || pkp == 0) { 4041592Ssklower printf ("pk_output: zero arg\n"); 4141592Ssklower return; 4241592Ssklower } 4341592Ssklower 4441592Ssklower while ((m = nextpk (lcp)) != NULL) { 4541592Ssklower xp = mtod (m, struct x25_packet *); 4641592Ssklower 4741592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) { 4841592Ssklower /* 4941592Ssklower * All the work is already done - just set the state and 5041592Ssklower * pass to peer. 5141592Ssklower */ 5241592Ssklower case CALL + READY: 5341592Ssklower lcp -> lcd_state = SENT_CALL; 5441592Ssklower lcp -> lcd_timer = pk_t21; 5541592Ssklower break; 5641592Ssklower 5741592Ssklower /* 5841592Ssklower * Just set the state to allow packet to flow and send the 5941592Ssklower * confirmation. 6041592Ssklower */ 6141592Ssklower case CALL_ACCEPTED + RECEIVED_CALL: 6241592Ssklower lcp -> lcd_state = DATA_TRANSFER; 6341592Ssklower break; 6441592Ssklower 6541592Ssklower /* 6641592Ssklower * Just set the state. Keep the LCD around till the clear 6741592Ssklower * confirmation is returned. 6841592Ssklower */ 6941592Ssklower case CLEAR + RECEIVED_CALL: 7041592Ssklower case CLEAR + SENT_CALL: 7141592Ssklower case CLEAR + DATA_TRANSFER: 7241592Ssklower lcp -> lcd_state = SENT_CLEAR; 7341592Ssklower lcp -> lcd_retry = 0; 7441592Ssklower /* fall through */ 7541592Ssklower 7641592Ssklower case CLEAR + SENT_CLEAR: 7741592Ssklower lcp -> lcd_timer = pk_t23; 7841592Ssklower lcp -> lcd_retry++; 7941592Ssklower break; 8041592Ssklower 8141592Ssklower case CLEAR_CONF + RECEIVED_CLEAR: 8241592Ssklower case CLEAR_CONF + SENT_CLEAR: 8341592Ssklower case CLEAR_CONF + READY: 8441592Ssklower lcp -> lcd_state = READY; 8541592Ssklower break; 8641592Ssklower 8741592Ssklower case DATA + DATA_TRANSFER: 8841592Ssklower PS(xp) = lcp -> lcd_ssn; 8941592Ssklower PR(xp) = lcp -> lcd_input_window; 9041592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 9141592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 9247269Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS)) 9341592Ssklower lcp -> lcd_window_condition = TRUE; 9441592Ssklower break; 9541592Ssklower 9641592Ssklower case INTERRUPT + DATA_TRANSFER: 9745895Ssklower #ifdef ancient_history 9841592Ssklower xp -> packet_data = 0; 9945895Ssklower #endif 10041592Ssklower lcp -> lcd_intrconf_pending = TRUE; 10141592Ssklower break; 10241592Ssklower 10341592Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 10441592Ssklower break; 10541592Ssklower 10641592Ssklower case RR + DATA_TRANSFER: 10741592Ssklower lcp -> lcd_input_window = (lcp -> lcd_input_window + 1) % MODULUS; 10841592Ssklower PR(xp) = lcp -> lcd_input_window; 10941592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11041592Ssklower break; 11141592Ssklower 11241592Ssklower case RNR + DATA_TRANSFER: 11341592Ssklower PR(xp) = lcp -> lcd_input_window; 11441592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11541592Ssklower break; 11641592Ssklower 11741592Ssklower case RESET + DATA_TRANSFER: 11841592Ssklower lcp -> lcd_reset_condition = TRUE; 11941592Ssklower break; 12041592Ssklower 12141592Ssklower case RESET_CONF + DATA_TRANSFER: 12241592Ssklower lcp -> lcd_reset_condition = FALSE; 12341592Ssklower break; 12441592Ssklower 12541592Ssklower /* 12641592Ssklower * A restart should be only generated internally. Therefore 12741592Ssklower * all logic for restart is in the pk_restart routine. 12841592Ssklower */ 12941592Ssklower case RESTART + READY: 13041592Ssklower lcp -> lcd_timer = pk_t20; 13141592Ssklower break; 13241592Ssklower 13341592Ssklower /* 13441592Ssklower * Restarts are all handled internally. Therefore all the 13541592Ssklower * logic for the incoming restart packet is handled in the 13641592Ssklower * pk_input routine. 13741592Ssklower */ 13841592Ssklower case RESTART_CONF + READY: 13941592Ssklower break; 14041592Ssklower 14141592Ssklower default: 14241592Ssklower m_freem (m); 14341592Ssklower return; 14441592Ssklower } 14541592Ssklower 14641592Ssklower /* Trace the packet. */ 14745895Ssklower pk_trace (pkp -> pk_xcp, m, "P-Out"); 14841592Ssklower 14941592Ssklower /* Pass the packet on down to the link layer */ 150*49591Ssklower if (pk_output_cache.mbc_size || pk_output_cache.mbc_oldsize) 151*49591Ssklower mbuf_cache(&pk_output_cache, m); 15245297Ssklower (*pkp -> pk_lloutput) (pkp -> pk_llnext, m); 15341592Ssklower } 15441592Ssklower } 15541592Ssklower 15641592Ssklower /* 15741592Ssklower * This procedure returns the next packet to send or null. A 15841592Ssklower * packet is composed of one or more mbufs. 15941592Ssklower */ 16041592Ssklower 16141592Ssklower struct mbuf * 16241592Ssklower nextpk (lcp) 16341592Ssklower struct pklcd *lcp; 16441592Ssklower { 16543361Ssklower register struct mbuf *m, *n; 16643361Ssklower struct socket *so = lcp -> lcd_so; 16743361Ssklower register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb); 16841592Ssklower 16941592Ssklower if (lcp -> lcd_template) { 17045895Ssklower m = lcp -> lcd_template; 17141592Ssklower lcp -> lcd_template = NULL; 17241592Ssklower } else { 17341592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 17441592Ssklower lcp -> lcd_reset_condition) 17541592Ssklower return (NULL); 17641592Ssklower 17743361Ssklower if ((m = sb -> sb_mb) == 0) 17841592Ssklower return (NULL); 17941592Ssklower 18043361Ssklower sb -> sb_mb = m -> m_nextpkt; 18141592Ssklower m->m_act = 0; 18243361Ssklower for (n = m; n; n = n -> m_next) 18343361Ssklower sbfree (sb, n); 18441592Ssklower } 18541592Ssklower return (m); 18641592Ssklower } 187