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

Cache object: 992b23e48b2fac3f41e4dcdf6818c35e


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