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_driver.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: tp_driver.c,v 1.19 2005/12/11 12:25:12 christos Exp $  */
    2 
    3 #include <sys/cdefs.h>
    4 __KERNEL_RCSID(0, "$NetBSD: tp_driver.c,v 1.19 2005/12/11 12:25:12 christos Exp $");
    5 
    6 #include "tp_states.h"
    7 
    8 static const struct act_ent {
    9         int             a_newstate;
   10         int             a_action;
   11 } statetable[] = {{
   12                 0, 0
   13 },
   14 #include "tp_states.init"
   15 };
   16 
   17 /* @(#)tp.trans 8.1 (Berkeley) 6/10/93 */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/socket.h>
   22 #include <sys/socketvar.h>
   23 #include <sys/protosw.h>
   24 #include <sys/mbuf.h>
   25 #include <sys/time.h>
   26 #include <sys/errno.h>
   27 
   28 #include <netiso/tp_param.h>
   29 #include <netiso/tp_var.h>
   30 #include <netiso/tp_stat.h>
   31 #include <netiso/tp_pcb.h>
   32 #include <netiso/tp_tpdu.h>
   33 #include <netiso/argo_debug.h>
   34 #include <netiso/tp_trace.h>
   35 #include <netiso/iso_errno.h>
   36 #include <netiso/tp_seq.h>
   37 #include <netiso/cons.h>
   38 
   39 #define DRIVERTRACE TPPTdriver
   40 #define sbwakeup(sb, dir)       sowakeup(p->tp_sock, sb, dir);
   41 #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0)
   42 
   43 static int trick_hc = 1;
   44 
   45 #include "tp_events.h"
   46 static int _Xebec_action (int, struct tp_event *, struct tp_pcb *);
   47 static int _Xebec_index (struct tp_event *, struct tp_pcb *);
   48 
   49 static int
   50 _Xebec_action(int a, struct tp_event *e, struct tp_pcb *p)
   51 {
   52         int             error;
   53         struct mbuf    *data = NULL;
   54         int             doack;
   55         struct socket  *so = p->tp_sock;
   56         struct sockbuf *sb;
   57         int             timo;
   58 
   59         switch (a) {
   60         case -1:
   61                 return tp_protocol_error(e, p);
   62         case 0x1:
   63                 (void) tp_emit(DC_TPDU_type, p, 0, 0, NULL);
   64                 break;
   65         case 0x2:
   66 #ifdef TP_DEBUG
   67                 if (e->ev_number != AK_TPDU)
   68                         printf("TPDU 0x%x in REFWAIT!!!!\n", e->ev_number);
   69 #endif  /* TP_DEBUG */
   70                 break;
   71         case 0x3:
   72                 /* oh, man is this grotesque or what? */
   73                 (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq);
   74                 /*
   75                  * but it's necessary because this pseudo-ack may
   76                  * happen before the CC arrives, but we HAVE to
   77                  * adjust the snduna as a result of the ack, WHENEVER
   78                  * it arrives
   79                  */
   80                 break;
   81         case 0x4:
   82                 tp_detach(p);
   83                 break;
   84         case 0x5:
   85                 p->tp_refstate = REF_OPEN;      /* has timers ??? */
   86                 break;
   87         case 0x6:
   88 #ifdef TPPT
   89                 if (tp_traceflags[D_CONN])
   90                         tptrace(TPPTmisc, "CR datalen data",
   91                                 e->ev_union.EV_CR_TPDU.e_datalen,
   92                                 e->ev_union.EV_CR_TPDU.e_data, 0, 0);
   93 #endif
   94 #ifdef ARGO_DEBUG
   95                 if (argo_debug[D_CONN]) {
   96                         printf("CR datalen 0x%x data %p",
   97                                 e->ev_union.EV_CR_TPDU.e_datalen,
   98                                 e->ev_union.EV_CR_TPDU.e_data);
   99                 }
  100 #endif
  101                 p->tp_refstate = REF_OPEN;      /* has timers */
  102                 p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt;
  103 
  104                 if (e->ev_union.EV_CR_TPDU.e_datalen > 0) {
  105                         /* n/a for class 0 */
  106                         ASSERT(p->tp_Xrcv.sb_cc == 0);
  107                         sbappendrecord(&p->tp_Xrcv,
  108                                        e->ev_union.EV_CR_TPDU.e_data);
  109                         e->ev_union.EV_CR_TPDU.e_data = NULL;
  110                 }
  111                 break;
  112         case 0x7:
  113                 IncStat(ts_tp0_conn);
  114 #ifdef TPPT
  115                 if (tp_traceflags[D_CONN])
  116                         tptrace(TPPTmisc, "Confiming", p, 0, 0, 0);
  117 #endif
  118 #ifdef ARGO_DEBUG
  119                     if (argo_debug[D_CONN]) {
  120                         printf("Confirming connection: p");
  121                 }
  122 #endif
  123                 soisconnected(p->tp_sock);
  124                 (void) tp_emit(CC_TPDU_type, p, 0, 0, NULL);
  125                 p->tp_fcredit = 1;
  126                 break;
  127         case 0x8:
  128                 IncStat(ts_tp4_conn);   /* even though not quite open */
  129 #ifdef TPPT
  130                 if (tp_traceflags[D_CONN])
  131                         tptrace(TPPTmisc, "Confiming", p, 0, 0, 0);
  132 #endif
  133 #ifdef ARGO_DEBUG
  134                 if (argo_debug[D_CONN]) {
  135                         printf("Confirming connection: p");
  136                 }
  137 #endif
  138                 tp_getoptions(p);
  139                 soisconnecting(p->tp_sock);
  140                 if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0))
  141                         p->tp_cong_win = p->tp_fcredit * p->tp_l_tpdusize;
  142                 p->tp_retrans = p->tp_Nretrans;
  143                 tp_ctimeout(p, TM_retrans, (int) p->tp_cc_ticks);
  144                 break;
  145         case 0x9:
  146 #ifdef ARGO_DEBUG
  147                 if (argo_debug[D_CONN]) {
  148                         printf("event: CR_TPDU emit CC failed done ");
  149                 }
  150 #endif
  151                 soisdisconnected(p->tp_sock);
  152                 tp_recycle_tsuffix(p);
  153                 tp_freeref(p->tp_lref);
  154                 tp_detach(p);
  155                 break;
  156         case 0xa:
  157 #ifdef TPPT
  158                 if (tp_traceflags[D_CONN])
  159                         tptrace(TPPTmisc, "T_CONN_req flags ucddata",
  160                                 (int) p->tp_flags, p->tp_ucddata, 0, 0);
  161 #endif
  162                 data = MCPY(p->tp_ucddata, M_WAIT);
  163                 if (data) {
  164 #ifdef ARGO_DEBUG
  165                         if (argo_debug[D_CONN]) {
  166                                 printf("T_CONN_req.trans m_copy cc %p\n",
  167                                        p->tp_ucddata);
  168                                 dump_mbuf(data, "sosnd @ T_CONN_req");
  169                         }
  170 #endif
  171                 }
  172                 if ((error = tp_emit(CR_TPDU_type, p, 0, 0, data)) != 0)
  173                         return error;   /* driver WON'T change state;
  174                                          * will return error */
  175 
  176                 p->tp_refstate = REF_OPEN;      /* has timers */
  177                 if (p->tp_class != TP_CLASS_0) {
  178                         p->tp_retrans = p->tp_Nretrans;
  179                         tp_ctimeout(p, TM_retrans, (int) p->tp_cr_ticks);
  180                 }
  181                 break;
  182         case 0xb:
  183                 sbflush(&p->tp_Xrcv);   /* purge non-delivered data
  184                                          * data */
  185                 if (e->ev_union.EV_DR_TPDU.e_datalen > 0) {
  186                         sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data);
  187                         e->ev_union.EV_DR_TPDU.e_data = NULL;
  188                 }
  189                 if (p->tp_state == TP_OPEN)
  190                         tp_indicate(T_DISCONNECT, p, 0);
  191                 else {
  192                         int             so_error = ECONNREFUSED;
  193                         if (e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_SESSION ^ TP_ERROR_MASK) &&
  194                             e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_CR_ON_NC ^ TP_ERROR_MASK) &&
  195                             e->ev_union.EV_DR_TPDU.e_reason != (E_TP_REF_OVERFLOW ^ TP_ERROR_MASK))
  196                                 so_error = ECONNABORTED;
  197                         tp_indicate(T_DISCONNECT, p, so_error);
  198                 }
  199                 tp_soisdisconnected(p);
  200                 if (p->tp_class != TP_CLASS_0) {
  201                         if (p->tp_state == TP_OPEN) {
  202                                 tp_euntimeout(p, TM_data_retrans);/* all */
  203                                 tp_cuntimeout(p, TM_retrans);
  204                                 tp_cuntimeout(p, TM_inact);
  205                                 tp_cuntimeout(p, TM_sendack);
  206                                 p->tp_flags &= ~TPF_DELACK;
  207                         }
  208                         tp_cuntimeout(p, TM_retrans);
  209                         if (e->ev_union.EV_DR_TPDU.e_sref != 0)
  210                                 (void) tp_emit(DC_TPDU_type, p, 0, 0, NULL);
  211                 }
  212                 break;
  213         case 0xc:
  214                 if (e->ev_union.EV_DR_TPDU.e_sref != 0)
  215                         (void) tp_emit(DC_TPDU_type, p, 0, 0, NULL);
  216                 /*
  217                  * reference timer already set - reset it to be safe
  218                  * (???)
  219                  */
  220                 tp_euntimeout(p, TM_reference); /* all */
  221                 tp_etimeout(p, TM_reference, (int) p->tp_refer_ticks);
  222                 break;
  223         case 0xd:
  224                 tp_cuntimeout(p, TM_retrans);
  225                 tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
  226                 tp_soisdisconnected(p);
  227                 break;
  228         case 0xe:
  229                 tp_cuntimeout(p, TM_retrans);
  230                 tp_soisdisconnected(p);
  231                 break;
  232         case 0xf:
  233                 tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
  234                 tp_cuntimeout(p, TM_retrans);
  235                 tp_soisdisconnected(p);
  236                 break;
  237         case 0x10:
  238                 tp_cuntimeout(p, TM_retrans);
  239                 tp_soisdisconnected(p);
  240                 break;
  241         case 0x11:
  242                 /* don't ask me why we have to do this - spec
  243                  * says so */
  244                 (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NO_SESSION, NULL);
  245                 /* don't bother with retransmissions of the DR */
  246                 break;
  247         case 0x12:
  248                 tp_soisdisconnecting(p->tp_sock);
  249                 tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
  250                 tp_soisdisconnected(p);
  251                 tp_netcmd(p, CONN_CLOSE);
  252                 break;
  253         case 0x13:
  254                 if (p->tp_state == TP_OPEN) {
  255                         tp_euntimeout(p, TM_data_retrans);      /* all */
  256                         tp_cuntimeout(p, TM_inact);
  257                         tp_cuntimeout(p, TM_sendack);
  258                 }
  259                 tp_soisdisconnecting(p->tp_sock);
  260                 tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
  261                 p->tp_retrans = p->tp_Nretrans;
  262                 tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  263                 (void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, NULL);
  264                 break;
  265         case 0x14:
  266                 tp_cuntimeout(p, TM_retrans);
  267                 IncStat(ts_tp0_conn);
  268                 p->tp_fcredit = 1;
  269                 soisconnected(p->tp_sock);
  270                 break;
  271         case 0x15:
  272 #ifdef ARGO_DEBUG
  273                 if (argo_debug[D_CONN]) {
  274                         printf("trans: CC_TPDU in CRSENT state flags 0x%x\n",
  275                                (int) p->tp_flags);
  276                 }
  277 #endif
  278                 IncStat(ts_tp4_conn);
  279                 p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref;
  280                 p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt;
  281                 if ((p->tp_rx_strat & TPRX_FASTSTART) &&
  282                     (e->ev_union.EV_CC_TPDU.e_cdt > 0))
  283                         p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt * p->tp_l_tpdusize;
  284                 tp_getoptions(p);
  285                 tp_cuntimeout(p, TM_retrans);
  286                 if (p->tp_ucddata) {
  287 #ifdef ARGO_DEBUG
  288                         if (argo_debug[D_CONN]) {
  289                                 printf("dropping user connect data cc 0x%x\n",
  290                                        p->tp_ucddata->m_len);
  291                         }
  292 #endif
  293                         m_freem(p->tp_ucddata);
  294                         p->tp_ucddata = 0;
  295                 }
  296                 soisconnected(p->tp_sock);
  297                 if (e->ev_union.EV_CC_TPDU.e_datalen > 0) {
  298                         ASSERT(p->tp_Xrcv.sb_cc == 0);  /* should be empty */
  299                         sbappendrecord(&p->tp_Xrcv,
  300                                         e->ev_union.EV_CC_TPDU.e_data);
  301                         e->ev_union.EV_CC_TPDU.e_data = NULL;
  302                 }
  303                 (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  304                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  305                 break;
  306         case 0x16:
  307                 IncStat(ts_retrans_cr);
  308                 p->tp_cong_win = 1 * p->tp_l_tpdusize;
  309                 data = MCPY(p->tp_ucddata, M_NOWAIT);
  310                 if (p->tp_ucddata) {
  311 #ifdef ARGO_DEBUG
  312                         if (argo_debug[D_CONN]) {
  313                                 printf("TM_retrans.trans m_copy cc %p\n",
  314                                         data);
  315                                 dump_mbuf(p->tp_ucddata, "sosnd @ TM_retrans");
  316                         }
  317 #endif
  318                         if (data == NULL)
  319                                 return ENOBUFS;
  320                 }
  321                 p->tp_retrans--;
  322                 if ((error = tp_emit(CR_TPDU_type, p, 0, 0, data)) != 0) {
  323                         p->tp_sock->so_error = error;
  324                 }
  325                 tp_ctimeout(p, TM_retrans, (int) p->tp_cr_ticks);
  326                 break;
  327         case 0x17:
  328                 IncStat(ts_conn_gaveup);
  329                 p->tp_sock->so_error = ETIMEDOUT;
  330                 tp_indicate(T_DISCONNECT, p, ETIMEDOUT);
  331                 tp_soisdisconnected(p);
  332                 break;
  333         case 0x18:
  334                 data = MCPY(p->tp_ucddata, M_WAIT);
  335 
  336                 if ((error = tp_emit(CC_TPDU_type, p, 0, 0, data)) != 0) {
  337                         p->tp_sock->so_error = error;
  338                 }
  339                 p->tp_retrans = p->tp_Nretrans;
  340                 tp_ctimeout(p, TM_retrans, (int) p->tp_cc_ticks);
  341                 break;
  342         case 0x19:
  343                 /*
  344                  * Get rid of any confirm or connect data, so that if we
  345                  * crash or close, it isn't thought of as disconnect data.
  346                  */
  347                 if (p->tp_ucddata) {
  348                         m_freem(p->tp_ucddata);
  349                         p->tp_ucddata = 0;
  350                 }
  351                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  352                 tp_cuntimeout(p, TM_retrans);
  353                 soisconnected(p->tp_sock);
  354                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  355 
  356                 /*
  357                  * see also next 2 transitions, if you make any
  358                  * changes
  359                  */
  360 
  361                 doack = tp_stash(p, e);
  362 #ifdef ARGO_DEBUG
  363                 if (argo_debug[D_DATA]) {
  364                         printf("tp_stash returns %d\n", doack);
  365                 }
  366 #endif
  367 
  368                 if (doack) {
  369                         (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  370                         tp_ctimeout(p, TM_sendack, (int) p->tp_keepalive_ticks);
  371                 } else
  372                         tp_ctimeout(p, TM_sendack, (int) p->tp_sendack_ticks);
  373 
  374 #ifdef ARGO_DEBUG
  375                 if (argo_debug[D_DATA]) {
  376                         printf("after stash calling sbwakeup\n");
  377                 }
  378 #endif
  379                 break;
  380         case 0x1a:
  381                 tp0_stash(p, e);
  382                 sbwakeup(&p->tp_sock->so_rcv, POLL_IN);
  383 
  384 #ifdef ARGO_DEBUG
  385                 if (argo_debug[D_DATA]) {
  386                         printf("after stash calling sbwakeup\n");
  387                 }
  388 #endif
  389                 break;
  390         case 0x1b:
  391                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  392                 sbwakeup(&p->tp_sock->so_rcv, POLL_IN);
  393 
  394                 doack = tp_stash(p, e);
  395 #ifdef ARGO_DEBUG
  396                 if (argo_debug[D_DATA]) {
  397                         printf("tp_stash returns %d\n", doack);
  398                 }
  399 #endif
  400 
  401                 if (doack)
  402                         (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  403                 else
  404                         tp_ctimeout_MIN(p, TM_sendack, (int) p->tp_sendack_ticks);
  405 
  406 #ifdef ARGO_DEBUG
  407                 if (argo_debug[D_DATA]) {
  408                         printf("after stash calling sbwakeup\n");
  409                 }
  410 #endif
  411                 break;
  412         case 0x1c:
  413 #ifdef TPPT
  414                 if (tp_traceflags[D_DATA])
  415                         tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ",
  416                                 e->ev_union.EV_DT_TPDU.e_seq,
  417                                 p->tp_rcvnxt, p->tp_lcredit, 0);
  418 #endif
  419                 IncStat(ts_dt_niw);
  420                 m_freem(e->ev_union.EV_DT_TPDU.e_data);
  421                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  422                 (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  423                 break;
  424         case 0x1d:
  425                 if (p->tp_ucddata) {
  426                         m_freem(p->tp_ucddata);
  427                         p->tp_ucddata = 0;
  428                 }
  429                 (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq);
  430                 tp_cuntimeout(p, TM_retrans);
  431 
  432                 soisconnected(p->tp_sock);
  433 #ifdef TPPT
  434                 if (tp_traceflags[D_CONN]) {
  435                         struct socket  *so = p->tp_sock;
  436                         tptrace(TPPTmisc,
  437                         "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags",
  438                                 so, so->so_state, so->so_rcv.sb_sel,
  439                                 so->so_rcv.sb_flags);
  440                         tptrace(TPPTmisc,
  441                     "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head",
  442                                 so->so_qlen, so->so_error, so->so_rcv.sb_cc,
  443                                 so->so_head);
  444                 }
  445 #endif
  446 
  447                 tp_ctimeout(p, TM_sendack, (int) p->tp_keepalive_ticks);
  448                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  449                 break;
  450         case 0x1e:
  451                 if (p->tp_state == TP_AKWAIT) {
  452                         if (p->tp_ucddata) {
  453                                 m_freem(p->tp_ucddata);
  454                                 p->tp_ucddata = 0;
  455                         }
  456                         tp_cuntimeout(p, TM_retrans);
  457                         soisconnected(p->tp_sock);
  458                         tp_ctimeout(p, TM_sendack, (int) p->tp_keepalive_ticks);
  459                         tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  460                 }
  461 #ifdef TPPT
  462                 if (tp_traceflags[D_XPD]) {
  463                         tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, "
  464                                 "e_seq datalen m_len\n", p->tp_Xrcvnxt,
  465                                 e->ev_union.EV_XPD_TPDU.e_seq,
  466                                 e->ev_union.EV_XPD_TPDU.e_datalen,
  467                                 e->ev_union.EV_XPD_TPDU.e_data->m_len);
  468                 }
  469 #endif
  470 
  471                 p->tp_sock->so_state |= SS_RCVATMARK;
  472                 e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR;
  473                 sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data);
  474 #ifdef ARGO_DEBUG
  475                 if (argo_debug[D_XPD]) {
  476                         dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv");
  477                 }
  478 #endif
  479                 tp_indicate(T_XDATA, p, 0);
  480                 sbwakeup(&p->tp_Xrcv, POLL_IN);
  481 
  482                 (void) tp_emit(XAK_TPDU_type, p, p->tp_Xrcvnxt, 0, NULL);
  483                 SEQ_INC(p, p->tp_Xrcvnxt);
  484                 break;
  485         case 0x1f:
  486                 if (p->tp_Xrcv.sb_cc == 0) {
  487                         /* kludge for select(): */
  488                         /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */
  489                 }
  490                 break;
  491         case 0x20:
  492 #ifdef TPPT
  493                 if (tp_traceflags[D_XPD])
  494                         tptrace(TPPTmisc,
  495                         "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n",
  496                                 p->tp_Xrcvnxt, e->ev_union.EV_XPD_TPDU.e_seq,
  497                                 p->tp_Xrcv.sb_cc, 0);
  498 #endif
  499                 if (p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq)
  500                         IncStat(ts_xpd_niw);
  501                 if (p->tp_Xrcv.sb_cc) {
  502                         /* might as well kick 'em again */
  503                         tp_indicate(T_XDATA, p, 0);
  504                         IncStat(ts_xpd_dup);
  505                 }
  506                 m_freem(e->ev_union.EV_XPD_TPDU.e_data);
  507                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  508                 /*
  509                  * don't send an xack because the xak gives "last one
  510                  * received", not "next one i expect" (dumb)
  511                  */
  512                 break;
  513         case 0x21:
  514                 /* detach from parent socket so it can finish closing */
  515                 if (so->so_head) {
  516                         if (!soqremque(so, 0) && !soqremque(so, 1))
  517                                 panic("tp: T_DETACH");
  518                         so->so_head = 0;
  519                 }
  520                 tp_soisdisconnecting(p->tp_sock);
  521                 tp_netcmd(p, CONN_CLOSE);
  522                 tp_soisdisconnected(p);
  523                 break;
  524         case 0x22:
  525                 /* detach from parent socket so it can finish closing */
  526                 if (so->so_head) {
  527                         if (!soqremque(so, 0) && !soqremque(so, 1))
  528                                 panic("tp: T_DETACH");
  529                         so->so_head = 0;
  530                 }
  531                 if (p->tp_state != TP_CLOSING) {
  532                         tp_soisdisconnecting(p->tp_sock);
  533                         data = MCPY(p->tp_ucddata, M_NOWAIT);
  534                         (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NORMAL_DISC, data);
  535                         p->tp_retrans = p->tp_Nretrans;
  536                         tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  537                 }
  538                 break;
  539         case 0x23:
  540                 tp_soisdisconnecting(p->tp_sock);
  541                 tp_netcmd(p, CONN_CLOSE);
  542                 tp_soisdisconnected(p);
  543                 break;
  544         case 0x24:
  545                 data = MCPY(p->tp_ucddata, M_WAIT);
  546 
  547                 if (p->tp_state == TP_OPEN) {
  548                         tp_euntimeout(p, TM_data_retrans);      /* all */
  549                         tp_cuntimeout(p, TM_inact);
  550                         tp_cuntimeout(p, TM_sendack);
  551                         p->tp_flags &= ~TPF_DELACK;
  552                 }
  553                 if (data) {
  554 #ifdef ARGO_DEBUG
  555                         if (argo_debug[D_CONN]) {
  556                                 printf("T_DISC_req.trans tp_ucddata %p\n",
  557                                        p->tp_ucddata);
  558                                 dump_mbuf(data, "ucddata @ T_DISC_req");
  559                         }
  560 #endif
  561                 }
  562                 tp_soisdisconnecting(p->tp_sock);
  563                 p->tp_retrans = p->tp_Nretrans;
  564                 tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  565 
  566                 if (trick_hc)
  567                         return tp_emit(DR_TPDU_type, p, 0,
  568                                        e->ev_union.EV_REQ_TPDU.e_reason,
  569                                        data);
  570                 break;
  571         case 0x25:
  572                 data = MCPY(p->tp_ucddata, M_WAIT);
  573 
  574                 IncStat(ts_retrans_cc);
  575                 p->tp_retrans--;
  576                 p->tp_cong_win = 1 * p->tp_l_tpdusize;
  577 
  578                 if ((error = tp_emit(CC_TPDU_type, p, 0, 0, data)) != 0)
  579                         p->tp_sock->so_error = error;
  580                 tp_ctimeout(p, TM_retrans, (int) p->tp_cc_ticks);
  581                 break;
  582         case 0x26:
  583                 IncStat(ts_conn_gaveup);
  584                 tp_soisdisconnecting(p->tp_sock);
  585                 p->tp_sock->so_error = ETIMEDOUT;
  586                 tp_indicate(T_DISCONNECT, p, ETIMEDOUT);
  587                 (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST, NULL);
  588                 p->tp_retrans = p->tp_Nretrans;
  589                 tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  590                 break;
  591         case 0x27:
  592                 tp_euntimeout(p, TM_data_retrans);      /* all */
  593                 tp_cuntimeout(p, TM_inact);
  594                 tp_cuntimeout(p, TM_sendack);
  595 
  596                 IncStat(ts_conn_gaveup);
  597                 tp_soisdisconnecting(p->tp_sock);
  598                 p->tp_sock->so_error = ETIMEDOUT;
  599                 tp_indicate(T_DISCONNECT, p, ETIMEDOUT);
  600                 (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST_2, NULL);
  601                 p->tp_retrans = p->tp_Nretrans;
  602                 tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  603                 break;
  604         case 0x28:
  605                 p->tp_cong_win = 1 * p->tp_l_tpdusize;
  606                 /* resume XPD */
  607                 if (p->tp_Xsnd.sb_mb) {
  608                         struct mbuf    *m = m_copy(p->tp_Xsnd.sb_mb, 0,
  609                                                    (int) p->tp_Xsnd.sb_cc);
  610                         int             shift;
  611 
  612 #ifdef TPPT
  613                         if (tp_traceflags[D_XPD]) {
  614                                 tptrace(TPPTmisc,
  615                                 "XPD retrans: Xuna Xsndnxt sndnxt snduna",
  616                                         p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndnxt,
  617                                         p->tp_snduna);
  618                         }
  619 #endif
  620 #ifdef ARGO_DEBUG
  621                         if (argo_debug[D_XPD]) {
  622                                 dump_mbuf(m, "XPD retrans emitting M");
  623                         }
  624 #endif
  625                         IncStat(ts_retrans_xpd);
  626                         p->tp_retrans--;
  627                         shift = max(p->tp_Nretrans - p->tp_retrans, 6);
  628                         (void) tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m);
  629                         tp_ctimeout(p, TM_retrans, ((int) p->tp_dt_ticks) << shift);
  630                 }
  631                 break;
  632         case 0x29:
  633                 p->tp_rxtshift++;
  634                 (void) tp_data_retrans(p);
  635                 break;
  636         case 0x2a:
  637                 p->tp_retrans--;
  638                 (void) tp_emit(DR_TPDU_type, p, 0, E_TP_DR_NO_REAS, NULL);
  639                 IncStat(ts_retrans_dr);
  640                 tp_ctimeout(p, TM_retrans, (int) p->tp_dr_ticks);
  641                 break;
  642         case 0x2b:
  643                 p->tp_sock->so_error = ETIMEDOUT;
  644                 p->tp_refstate = REF_FROZEN;
  645                 tp_recycle_tsuffix(p);
  646                 tp_etimeout(p, TM_reference, (int) p->tp_refer_ticks);
  647                 break;
  648         case 0x2c:
  649                 tp_freeref(p->tp_lref);
  650                 tp_detach(p);
  651                 break;
  652         case 0x2d:
  653                 if (p->tp_class != TP_CLASS_0) {
  654                         tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  655                         if (e->ev_number == CC_TPDU)
  656                                 (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  657                 }
  658                 /*
  659                  * ignore it if class 0 - state tables are blank for
  660                  * this
  661                  */
  662                 break;
  663         case 0x2e:
  664 #ifdef TPPT
  665                 if (tp_traceflags[D_DATA])
  666                         tptrace(TPPTmisc,
  667                         "T_DATA_req sndnxt snduna fcredit, tpcb",
  668                                 p->tp_sndnxt, p->tp_snduna, p->tp_fcredit, p);
  669 #endif
  670 
  671                 tp_send(p);
  672                 break;
  673         case 0x2f:
  674                 error = 0;
  675 
  676                 /* resume XPD */
  677                 if (p->tp_Xsnd.sb_mb) {
  678                         struct mbuf    *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int) p->tp_Xsnd.sb_cc);
  679                         /*
  680                          * m_copy doesn't preserve the m_xlink field,
  681                          * but at this pt. that doesn't matter
  682                          */
  683 
  684 #ifdef TPPT
  685                         if (tp_traceflags[D_XPD])
  686                                 tptrace(TPPTmisc,
  687                                 "XPD req: Xuna Xsndnxt sndnxt snduna",
  688                                         p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndnxt,
  689                                         p->tp_snduna);
  690 #endif
  691 #ifdef ARGO_DEBUG
  692                         if (argo_debug[D_XPD]) {
  693                                 printf("T_XPD_req: sb_cc 0x%lx\n", p->tp_Xsnd.sb_cc);
  694                                 dump_mbuf(m, "XPD req emitting M");
  695                         }
  696 #endif
  697                         error =
  698                                 tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m);
  699                         p->tp_retrans = p->tp_Nretrans;
  700 
  701                         tp_ctimeout(p, TM_retrans, (int) p->tp_rxtcur);
  702                         SEQ_INC(p, p->tp_Xsndnxt);
  703                 }
  704                 if (trick_hc)
  705                         return error;
  706                 break;
  707         case 0x30:
  708                 sb = &p->tp_sock->so_snd;
  709 
  710 #ifdef ARGO_DEBUG
  711                 if (argo_debug[D_ACKRECV]) {
  712                         printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_cdt);
  713                 }
  714 #endif
  715                 if (p->tp_class != TP_CLASS_0) {
  716                         tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  717                 }
  718                 sbwakeup(sb, POLL_OUT);
  719 #ifdef ARGO_DEBUG
  720                 if (argo_debug[D_ACKRECV]) {
  721                         printf("GOOD ACK new sndnxt 0x%x\n", p->tp_sndnxt);
  722                 }
  723 #endif
  724                 break;
  725         case 0x31:
  726 #ifdef TPPT
  727                 if (tp_traceflags[D_ACKRECV])
  728                         tptrace(TPPTmisc,
  729                                 "BOGUS ACK fcc_present, tp_r_subseq e_subseq",
  730                                 e->ev_union.EV_AK_TPDU.e_fcc_present,
  731                                 p->tp_r_subseq,
  732                                 e->ev_union.EV_AK_TPDU.e_subseq, 0);
  733 #endif
  734                 if (p->tp_class != TP_CLASS_0) {
  735 
  736                         if (!e->ev_union.EV_AK_TPDU.e_fcc_present) {
  737                                 /* send ACK with FCC */
  738                                 IncStat(ts_ackreason[_ACK_FCC_]);
  739                                 (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt,
  740                                                1, NULL);
  741                         }
  742                         tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  743                 }
  744                 break;
  745         case 0x32:
  746                 tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  747                 tp_cuntimeout(p, TM_retrans);
  748 
  749                 sbwakeup(&p->tp_sock->so_snd, POLL_OUT);
  750 
  751                 /* resume normal data */
  752                 tp_send(p);
  753                 break;
  754         case 0x33:
  755 #ifdef TPPT
  756                 if (tp_traceflags[D_ACKRECV])
  757                         tptrace(TPPTmisc, "BOGUS XACK eventtype ",
  758                                 e->ev_number, 0, 0, 0);
  759 #endif
  760                 if (p->tp_class != TP_CLASS_0) {
  761                         tp_ctimeout(p, TM_inact, (int) p->tp_inact_ticks);
  762                 }
  763                 break;
  764         case 0x34:
  765 #ifdef TPPT
  766                 if (tp_traceflags[D_TIMER])
  767                         tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe,
  768                                 p->tp_sent_lcdt, 0);
  769 #endif
  770                 IncPStat(p, tps_n_TMsendack);
  771                 (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  772                 if (p->tp_fcredit == 0) {
  773                         if (p->tp_rxtshift < TP_MAXRXTSHIFT)
  774                                 p->tp_rxtshift++;
  775                         timo = (p->tp_dt_ticks) << p->tp_rxtshift;
  776                 } else
  777                         timo = p->tp_sendack_ticks;
  778                 tp_ctimeout(p, TM_sendack, timo);
  779                 break;
  780         case 0x35:
  781                 if (sbspace(&p->tp_sock->so_rcv) > 0)
  782                         tp0_openflow(p);
  783                 break;
  784         case 0x36:
  785                 if (trick_hc) {
  786                         SeqNum          ack_thresh;
  787                         /*
  788                          * If the upper window edge has advanced a reasonable
  789                          * amount beyond what was known, send an ACK.
  790                          * A reasonable amount is 2 packets, unless the max window
  791                          * is only 1 or 2 packets, in which case we
  792                          * should send an ack for any advance in the upper window edge.
  793                          */
  794                         LOCAL_CREDIT(p);
  795                         ack_thresh = SEQ_SUB(p, p->tp_lcredit + p->tp_rcvnxt,
  796                                     (p->tp_maxlcredit > 2 ? 2 : 1));
  797                         if (SEQ_GT(p, ack_thresh, p->tp_sent_uwe)) {
  798                                 IncStat(ts_ackreason[_ACK_USRRCV_]);
  799                                 p->tp_flags &= ~TPF_DELACK;
  800                                 return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, NULL);
  801                         }
  802                 }
  803                 break;
  804         case 0x37:
  805                 if (trick_hc)
  806                         return ECONNABORTED;
  807                 break;
  808         case 0x38:
  809                 ASSERT(p->tp_state != TP_LISTENING);
  810                 tp_indicate(T_DISCONNECT, p, ECONNRESET);
  811                 tp_soisdisconnected(p);
  812                 break;
  813         }
  814         return 0;
  815 }
  816 
  817 static int
  818 _Xebec_index(e, p)
  819         struct tp_event *e;
  820         struct tp_pcb  *p;
  821 {
  822         switch ((e->ev_number << 4) + (p->tp_state)) {
  823         case 0x12:
  824                 if (p->tp_retrans > 0)
  825                         return 0x1e;
  826                 else
  827                         return 0x1f;
  828         case 0x13:
  829                 if (p->tp_retrans > 0)
  830                         return 0x2f;
  831                 else
  832                         return 0x30;
  833         case 0x14:
  834                 if (p->tp_retrans > 0)
  835                         return 0x32;
  836                 else
  837                         return 0x31;
  838         case 0x15:
  839                 if (p->tp_retrans > 0)
  840                         return 0x34;
  841                 else
  842                         return 0x35;
  843         case 0x54:
  844                 if (p->tp_rxtshift < TP_NRETRANS)
  845                         return 0x33;
  846                 else
  847                         return 0x31;
  848         case 0x64:
  849                 if (p->tp_class == TP_CLASS_0)
  850                         return 0x1a;
  851                 else
  852                         return 0x1b;
  853         case 0x77:
  854                 if (p->tp_class == TP_CLASS_0)
  855                         return 0xd;
  856                 else
  857                         return 0xe;
  858         case 0x86:
  859                 if (e->ev_union.EV_DR_TPDU.e_sref != 0)
  860                         return 0x2;
  861                 else
  862                         return 0x3;
  863         case 0xa2:
  864                 if (p->tp_class == TP_CLASS_0)
  865                         return 0x1c;
  866                 else
  867                         return 0x1d;
  868         case 0xb2:
  869                 if (p->tp_class == TP_CLASS_0)
  870                         return 0x5;
  871                 else
  872                         return 0x0;
  873         case 0xb4:
  874                 if (tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq))
  875                         return 0x3a;
  876                 else
  877                         return 0x3b;
  878         case 0xc3:
  879                 if (IN_RWINDOW(p, e->ev_union.EV_DT_TPDU.e_seq,
  880                         p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)))
  881                         return 0x21;
  882                 else
  883                         return 0x24;
  884         case 0xc4:
  885                 if (p->tp_class == TP_CLASS_0)
  886                         return 0x22;
  887                 else if (IN_RWINDOW(p, e->ev_union.EV_DT_TPDU.e_seq,
  888                         p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)))
  889                         return 0x23;
  890                 else
  891                         return 0x25;
  892         case 0xd3:
  893                 if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq)
  894                         return 0x27;
  895                 else
  896                         return 0x2a;
  897         case 0xd4:
  898                 if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq)
  899                         return 0x27;
  900                 else
  901                         return 0x29;
  902         case 0xe4:
  903                 if (tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq))
  904                         return 0x3c;
  905                 else
  906                         return 0x3d;
  907         case 0x102:
  908                 if (p->tp_class == TP_CLASS_0)
  909                         return 0x2d;
  910                 else
  911                         return 0x2e;
  912         case 0x104:
  913                 if (p->tp_class == TP_CLASS_0)
  914                         return 0x2d;
  915                 else
  916                         return 0x2e;
  917         case 0x144:
  918                 if (p->tp_class == TP_CLASS_0)
  919                         return 0x3f;
  920                 else
  921                         return 0x40;
  922         case 0x162:
  923                 if (p->tp_class == TP_CLASS_0)
  924                         return 0x2b;
  925                 else
  926                         return 0x2c;
  927         case 0x172:
  928                 if (p->tp_class != TP_CLASS_4)
  929                         return 0x42;
  930                 else
  931                         return 0x46;
  932         case 0x174:
  933                 if (p->tp_class != TP_CLASS_4)
  934                         return 0x42;
  935                 else
  936                         return 0x47;
  937         case 0x177:
  938                 if (p->tp_class != TP_CLASS_4)
  939                         return 0x42;
  940                 else
  941                         return 0x43;
  942         case 0x188:
  943                 if (p->tp_class == TP_CLASS_0)
  944                         return 0xf;
  945                 else if (tp_emit(CC_TPDU_type, p, 0, 0, MCPY(p->tp_ucddata, M_NOWAIT)) == 0)
  946                         return 0x10;
  947                 else
  948                         return 0x11;
  949         default:
  950                 return 0;
  951         }                       /* end switch */
  952 }                               /* _Xebec_index() */
  953 static const int inx[26][9] =
  954 {
  955     {0, 0, 0, 0, 0, 0, 0, 0, 0,},
  956     {0x0, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0,},
  957     {0x0, 0x0, -1, -1, -1, -1, 0x0, 0x0, 0x0,},
  958     {0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0,},
  959     {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,},
  960     {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0,},
  961     {0x0, 0x0, 0x0, 0x0, -1, 0x0, 0x0, 0x0, 0x0,},
  962     {0x0, 0x7, 0x15, 0x1b, -1, 0x17, 0x3, 0xa, 0x0,},
  963     {0x0, 0x19, 0x6, 0x20, 0x37, 0x8, 0x3, -1, 0x0,},
  964     {0x0, 0x14, 0x13, 0x13, 0x13, 0x16, -1, 0xa, 0x0,},
  965     {0x0, 0x7, 0x6, 0x1, 0x9, 0x18, 0x3, 0xa, 0x0,},
  966     {0x0, 0x19, -1, 0x1, 0x37, 0x8, 0x3, 0xa, 0x0,},
  967     {0x0, 0x7, -1, 0x26, -1, 0x8, 0x3, 0xa, 0x0,},
  968     {0x0, 0x7, 0x6, -1, -1, 0x8, 0x3, 0xa, 0x0,},
  969     {0x0, 0x7, 0x6, -1, -1, 0x8, 0x3, 0xa, 0x0,},
  970     {0x0, 0x7, 0x6, 0x1, -1, 0x8, 0x3, 0xa, 0x0,},
  971     {0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,},
  972     {0x0, 0x0, -1, 0x2e, -1, 0x0, 0x4, 0x0, 0x2e,},
  973     {0x0, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,},
  974     {0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0,},
  975     {0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0,},
  976     {0x0, 0x0, 0x0, 0x0, -1, 0x0, 0x41, 0x0, 0x0,},
  977     {0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x41, 0x0, 0x0,},
  978     {0x0, 0xc, -1, 0x2c, 0x0, 0x2c, 0x4, 0xc, 0x2c,},
  979     {0x0, 0x49, -1, 0x45, -1, 0x44, 0x48, -1, 0x0,},
  980     {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -1,},
  981 };
  982 int
  983 tp_driver(struct tp_pcb *p, struct tp_event *e)
  984 {
  985         int    index, error = 0;
  986         const struct act_ent *a;
  987         static const struct act_ent erroraction = {0, -1};
  988 
  989         index = inx[1 + e->ev_number][p->tp_state];
  990         if (index < 0)
  991                 index = _Xebec_index(e, p);
  992         if (index == 0) {
  993                 a = &erroraction;
  994         } else
  995                 a = &statetable[index];
  996 
  997         if (a->a_action)
  998                 error = _Xebec_action(a->a_action, e, p);
  999 #ifdef TPPT
 1000         if (tp_traceflag[D_DRIVER])
 1001                 tptrace(DRIVERTRACE, a->a_newstate, p->tp_state,
 1002                         e->ev_number, a->a_action, 0);
 1003 #endif
 1004         if (error == 0)
 1005                 p->tp_state = a->a_newstate;
 1006         return error;
 1007 }

Cache object: a0df32cb473201dc7a4b55b46a6de74a


[ 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.