The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netiso/tp.trans

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: tp.trans,v 1.9 2004/02/13 17:56:17 wiz Exp $   */
    2 
    3 /* NEW */
    4 /*-
    5  * Copyright (c) 1991, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)tp.trans    8.1 (Berkeley) 6/10/93
   33  */
   34 
   35 /***********************************************************
   36                 Copyright IBM Corporation 1987
   37 
   38                       All Rights Reserved
   39 
   40 Permission to use, copy, modify, and distribute this software and its 
   41 documentation for any purpose and without fee is hereby granted, 
   42 provided that the above copyright notice appear in all copies and that
   43 both that copyright notice and this permission notice appear in 
   44 supporting documentation, and that the name of IBM not be
   45 used in advertising or publicity pertaining to distribution of the
   46 software without specific, written prior permission.  
   47 
   48 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   49 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   50 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   51 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   52 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   53 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   54 SOFTWARE.
   55 
   56 ******************************************************************/
   57 
   58 /*
   59  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
   60  */
   61 /*
   62  * Transition file for TP.
   63  *
   64  * DO NOT:
   65  * - change the order of any of the events or states.  to do so will
   66  *   make tppt, netstat, etc. cease working.
   67  *
   68  * NOTE:
   69  * some hooks exist for data on (dis)connect, but it's ***NOT***SUPPORTED***
   70  * (read: may not work!)
   71  *
   72  * I tried to put everything that causes a change of state in here, hence 
   73  * there are some seemingly trivial events  like T_DETACH and T_LISTEN_req.
   74  *
   75  * Almost everything having to do w/ setting & cancelling timers is here
   76  * but once it was debugged, I moved the setting of the 
   77  * keepalive (sendack) timer to tp_emit(), where an AK_TPDU is sent.
   78  * This is so the code wouldn't be duplicated all over creation in here.
   79  *
   80  */
   81 *PROTOCOL tp
   82 
   83 *INCLUDE
   84 {
   85 /* @(#)tp.trans 8.1 (Berkeley) 6/10/93 */
   86 #include <sys/param.h>
   87 #include <sys/systm.h>
   88 #include <sys/socket.h>
   89 #include <sys/socketvar.h>
   90 #include <sys/protosw.h>
   91 #include <sys/mbuf.h>
   92 #include <sys/time.h>
   93 #include <sys/errno.h>
   94 
   95 #include <netiso/tp_param.h>
   96 #include <netiso/tp_stat.h>
   97 #include <netiso/tp_pcb.h>
   98 #include <netiso/tp_tpdu.h>
   99 #include <netiso/argo_debug.h>
  100 #include <netiso/tp_trace.h>
  101 #include <netiso/iso_errno.h>
  102 #include <netiso/tp_seq.h>
  103 #include <netiso/cons.h>
  104 
  105 #define DRIVERTRACE TPPTdriver
  106 #define sbwakeup(sb)    sowakeup(p->tp_sock, sb);
  107 #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0)
  108 
  109 static  trick_hc = 1;
  110 
  111 int     tp_emit(),
  112                 tp_goodack(),                           tp_goodXack(),
  113                 tp_stash()
  114 ;
  115 void    tp_indicate(),                          tp_getoptions(),        
  116                 tp_soisdisconnecting(),         tp_soisdisconnected(),
  117                 tp_recycle_tsuffix(),           
  118 #ifdef TP_DEBUG_TIMERS
  119                 tp_etimeout(),                          tp_euntimeout(),
  120                 tp_ctimeout(),                          tp_cuntimeout(),
  121                 tp_ctimeout_MIN(),
  122 #endif
  123                 tp_freeref(),                           tp_detach(),
  124                 tp0_stash(),                            tp0_send(),
  125                 tp_netcmd(),                            tp_send()
  126 ;
  127 
  128 typedef  struct tp_pcb tpcb_struct;
  129 
  130 
  131 }
  132 
  133 *PCB    tpcb_struct     SYNONYM  P
  134 
  135 *STATES
  136 
  137 TP_CLOSED       
  138 TP_CRSENT
  139 TP_AKWAIT
  140 TP_OPEN
  141 TP_CLOSING 
  142 TP_REFWAIT
  143 TP_LISTENING    /* Local to this implementation */
  144 TP_CONFIRMING   /* Local to this implementation */
  145 
  146 *EVENTS         { struct timeval e_time; }              SYNONYM  E
  147 
  148  /*
  149   * C (typically cancelled) timers  - 
  150   *
  151   * let these be the first ones so for the sake of convenience
  152   * their values are 0--> n-1
  153   * DO NOT CHANGE THE ORDER OF THESE TIMER EVENTS!! 
  154   */
  155  TM_inact               
  156  TM_retrans             
  157                                 /* TM_retrans is used for all 
  158                                  * simple retransmissions - CR,CC,XPD,DR 
  159                                  */
  160 
  161  TM_sendack             
  162                                 /* TM_sendack does dual duty - keepalive AND closed-window
  163                                  * Probes.
  164                                  * It's set w/ keepalive-ticks every time an ack is sent.
  165                                  * (this is done in (void) tp_emit() ).
  166                                  * Whenever a DT arrives which doesn't require immediate acking,
  167                                  * a separate fast-timeout flag is set ensuring 200ms response.
  168                                  */
  169  TM_notused     
  170 
  171  /* 
  172   * E (typically expired) timers - these may be in any order. 
  173   * These cause procedures to be executed directly; may not
  174   * cause an 'event' as we know them here.
  175   */
  176  TM_reference           { SeqNum e_low; SeqNum e_high; int e_retrans; }
  177  TM_data_retrans        { SeqNum e_low; SeqNum e_high; int e_retrans; }
  178 
  179 /* NOTE: in tp_input is a minor optimization that assumes that
  180  * for all tpdu types that can take e_data and e_datalen, these
  181  * fields fall in the same place in the event structure, that is,
  182  * e_data is the first field and e_datalen is the 2nd field.
  183  */
  184 
  185  ER_TPDU                {
  186                                   u_char                e_reason;
  187                                 }
  188  CR_TPDU                { struct mbuf   *e_data;        /* first field */
  189                                   int                   e_datalen; /* 2nd field */
  190                                   u_int                 e_cdt;
  191                                 }
  192  DR_TPDU                { struct mbuf   *e_data;        /* first field */
  193                                   int                   e_datalen; /* 2nd field */
  194                                   u_short               e_sref;
  195                                   u_char                e_reason;
  196                                 }
  197  DC_TPDU                
  198  CC_TPDU                { struct mbuf   *e_data;        /* first field */
  199                                   int                   e_datalen; /* 2nd field */
  200                                   u_short               e_sref;
  201                                   u_int                 e_cdt;
  202                                 }
  203  AK_TPDU                { u_int                 e_cdt;  
  204                                   SeqNum                e_seq;          
  205                                   SeqNum                e_subseq;               
  206                                   u_char                e_fcc_present;          
  207                                 }
  208  DT_TPDU                { struct mbuf   *e_data;        /* first field */
  209                                   int                   e_datalen; /* 2nd field */
  210                                   u_int                 e_eot;
  211                                   SeqNum                e_seq; 
  212                                 }
  213  XPD_TPDU               { struct mbuf   *e_data;        /* first field */
  214                                   int                   e_datalen;      /* 2nd field */
  215                                   SeqNum                e_seq;  
  216                                 }
  217  XAK_TPDU               { SeqNum                e_seq;          }
  218 
  219  T_CONN_req 
  220  T_DISC_req             { u_char                e_reason;       }
  221  T_LISTEN_req
  222  T_DATA_req
  223  T_XPD_req      
  224  T_USR_rcvd     
  225  T_USR_Xrcvd    
  226  T_DETACH
  227  T_NETRESET
  228  T_ACPT_req
  229 
  230 
  231 *TRANSITIONS
  232 
  233 
  234 /* TP_AKWAIT doesn't exist in TP 0 */
  235 SAME                    <==                     TP_AKWAIT                       [ CC_TPDU, DC_TPDU, XAK_TPDU ]
  236         DEFAULT
  237         NULLACTION
  238 ;
  239 
  240 
  241 /* applicable in TP4, TP0 */
  242 SAME                    <==                     TP_REFWAIT                                                              DR_TPDU
  243         ( $$.e_sref !=  0 ) 
  244         {
  245                 (void) tp_emit(DC_TPDU_type, $P, 0, 0, NULL);
  246         }
  247 ;
  248         
  249 /* applicable in TP4, TP0 */
  250 SAME                    <==                     TP_REFWAIT                      [ CR_TPDU, CC_TPDU, DT_TPDU, 
  251                                         DR_TPDU, XPD_TPDU, AK_TPDU, XAK_TPDU, DC_TPDU, ER_TPDU ]
  252         DEFAULT
  253         {
  254 #               ifdef TP_DEBUG
  255                 if( $E.ev_number != AK_TPDU )
  256                         printf("TPDU 0x%x in REFWAIT!!!!\n", $E.ev_number);
  257 #               endif TP_DEBUG
  258         }
  259 ;
  260 
  261 /* applicable in TP4, TP0 */
  262 SAME                    <==                     TP_REFWAIT                              [ T_DETACH, T_DISC_req ]
  263         DEFAULT
  264         NULLACTION
  265 ;
  266 
  267 /* applicable in TP4, TP0 */
  268 SAME                    <==                     TP_CRSENT                                                                AK_TPDU
  269         ($P.tp_class == TP_CLASS_0)
  270         {
  271                 /* oh, man is this grotesque or what? */
  272                 (void) tp_goodack($P, $$.e_cdt, $$.e_seq,  $$.e_subseq);
  273                 /* but it's necessary because this pseudo-ack may happen
  274                  * before the CC arrives, but we HAVE to adjust the
  275                  * snduna as a result of the ack, WHENEVER it arrives
  276                  */
  277         }
  278 ;
  279 
  280 /* applicable in TP4, TP0 */
  281 SAME                    <==                     TP_CRSENT       
  282                                         [ CR_TPDU, DC_TPDU, DT_TPDU, XPD_TPDU,  XAK_TPDU ]
  283         DEFAULT
  284         NULLACTION
  285 ;
  286 
  287 /* applicable in TP4, TP0 */
  288 SAME                    <==                     TP_CLOSED                                       [ DT_TPDU, XPD_TPDU,
  289                                                                                 ER_TPDU, DC_TPDU, AK_TPDU, XAK_TPDU ] 
  290         DEFAULT
  291         NULLACTION
  292 ;
  293 
  294 /* TP_CLOSING doesn't exist in TP 0 */
  295 SAME                    <==             TP_CLOSING
  296                                         [ CC_TPDU, CR_TPDU, DT_TPDU, XPD_TPDU, AK_TPDU, XAK_TPDU ]
  297         DEFAULT
  298         NULLACTION
  299 ;
  300 
  301 
  302 /* DC_TPDU doesn't exist in TP 0 */
  303 SAME                    <==                     TP_OPEN                                           DC_TPDU
  304         DEFAULT
  305         NULLACTION
  306 ;
  307 
  308 /* applicable in TP4, TP0 */
  309 SAME                    <==                     TP_LISTENING  [DR_TPDU, CC_TPDU, DT_TPDU, XPD_TPDU,
  310                                                                                  ER_TPDU, DC_TPDU, AK_TPDU, XAK_TPDU ] 
  311         DEFAULT 
  312         NULLACTION
  313 ;
  314 
  315 /* applicable in TP4, TP0 */
  316 TP_LISTENING    <==                     TP_CLOSED                                                       T_LISTEN_req 
  317         DEFAULT
  318         NULLACTION
  319 ;
  320 
  321 /* applicable in TP4, TP0 */
  322 TP_CLOSED               <==             [ TP_LISTENING, TP_CLOSED ]                     T_DETACH
  323         DEFAULT
  324         {
  325                 tp_detach($P);
  326         }
  327 ;
  328 
  329 TP_CONFIRMING   <==              TP_LISTENING                                                           CR_TPDU 
  330         ( $P.tp_class == TP_CLASS_0)
  331         {
  332                 $P.tp_refstate = REF_OPEN; /* has timers ??? */
  333         }
  334 ;
  335 
  336 TP_CONFIRMING           <==              TP_LISTENING                                                   CR_TPDU 
  337         DEFAULT
  338         {
  339                 IFTRACE(D_CONN)
  340                         tptrace(TPPTmisc, "CR datalen data", $$.e_datalen, $$.e_data,0,0);
  341                 ENDTRACE
  342                 IFDEBUG(D_CONN)
  343                         printf("CR datalen 0x%x data 0x%x", $$.e_datalen, $$.e_data);
  344                 ENDDEBUG
  345                 $P.tp_refstate = REF_OPEN; /* has timers */
  346                 $P.tp_fcredit = $$.e_cdt;
  347 
  348                 if ($$.e_datalen > 0) {
  349                         /* n/a for class 0 */
  350                         ASSERT($P.tp_Xrcv.sb_cc == 0); 
  351                         sbappendrecord(&$P.tp_Xrcv, $$.e_data);
  352                         $$.e_data = NULL; 
  353                 } 
  354         }
  355 ;
  356 
  357 TP_OPEN         <==              TP_CONFIRMING                                                                  T_ACPT_req 
  358         ( $P.tp_class == TP_CLASS_0 )
  359         {
  360                 IncStat(ts_tp0_conn);
  361                 IFTRACE(D_CONN)
  362                         tptrace(TPPTmisc, "Confiming", $P, 0,0,0);
  363                 ENDTRACE
  364                 IFDEBUG(D_CONN)
  365                         printf("Confirming connection: $P" );
  366                 ENDDEBUG
  367                 soisconnected($P.tp_sock);
  368                 (void) tp_emit(CC_TPDU_type, $P, 0,0, NULL) ;
  369                 $P.tp_fcredit = 1;
  370         }
  371 ;
  372 
  373 TP_AKWAIT               <==              TP_CONFIRMING                                                          T_ACPT_req
  374         (tp_emit(CC_TPDU_type, $P, 0,0, MCPY($P.tp_ucddata, M_NOWAIT)) == 0)
  375         {
  376                 IncStat(ts_tp4_conn); /* even though not quite open */
  377                 IFTRACE(D_CONN)
  378                         tptrace(TPPTmisc, "Confiming", $P, 0,0,0);
  379                 ENDTRACE
  380                 IFDEBUG(D_CONN)
  381                         printf("Confirming connection: $P" );
  382                 ENDDEBUG
  383                 tp_getoptions($P);
  384                 soisconnecting($P.tp_sock);
  385                 if (($P.tp_rx_strat & TPRX_FASTSTART) && ($P.tp_fcredit > 0))
  386                         $P.tp_cong_win = $P.tp_fcredit * $P.tp_l_tpdusize;
  387                 $P.tp_retrans = $P.tp_Nretrans;
  388                 tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
  389         }
  390 ;
  391 
  392 /* TP4 only */
  393 TP_CLOSED               <==              TP_CONFIRMING                                                          T_ACPT_req
  394         DEFAULT /* emit failed */
  395         {
  396                 IFDEBUG(D_CONN)
  397                         printf("event: CR_TPDU emit CC failed done " );
  398                 ENDDEBUG
  399                 soisdisconnected($P.tp_sock);
  400                 tp_recycle_tsuffix($P);
  401                 tp_freeref($P.tp_lref);
  402                 tp_detach($P);
  403         }
  404 ;
  405 
  406 /* applicable in TP4, TP0 */
  407 TP_CRSENT               <==             TP_CLOSED                                                               T_CONN_req 
  408         DEFAULT
  409         {
  410                 int error;
  411                 struct mbuf *data = NULL;
  412 
  413                 IFTRACE(D_CONN)
  414                         tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)$P.tp_flags,
  415                         $P.tp_ucddata, 0, 0);
  416                 ENDTRACE
  417                 data =  MCPY($P.tp_ucddata, M_WAIT);
  418                 if (data) {
  419                         IFDEBUG(D_CONN)
  420                                 printf("T_CONN_req.trans m_copy cc 0x%x\n", 
  421                                         $P.tp_ucddata);
  422                                 dump_mbuf(data, "sosnd @ T_CONN_req");
  423                         ENDDEBUG
  424                 }
  425 
  426                 if (error = tp_emit(CR_TPDU_type, $P, 0, 0, data) )
  427                         return error; /* driver WON'T change state; will return error */
  428                 
  429                 $P.tp_refstate = REF_OPEN; /* has timers */
  430                 if($P.tp_class != TP_CLASS_0) {
  431                         $P.tp_retrans = $P.tp_Nretrans;
  432                         tp_ctimeout($P, TM_retrans, (int)$P.tp_cr_ticks);
  433                 }
  434         }
  435 ;
  436 
  437 /* applicable in TP4, TP0, but state TP_AKWAIT doesn't apply to TP0 */
  438 TP_REFWAIT              <==             [ TP_CRSENT, TP_AKWAIT, TP_OPEN ]                       DR_TPDU 
  439         DEFAULT
  440         {
  441                 sbflush(&$P.tp_Xrcv); /* purge non-delivered data data */
  442                 if ($$.e_datalen > 0) {
  443                         sbappendrecord(&$P.tp_Xrcv, $$.e_data);
  444                         $$.e_data = NULL;
  445                 } 
  446                 if ($P.tp_state == TP_OPEN)
  447                         tp_indicate(T_DISCONNECT, $P, 0);
  448                 else {
  449                         int so_error = ECONNREFUSED;
  450                         if ($$.e_reason != (E_TP_NO_SESSION ^ TP_ERROR_MASK) &&
  451                             $$.e_reason != (E_TP_NO_CR_ON_NC ^ TP_ERROR_MASK) &&
  452                             $$.e_reason != (E_TP_REF_OVERFLOW ^ TP_ERROR_MASK))
  453                                 so_error = ECONNABORTED;
  454                         tp_indicate(T_DISCONNECT, $P, so_error);
  455                 }
  456                 tp_soisdisconnected($P);
  457                 if ($P.tp_class != TP_CLASS_0) {
  458                         if ($P.tp_state == TP_OPEN ) {
  459                                 tp_euntimeout($P, TM_data_retrans); /* all */
  460                                 tp_cuntimeout($P, TM_retrans);
  461                                 tp_cuntimeout($P, TM_inact);
  462                                 tp_cuntimeout($P, TM_sendack);
  463                                 $P.tp_flags &= ~TPF_DELACK;
  464                         }
  465                         tp_cuntimeout($P, TM_retrans);
  466                         if( $$.e_sref !=  0 ) 
  467                                 (void) tp_emit(DC_TPDU_type, $P, 0, 0, NULL);
  468                 }
  469         }
  470 ;
  471 
  472 SAME                    <==             TP_CLOSED                                                                       DR_TPDU 
  473         DEFAULT
  474         {
  475                 if( $$.e_sref != 0 )
  476                         (void) tp_emit(DC_TPDU_type, $P, 0, 0, NULL); 
  477                 /* reference timer already set - reset it to be safe (???) */
  478                 tp_euntimeout($P, TM_reference); /* all */
  479                 tp_etimeout($P, TM_reference, (int)$P.tp_refer_ticks);
  480         }
  481 ;
  482 
  483 /* NBS(34) */
  484 TP_REFWAIT              <==     TP_CRSENT                                                                       ER_TPDU
  485         DEFAULT
  486         {       
  487                 tp_cuntimeout($P, TM_retrans);
  488                 tp_indicate(ER_TPDU, $P, $$.e_reason);
  489                 tp_soisdisconnected($P);
  490         }
  491 ;
  492 
  493 /* NBS(27) */
  494 TP_REFWAIT              <==             TP_CLOSING                                                                      DR_TPDU
  495         DEFAULT
  496         {        
  497                 tp_cuntimeout($P, TM_retrans);
  498                 tp_soisdisconnected($P);
  499         }
  500 ;
  501 /* these two transitions are the same but can't be combined because xebec
  502  * can't handle the use of $$.e_reason if they're combined
  503  */
  504 /* NBS(27) */
  505 TP_REFWAIT              <==             TP_CLOSING                                                                      ER_TPDU
  506         DEFAULT
  507         {        
  508                 tp_indicate(ER_TPDU, $P, $$.e_reason);
  509                 tp_cuntimeout($P, TM_retrans);
  510                 tp_soisdisconnected($P);
  511         }
  512 ;
  513 /* NBS(27) */
  514 TP_REFWAIT              <==             TP_CLOSING                                                                      DC_TPDU 
  515         DEFAULT
  516         {        
  517                 tp_cuntimeout($P, TM_retrans);
  518                 tp_soisdisconnected($P);
  519         }
  520 ;
  521 
  522 /* NBS(21) */
  523 SAME                    <==     TP_CLOSED                                               [ CC_TPDU, CR_TPDU ]
  524         DEFAULT
  525         {       /* don't ask me why we have to do this - spec says so */
  526                 (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NO_SESSION, NULL);
  527                 /* don't bother with retransmissions of the DR */
  528         }
  529 ;
  530 
  531 /* NBS(34) */
  532 TP_REFWAIT              <==     TP_OPEN                                                                         ER_TPDU
  533         ($P.tp_class == TP_CLASS_0)
  534         {
  535                 tp_soisdisconnecting($P.tp_sock);
  536                 tp_indicate(ER_TPDU, $P, $$.e_reason);
  537                 tp_soisdisconnected($P);
  538                 tp_netcmd( $P, CONN_CLOSE );
  539         }
  540 ;
  541 
  542 TP_CLOSING              <==     [ TP_AKWAIT, TP_OPEN ]                                          ER_TPDU
  543         DEFAULT
  544         {
  545                 if ($P.tp_state == TP_OPEN) {
  546                         tp_euntimeout($P, TM_data_retrans); /* all */
  547                         tp_cuntimeout($P, TM_inact);
  548                         tp_cuntimeout($P, TM_sendack);
  549                 }
  550                 tp_soisdisconnecting($P.tp_sock);
  551                 tp_indicate(ER_TPDU, $P, $$.e_reason);
  552                 $P.tp_retrans = $P.tp_Nretrans;
  553                 tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
  554                 (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_PROTO_ERR, NULL);
  555         }
  556 ;
  557 /* NBS(6) */
  558 TP_OPEN                 <==             TP_CRSENT                                                                       CC_TPDU 
  559         ($P.tp_class == TP_CLASS_0) 
  560         {       
  561                 tp_cuntimeout($P, TM_retrans);
  562                 IncStat(ts_tp0_conn);
  563                 $P.tp_fcredit = 1;
  564                 soisconnected($P.tp_sock);
  565         }
  566 ;
  567 
  568 TP_OPEN                 <==             TP_CRSENT                                                                       CC_TPDU 
  569         DEFAULT
  570         {       
  571                 IFDEBUG(D_CONN)
  572                         printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", 
  573                             (int)$P.tp_flags);
  574                 ENDDEBUG
  575                 IncStat(ts_tp4_conn);
  576                 $P.tp_fref = $$.e_sref;
  577                 $P.tp_fcredit = $$.e_cdt;
  578                 if (($P.tp_rx_strat & TPRX_FASTSTART) && ($$.e_cdt > 0))
  579                         $P.tp_cong_win = $$.e_cdt * $P.tp_l_tpdusize;
  580                 tp_getoptions($P);
  581                 tp_cuntimeout($P, TM_retrans);
  582                 if ($P.tp_ucddata) {
  583                         IFDEBUG(D_CONN)
  584                                 printf("dropping user connect data cc 0x%x\n",
  585                                     $P.tp_ucddata->m_len);
  586                         ENDDEBUG
  587                         m_freem($P.tp_ucddata);
  588                         $P.tp_ucddata = 0;
  589                 }
  590                 soisconnected($P.tp_sock);
  591                 if ($$.e_datalen > 0) {
  592                         ASSERT($P.tp_Xrcv.sb_cc == 0); /* should be empty */
  593                         sbappendrecord(&$P.tp_Xrcv, $$.e_data);
  594                         $$.e_data = NULL;
  595                 }
  596 
  597                 (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL);
  598                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  599         }
  600 ;
  601 
  602 /* TP4 only */
  603 SAME                    <==             TP_CRSENT                                                                       TM_retrans 
  604         (       $P.tp_retrans > 0 )
  605         {
  606                 struct mbuf *data = NULL;
  607                 int error;
  608 
  609                 IncStat(ts_retrans_cr);
  610                 $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
  611                 data = MCPY($P.tp_ucddata, M_NOWAIT);
  612                 if($P.tp_ucddata) {
  613                         IFDEBUG(D_CONN)
  614                                 printf("TM_retrans.trans m_copy cc 0x%x\n", data);
  615                                 dump_mbuf($P.tp_ucddata, "sosnd @ TM_retrans");
  616                         ENDDEBUG
  617                         if( data == NULL )
  618                                 return ENOBUFS;
  619                 }
  620 
  621                 $P.tp_retrans --;
  622                 if( error = tp_emit(CR_TPDU_type, $P, 0, 0, data) ) {
  623                         $P.tp_sock->so_error = error;
  624                 }
  625                 tp_ctimeout($P, TM_retrans, (int)$P.tp_cr_ticks);
  626         }
  627 ;
  628 
  629 /* TP4 only  */
  630 TP_REFWAIT              <==             TP_CRSENT                                                                       TM_retrans 
  631         DEFAULT /* no more CR retransmissions */
  632         {       
  633                 IncStat(ts_conn_gaveup);
  634                 $P.tp_sock->so_error = ETIMEDOUT;
  635                 tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
  636                 tp_soisdisconnected($P);
  637         }
  638 ;
  639 
  640 /* TP4 only */
  641 SAME                    <==      TP_AKWAIT                                                                                      CR_TPDU 
  642         DEFAULT
  643         /* duplicate CR (which doesn't really exist in the context of
  644          * a connectionless network layer) 
  645          * Doesn't occur in class 0.
  646          */
  647         {       
  648                 int error;
  649                 struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
  650 
  651                 if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) {
  652                         $P.tp_sock->so_error = error;
  653                 }
  654                 $P.tp_retrans = $P.tp_Nretrans;
  655                 tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
  656         }
  657 ;
  658 
  659 /* TP4 only */
  660 TP_OPEN                 <==             TP_AKWAIT                                                                               DT_TPDU 
  661         ( IN_RWINDOW( $P, $$.e_seq,
  662                                         $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) )
  663         {
  664                 int doack;
  665 
  666                 /*
  667                  * Get rid of any confirm or connect data, so that if we
  668                  * crash or close, it isn't thought of as disconnect data.
  669                  */
  670                 if ($P.tp_ucddata) {
  671                         m_freem($P.tp_ucddata);
  672                         $P.tp_ucddata = 0;
  673                 }
  674                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  675                 tp_cuntimeout($P, TM_retrans);
  676                 soisconnected($P.tp_sock);
  677                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  678 
  679                 /* see also next 2 transitions, if you make any changes */
  680 
  681                 doack = tp_stash($P, $E);
  682                 IFDEBUG(D_DATA)
  683                         printf("tp_stash returns %d\n",doack);
  684                 ENDDEBUG
  685 
  686                 if (doack) {
  687                         (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL ); 
  688                         tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
  689                 } else
  690                         tp_ctimeout( $P, TM_sendack, (int)$P.tp_sendack_ticks);
  691                 
  692                 IFDEBUG(D_DATA)
  693                         printf("after stash calling sbwakeup\n");
  694                 ENDDEBUG
  695         }
  696 ;
  697 
  698 SAME                    <==             TP_OPEN                                                                         DT_TPDU 
  699         ( $P.tp_class == TP_CLASS_0 )
  700         {
  701                 tp0_stash($P, $E);
  702                 sbwakeup( &$P.tp_sock->so_rcv );
  703 
  704                 IFDEBUG(D_DATA)
  705                         printf("after stash calling sbwakeup\n");
  706                 ENDDEBUG
  707         }
  708 ;
  709 
  710 /* TP4 only */
  711 SAME                    <==             TP_OPEN                                                                         DT_TPDU 
  712         ( IN_RWINDOW( $P, $$.e_seq,
  713                                         $P.tp_rcvnxt, SEQ($P, $P.tp_rcvnxt + $P.tp_lcredit)) )
  714         {
  715                 int doack; /* tells if we must ack immediately */
  716 
  717                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  718                 sbwakeup( &$P.tp_sock->so_rcv );
  719 
  720                 doack = tp_stash($P, $E);
  721                 IFDEBUG(D_DATA)
  722                         printf("tp_stash returns %d\n",doack);
  723                 ENDDEBUG
  724 
  725                 if(doack)
  726                         (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL ); 
  727                 else
  728                         tp_ctimeout_MIN( $P, TM_sendack, (int)$P.tp_sendack_ticks);
  729                 
  730                 IFDEBUG(D_DATA)
  731                         printf("after stash calling sbwakeup\n");
  732                 ENDDEBUG
  733         }
  734 ;
  735 
  736 /* Not in window  - we must ack under certain circumstances, namely
  737  * a) if the seq number is below lwe but > lwe - (max credit ever given)
  738  * (to handle lost acks) Can use max-possible-credit for this ^^^.
  739  * and 
  740  * b) seq number is > uwe but < uwe + previously sent & withdrawn credit
  741  *
  742  * (see 12.2.3.8.1 of ISO spec, p. 73)
  743  * We just always ack.
  744  */
  745 /* TP4 only */
  746 SAME                    <==     [ TP_OPEN, TP_AKWAIT ]                                                  DT_TPDU
  747         DEFAULT /* Not in window */
  748         {       
  749                 IFTRACE(D_DATA)
  750                         tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ",
  751                                 $$.e_seq, $P.tp_rcvnxt, $P.tp_lcredit, 0);
  752                 ENDTRACE
  753                 IncStat(ts_dt_niw);
  754                 m_freem($$.e_data);
  755                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  756                 (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL ); 
  757         }
  758 ;
  759 
  760 /* TP4 only */
  761 TP_OPEN                 <==             TP_AKWAIT                                                                               AK_TPDU
  762         DEFAULT
  763         {
  764                 if ($P.tp_ucddata) {
  765                         m_freem($P.tp_ucddata);
  766                         $P.tp_ucddata = 0;
  767                 }
  768                 (void) tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq);
  769                 tp_cuntimeout($P, TM_retrans);
  770 
  771                 soisconnected($P.tp_sock);
  772                 IFTRACE(D_CONN)
  773                         struct socket *so = $P.tp_sock;
  774                         tptrace(TPPTmisc, 
  775                         "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags",
  776                                 so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags);
  777                         tptrace(TPPTmisc, 
  778                         "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head",
  779                                 so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head);
  780                 ENDTRACE
  781 
  782                 tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
  783                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  784         }
  785 ;
  786 
  787 /* TP4 only */
  788 TP_OPEN                 <==     [ TP_OPEN, TP_AKWAIT ]                                          XPD_TPDU
  789         ($P.tp_Xrcvnxt == $$.e_seq)
  790         {
  791                 if( $P.tp_state == TP_AKWAIT ) {
  792                         if ($P.tp_ucddata) {
  793                                 m_freem($P.tp_ucddata);
  794                                 $P.tp_ucddata = 0;
  795                         }
  796                         tp_cuntimeout($P, TM_retrans);
  797                         soisconnected($P.tp_sock);
  798                         tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
  799                         tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  800                 } 
  801                 IFTRACE(D_XPD)
  802                 tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n",
  803                                 $P.tp_Xrcvnxt,$$.e_seq,  $$.e_datalen, $$.e_data->m_len);
  804                 ENDTRACE
  805 
  806                 $P.tp_sock->so_state |= SS_RCVATMARK;
  807                 $$.e_data->m_flags |= M_EOR;
  808                 sbinsertoob(&$P.tp_Xrcv, $$.e_data);
  809                 IFDEBUG(D_XPD)
  810                         dump_mbuf($$.e_data, "XPD TPDU: tp_Xrcv");
  811                 ENDDEBUG
  812                 tp_indicate(T_XDATA, $P, 0);
  813                 sbwakeup( &$P.tp_Xrcv );
  814 
  815                 (void) tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, NULL);
  816                 SEQ_INC($P, $P.tp_Xrcvnxt);
  817         }
  818 ;
  819 
  820 /* TP4 only */
  821 SAME                    <==             TP_OPEN                                                                         T_USR_Xrcvd
  822         DEFAULT
  823         {
  824                 if( $P.tp_Xrcv.sb_cc == 0 ) {
  825                         /* kludge for select(): */ 
  826                         /* $P.tp_sock->so_state &= ~SS_OOBAVAIL; */
  827                 }
  828         }
  829         /* OLD WAY:
  830          * Ack only after the user receives the XPD.  This is better for 
  831          * users that use one XPD right after another.
  832          * Acking right away (the NEW WAY, see the prev. transition) is 
  833          * better for occasional * XPD, when the receiving user doesn't 
  834          * want to read the XPD immediately (which is session's behavior).
  835          *
  836                 int error = tp_emit(XAK_TPDU_type, $P, $P.tp_Xrcvnxt, 0, NULL);
  837                 SEQ_INC($P, $P.tp_Xrcvnxt);
  838                 return error;
  839         */
  840 ;
  841 
  842 /* NOTE: presently if the user doesn't read the connection data
  843  * before and expedited data PDU comes in, the connection data will
  844  * be dropped. This is a bug.  To avoid it, we need somewhere else
  845  * to put the connection data.
  846  * On the other hand, we need not to have it sitting around forever.
  847  * This is a problem with the idea of trying to accommodate
  848  * data on connect w/ a passive-open user interface. 
  849  */
  850 /* TP4 only */
  851 
  852 SAME                    <==     [ TP_AKWAIT, TP_OPEN ]                                                  XPD_TPDU
  853         DEFAULT /* not in window or cdt==0 */
  854         {
  855                 IFTRACE(D_XPD)
  856                         tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n",
  857                                 $P.tp_Xrcvnxt, $$.e_seq,  $P.tp_Xrcv.sb_cc , 0);
  858                 ENDTRACE
  859                 if( $P.tp_Xrcvnxt != $$.e_seq )
  860                         IncStat(ts_xpd_niw);
  861                 if( $P.tp_Xrcv.sb_cc ) {
  862                         /* might as well kick 'em again */
  863                         tp_indicate(T_XDATA, $P, 0);
  864                         IncStat(ts_xpd_dup);
  865                 }
  866                 m_freem($$.e_data);
  867                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
  868                 /* don't send an xack because the xak gives "last one received", not
  869                  * "next one i expect" (dumb)
  870                  */
  871         }
  872 ;
  873 
  874 /* Occurs (AKWAIT, OPEN) when parent (listening) socket gets aborted, and tries
  875  * to detach all its "children"
  876  * Also (CRSENT) when user kills a job that's doing a connect()
  877  */
  878 TP_REFWAIT              <==     TP_CRSENT                                                                               T_DETACH
  879         ($P.tp_class == TP_CLASS_0)
  880         {
  881                 struct socket *so = $P.tp_sock;
  882 
  883                 /* detach from parent socket so it can finish closing */
  884                 if (so->so_head) {
  885                         if (!soqremque(so, 0) && !soqremque(so, 1))
  886                                 panic("tp: T_DETACH");
  887                         so->so_head = 0;
  888                 }
  889                 tp_soisdisconnecting($P.tp_sock);
  890                 tp_netcmd( $P, CONN_CLOSE);
  891                 tp_soisdisconnected($P);
  892         }
  893 ;
  894 
  895 /* TP4 only */
  896 TP_CLOSING              <== [ TP_CLOSING, TP_AKWAIT, TP_CRSENT, TP_CONFIRMING ] T_DETACH
  897         DEFAULT
  898         {
  899                 struct socket *so = $P.tp_sock;
  900                 struct mbuf *data = NULL;
  901 
  902                 /* detach from parent socket so it can finish closing */
  903                 if (so->so_head) {
  904                         if (!soqremque(so, 0) && !soqremque(so, 1))
  905                                 panic("tp: T_DETACH");
  906                         so->so_head = 0;
  907                 }
  908                 if ($P.tp_state != TP_CLOSING) {
  909                         tp_soisdisconnecting($P.tp_sock);
  910                         data = MCPY($P.tp_ucddata, M_NOWAIT);
  911                         (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NORMAL_DISC, data);
  912                         $P.tp_retrans = $P.tp_Nretrans;
  913                         tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
  914                 }
  915         }
  916 ;
  917 
  918 TP_REFWAIT              <==             [ TP_OPEN, TP_CRSENT ]                                          T_DISC_req
  919         ( $P.tp_class == TP_CLASS_0 )
  920         {
  921                 tp_soisdisconnecting($P.tp_sock);
  922                 tp_netcmd( $P, CONN_CLOSE);
  923                 tp_soisdisconnected($P);
  924         }
  925 ;
  926 
  927 /* TP4 only */
  928 TP_CLOSING              <==     [ TP_AKWAIT, TP_OPEN, TP_CRSENT, TP_CONFIRMING ]  T_DISC_req
  929         DEFAULT
  930         {
  931                 struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
  932 
  933                 if($P.tp_state == TP_OPEN) {
  934                         tp_euntimeout($P, TM_data_retrans); /* all */
  935                         tp_cuntimeout($P, TM_inact);
  936                         tp_cuntimeout($P, TM_sendack);
  937                         $P.tp_flags &= ~TPF_DELACK;
  938                 }
  939                 if (data) {
  940                         IFDEBUG(D_CONN)
  941                                 printf("T_DISC_req.trans tp_ucddata 0x%x\n", 
  942                                         $P.tp_ucddata);
  943                                 dump_mbuf(data, "ucddata @ T_DISC_req");
  944                         ENDDEBUG
  945                 }
  946                 tp_soisdisconnecting($P.tp_sock);
  947                 $P.tp_retrans = $P.tp_Nretrans;
  948                 tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
  949 
  950                 if( trick_hc )
  951                         return tp_emit(DR_TPDU_type, $P, 0, $$.e_reason, data);
  952         }
  953 ;
  954 
  955 /* TP4 only */
  956 SAME                    <==             TP_AKWAIT                                                                       TM_retrans
  957         ( $P.tp_retrans > 0 )
  958         {
  959                 int error;
  960                 struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
  961 
  962                 IncStat(ts_retrans_cc);
  963                 $P.tp_retrans --;
  964                 $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
  965 
  966                 if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) 
  967                         $P.tp_sock->so_error = error;
  968                 tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
  969         }
  970 ;
  971 
  972 /* TP4 only */
  973 TP_CLOSING              <==             TP_AKWAIT                                                                       TM_retrans
  974         DEFAULT  /* out of time */
  975         {
  976                 IncStat(ts_conn_gaveup);
  977                 tp_soisdisconnecting($P.tp_sock);
  978                 $P.tp_sock->so_error = ETIMEDOUT;
  979                 tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
  980                 (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST, NULL);
  981                 $P.tp_retrans = $P.tp_Nretrans;
  982                 tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
  983         }
  984 ;
  985 
  986 /* the retrans timers had better go off BEFORE the inactivity timer does,
  987  * if transmissions are going on.
  988  * (i.e., TM_inact should be greater than timer for all retrans plus ack
  989  * turnaround)
  990  */
  991 /* TP4 only */
  992 TP_CLOSING              <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
  993         DEFAULT
  994         {
  995                 tp_euntimeout($P, TM_data_retrans); /* all */
  996                 tp_cuntimeout($P, TM_inact); 
  997                 tp_cuntimeout($P, TM_sendack);
  998 
  999                 IncStat(ts_conn_gaveup);
 1000                 tp_soisdisconnecting($P.tp_sock);
 1001                 $P.tp_sock->so_error = ETIMEDOUT;
 1002                 tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
 1003                 (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST_2, NULL);
 1004                 $P.tp_retrans = $P.tp_Nretrans;
 1005                 tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
 1006         }
 1007 ;
 1008 
 1009 /* TP4 only */
 1010 SAME                    <==             TP_OPEN                                                                         TM_retrans
 1011         ( $P.tp_retrans > 0 )
 1012         {
 1013                 $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
 1014                 /* resume XPD */
 1015                 if      ( $P.tp_Xsnd.sb_mb )  {
 1016                         struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
 1017                         int shift;
 1018 
 1019                         IFTRACE(D_XPD)
 1020                                 tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndnxt snduna",
 1021                                         $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, 
 1022                                         $P.tp_snduna); 
 1023                         ENDTRACE
 1024                         IFDEBUG(D_XPD)
 1025                                 dump_mbuf(m, "XPD retrans emitting M");
 1026                         ENDDEBUG
 1027                         IncStat(ts_retrans_xpd);
 1028                         $P.tp_retrans --;
 1029                         shift = max($P.tp_Nretrans - $P.tp_retrans, 6);
 1030                         (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
 1031                         tp_ctimeout($P, TM_retrans, ((int)$P.tp_dt_ticks) << shift);
 1032                 }
 1033         }
 1034 ;
 1035 
 1036 /* TP4 only */
 1037 SAME                    <==             TP_OPEN                                                                 TM_data_retrans
 1038         ($P.tp_rxtshift < TP_NRETRANS)
 1039         {       
 1040                 $P.tp_rxtshift++;
 1041                 (void) tp_data_retrans($P);
 1042         }
 1043 ;
 1044 
 1045 /* TP4 only */
 1046 SAME                    <==             TP_CLOSING                                                                      TM_retrans
 1047         (       $P.tp_retrans > 0 )
 1048         {       
 1049                 $P.tp_retrans --;
 1050                 (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_DR_NO_REAS, NULL);
 1051                 IncStat(ts_retrans_dr);
 1052                 tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
 1053         }
 1054 ;
 1055 
 1056 /* TP4 only */
 1057 TP_REFWAIT              <==             TP_CLOSING                                                                      TM_retrans
 1058         DEFAULT /* no more retrans - gave up */
 1059         {       
 1060                 $P.tp_sock->so_error = ETIMEDOUT;
 1061                 $P.tp_refstate = REF_FROZEN;
 1062                 tp_recycle_tsuffix( $P );
 1063                 tp_etimeout($P, TM_reference, (int)$P.tp_refer_ticks);
 1064         }
 1065 ;
 1066 
 1067 /*
 1068  * The resources are kept around until the ref timer goes off.
 1069  * The suffixes are wiped out sooner so they can be reused right away.
 1070  */
 1071 /* applicable in TP4, TP0 */
 1072 TP_CLOSED               <==             TP_REFWAIT                                                                      TM_reference
 1073         DEFAULT
 1074         {
 1075                 tp_freeref($P.tp_lref);
 1076                 tp_detach($P);
 1077         }
 1078 ;
 1079 
 1080 /* applicable in TP4, TP0 */
 1081 /* A duplicate CR from connectionless network layer can't happen */
 1082 SAME                    <==     TP_OPEN                                                         [ CR_TPDU, CC_TPDU ]
 1083         DEFAULT
 1084         {       
 1085                 if( $P.tp_class != TP_CLASS_0) {
 1086                         tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 1087                         if ( $E.ev_number == CC_TPDU )
 1088                                 (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL); 
 1089                 }
 1090                 /* ignore it if class 0 - state tables are blank for this */
 1091         }
 1092 ;
 1093 
 1094 /* applicable in TP4, TP0 */
 1095 SAME                    <==     TP_OPEN                                                                 T_DATA_req
 1096         DEFAULT
 1097         {
 1098                 IFTRACE(D_DATA)
 1099                         tptrace(TPPTmisc, "T_DATA_req sndnxt snduna fcredit, tpcb",
 1100                                 $P.tp_sndnxt, $P.tp_snduna, $P.tp_fcredit, $P);
 1101                 ENDTRACE
 1102 
 1103                 tp_send($P);
 1104         }
 1105 ;
 1106 
 1107 /* TP4 only */
 1108 SAME                    <==             TP_OPEN                                                                         T_XPD_req
 1109         DEFAULT
 1110                 /* T_XPD_req was issued by sosend iff xpd socket buf was empty
 1111                  * at time of sosend(), 
 1112                  * AND (which means) there were no unacknowledged XPD tpdus outstanding!
 1113                  */
 1114         {
 1115                 int error = 0;
 1116 
 1117                 /* resume XPD */
 1118                 if      ( $P.tp_Xsnd.sb_mb )  {
 1119                         struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
 1120                         /* m_copy doesn't preserve the m_xlink field, but at this pt.
 1121                          * that doesn't matter
 1122                          */
 1123 
 1124                         IFTRACE(D_XPD)
 1125                                 tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndnxt snduna",
 1126                                         $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, 
 1127                                         $P.tp_snduna); 
 1128                         ENDTRACE
 1129                         IFDEBUG(D_XPD)
 1130                                 printf("T_XPD_req: sb_cc 0x%x\n", $P.tp_Xsnd.sb_cc);
 1131                                 dump_mbuf(m, "XPD req emitting M");
 1132                         ENDDEBUG
 1133                         error = 
 1134                                 tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
 1135                         $P.tp_retrans = $P.tp_Nretrans;
 1136 
 1137                         tp_ctimeout($P, TM_retrans, (int)$P.tp_rxtcur);
 1138                         SEQ_INC($P, $P.tp_Xsndnxt);
 1139                 } 
 1140                 if(trick_hc)
 1141                         return error;
 1142         }
 1143 ;
 1144 
 1145 /* TP4, faked ack in TP0 when cons send completes */
 1146 SAME                    <==             TP_OPEN                                                                         AK_TPDU
 1147         ( tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq)  )
 1148 
 1149         /* tp_goodack == true means 
 1150          * EITHER it actually acked something heretofore unacknowledged
 1151          * OR no news but the credit should be processed.
 1152          */
 1153         {
 1154                 struct sockbuf *sb = &$P.tp_sock->so_snd;
 1155 
 1156                 IFDEBUG(D_ACKRECV)
 1157                         printf("GOOD ACK seq 0x%x cdt 0x%x\n", $$.e_seq, $$.e_cdt);
 1158                 ENDDEBUG
 1159                 if( $P.tp_class != TP_CLASS_0) {
 1160                         tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 1161                 }
 1162                 sbwakeup(sb);
 1163                 IFDEBUG(D_ACKRECV)
 1164                         printf("GOOD ACK new sndnxt 0x%x\n", $P.tp_sndnxt);
 1165                 ENDDEBUG
 1166         }
 1167 ;
 1168 
 1169 /* TP4, and TP0 after sending a CC or possibly a CR */
 1170 SAME                    <==             TP_OPEN                                                                          AK_TPDU
 1171         DEFAULT
 1172         {
 1173                 IFTRACE(D_ACKRECV)
 1174                         tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 
 1175                                 $$.e_fcc_present, $P.tp_r_subseq, $$.e_subseq, 0);
 1176                 ENDTRACE
 1177                 if( $P.tp_class != TP_CLASS_0 ) {
 1178 
 1179                         if ( !$$.e_fcc_present ) {
 1180                                 /* send ACK with FCC */
 1181                                 IncStat( ts_ackreason[_ACK_FCC_] );
 1182                                 (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 1, NULL);
 1183                         }
 1184                         tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 1185                 } 
 1186         }
 1187 ;
 1188 
 1189 /* NBS(47) */
 1190         /* goes in at *** */
 1191                 /* just so happens that this is never true now, because we allow
 1192                  * only 1 packet in the queue at once (this could be changed)
 1193                 if      ( $P.tp_Xsnd.sb_mb )  {
 1194                         struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, ??);
 1195 
 1196                         (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
 1197                         $P.tp_retrans = $P.tp_Nretrans;
 1198                         tp_ctimeout($P, TM_retrans, (int)$P.tp_xpd_ticks);
 1199                         SEQ_INC($P, $P.tp_Xsndnxt);
 1200                 }
 1201                  */
 1202         /* end of the above hack */
 1203 
 1204 /* TP4 only */
 1205 SAME                    <==     TP_OPEN                                                                         XAK_TPDU
 1206         ( tp_goodXack($P, $$.e_seq) )
 1207         /* tp_goodXack checks for good ack, removes the correct 
 1208          * tpdu from the queue and  returns 1 if ack was legit, 0 if not.
 1209          * also updates tp_Xuna
 1210          */
 1211         {       
 1212                 tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 1213                 tp_cuntimeout($P, TM_retrans);
 1214 
 1215                 sbwakeup( &$P.tp_sock->so_snd );
 1216 
 1217                 /* resume normal data */
 1218                 tp_send($P);
 1219         }
 1220 ;
 1221 
 1222 /* TP4, and TP0 after sending a CC or possibly a CR */
 1223 SAME                    <==             TP_OPEN                                                                         XAK_TPDU
 1224         DEFAULT
 1225         {
 1226                 IFTRACE(D_ACKRECV)
 1227                         tptrace(TPPTmisc, "BOGUS XACK eventtype ", $E.ev_number, 0, 0,0);
 1228                 ENDTRACE
 1229                 if( $P.tp_class != TP_CLASS_0 ) {
 1230                         tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 1231                 } 
 1232         }
 1233 ;
 1234 
 1235 /* TP4 only */
 1236 SAME                    <==             TP_OPEN                                                                 TM_sendack 
 1237         DEFAULT
 1238         {       
 1239                 int timo;
 1240                 IFTRACE(D_TIMER)
 1241                         tptrace(TPPTsendack, -1, $P.tp_lcredit, $P.tp_sent_uwe, 
 1242                         $P.tp_sent_lcdt, 0);
 1243                 ENDTRACE
 1244                 IncPStat($P, tps_n_TMsendack);
 1245                 (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL);
 1246                 if ($P.tp_fcredit == 0) {
 1247                         if ($P.tp_rxtshift < TP_MAXRXTSHIFT)
 1248                                 $P.tp_rxtshift++;
 1249                         timo = ($P.tp_dt_ticks) << $P.tp_rxtshift;
 1250                 } else
 1251                         timo = $P.tp_sendack_ticks;
 1252                 tp_ctimeout($P, TM_sendack, timo);
 1253         }
 1254 ;
 1255 
 1256 /* TP0 only */
 1257 SAME                    <==             TP_OPEN                                                                         T_USR_rcvd
 1258         ($P.tp_class == TP_CLASS_0)
 1259         {
 1260                 if (sbspace(&$P.tp_sock->so_rcv) > 0)
 1261                         tp0_openflow($P);
 1262         }
 1263 ;
 1264 
 1265 /* TP4 only */
 1266                 /* If old credit was zero, 
 1267                  * we'd better inform other side that we now have space
 1268                  * But this is not enough.  Sender might not yet have
 1269                  * seen an ack with cdt 0 but it might still think the
 1270                  * window is closed, so it's going to wait.
 1271                  * Best to send an ack each time.
 1272                  * Strictly speaking, this ought to be a function of the
 1273                  * general ack strategy.
 1274                  */
 1275 SAME                    <==             TP_OPEN                                                                         T_USR_rcvd
 1276         DEFAULT
 1277         {       
 1278                 if( trick_hc ) {
 1279                         SeqNum ack_thresh;
 1280                         /*
 1281                          * If the upper window edge has advanced a reasonable
 1282                          * amount beyond what was known, send an ACK.
 1283                          * A reasonable amount is 2 packets, unless the max window
 1284                          * is only 1 or 2 packets, in which case we
 1285                          * should send an ack for any advance in the upper window edge.
 1286                          */
 1287                         LOCAL_CREDIT($P);
 1288                         ack_thresh = SEQ_SUB($P, $P.tp_lcredit + $P.tp_rcvnxt,
 1289                                                                          ($P.tp_maxlcredit > 2 ? 2 : 1));
 1290                         if (SEQ_GT($P, ack_thresh, $P.tp_sent_uwe)) {
 1291                                 IncStat(ts_ackreason[_ACK_USRRCV_]);
 1292                                 $P.tp_flags &= ~TPF_DELACK;
 1293                                 return tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, NULL);
 1294                         }
 1295                 }
 1296         }
 1297 ;
 1298 
 1299 /* applicable in TP4, TP0 */
 1300 SAME                    <==             TP_REFWAIT                              [ T_USR_rcvd, T_USR_Xrcvd ]
 1301         DEFAULT
 1302         /* This happens if other end sent a DR when  the user was waiting 
 1303          * on a receive.  
 1304          * Processing the DR includes putting us in REFWAIT state.
 1305          */
 1306         {
 1307                 if(trick_hc)
 1308                 return ECONNABORTED;
 1309         }
 1310 ;
 1311 
 1312 /* TP0 only */
 1313 TP_REFWAIT              <==             [ TP_OPEN, TP_CRSENT, TP_LISTENING ]    T_NETRESET
 1314         ( $P.tp_class != TP_CLASS_4 ) 
 1315                 /* 0 or (4 and 0) */
 1316                 /* in OPEN class will be 0 or 4 but not both */
 1317                 /* in CRSENT or LISTENING it could be in negotiation, hence both */
 1318                 /* Actually, this shouldn't ever happen in LISTENING */
 1319         {
 1320                 ASSERT( $P.tp_state != TP_LISTENING );
 1321                 tp_indicate(T_DISCONNECT, $P, ECONNRESET);
 1322                 tp_soisdisconnected($P);
 1323         }
 1324 ;
 1325 
 1326 /* TP4: ignore resets */
 1327 SAME            <==             [ TP_OPEN, TP_CRSENT, TP_AKWAIT,
 1328                                                 TP_CLOSING, TP_LISTENING ]                              T_NETRESET
 1329         DEFAULT
 1330         NULLACTION
 1331 ;
 1332  
 1333 /* applicable in TP4, TP0 */
 1334 SAME                    <==             [ TP_CLOSED, TP_REFWAIT ]                               T_NETRESET
 1335         DEFAULT
 1336         NULLACTION
 1337 ;
 1338 
 1339 /* C'EST TOUT */

Cache object: d210f82c4f6f77fca2a9831bbe963bc8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.