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_emit.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_emit.c,v 1.25 2006/09/07 02:40:33 dogcow Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)tp_emit.c   8.1 (Berkeley) 6/10/93
   32  */
   33 
   34 /***********************************************************
   35                 Copyright IBM Corporation 1987
   36 
   37                       All Rights Reserved
   38 
   39 Permission to use, copy, modify, and distribute this software and its
   40 documentation for any purpose and without fee is hereby granted,
   41 provided that the above copyright notice appear in all copies and that
   42 both that copyright notice and this permission notice appear in
   43 supporting documentation, and that the name of IBM not be
   44 used in advertising or publicity pertaining to distribution of the
   45 software without specific, written prior permission.
   46 
   47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   53 SOFTWARE.
   54 
   55 ******************************************************************/
   56 
   57 /*
   58  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
   59  */
   60 /*
   61  * This file contains tp_emit() and tp_error_emit(), which form TPDUs and
   62  * hand them to ip. They take data in the form of mbuf chain, allocate mbufs
   63  * as necessary for headers, and set the fields as appropriate from
   64  * information found in the tpcb and net-level pcb.
   65  *
   66  * The worst thing about this code is adding the variable-length options on a
   67  * machine that requires alignment for any memory access that isn't of size
   68  * 1.  See the macro ADDOPTION() below.
   69  *
   70  * We don't do any concatenation. (There's a kludge to test the basic mechanism
   71  * of separation under the 'w' tpdebug option, that's all.)
   72  */
   73 
   74 #include <sys/cdefs.h>
   75 __KERNEL_RCSID(0, "$NetBSD: tp_emit.c,v 1.25 2006/09/07 02:40:33 dogcow Exp $");
   76 
   77 #include "opt_iso.h"
   78 
   79 #include <sys/param.h>
   80 #include <sys/systm.h>
   81 #include <sys/mbuf.h>
   82 #include <sys/socket.h>
   83 #include <sys/socketvar.h>
   84 #include <sys/protosw.h>
   85 #include <sys/errno.h>
   86 #include <sys/time.h>
   87 
   88 #include <net/if.h>
   89 
   90 #include <netiso/iso.h>
   91 #include <netiso/iso_pcb.h>
   92 #include <netiso/argo_debug.h>
   93 #include <netiso/tp_timer.h>
   94 #include <netiso/tp_param.h>
   95 #include <netiso/tp_stat.h>
   96 #include <netiso/tp_pcb.h>
   97 #include <netiso/tp_tpdu.h>
   98 #include <netiso/tp_trace.h>
   99 #include <netiso/tp_meas.h>
  100 #include <netiso/tp_seq.h>
  101 #include <netiso/tp_var.h>
  102 #include <netiso/iso_errno.h>
  103 #include <netiso/iso_var.h>
  104 
  105 /*
  106  * Here is a mighty kludge.  The token ring misorders packets if you fire
  107  * them at it too fast, and TP sans checksum is "too fast", so we have
  108  * introduced a delay when checksumming isn't used.
  109  */
  110 char            tp_delay = 0x00;/* delay to keep token ring from blowing it */
  111 
  112 /*
  113  * NAME:        tp_emit()
  114  *
  115  * CALLED FROM: tp.trans and from tp_sbsend()
  116  *
  117  * FUNCTION and ARGUMENTS:
  118  *      Emits one tpdu of the type (dutype), of the format appropriate
  119  *      to the connection described by the pcb (tpcb), with sequence
  120  *      number (seq) (where appropriate), end-of-tsdu bit (eot) where
  121  *      appropriate, and with the data in the mbuf chain (data).
  122  *      For DR and ER tpdus, the argument (eot) is
  123  *      the reason for issuing the tpdu rather than an end-of-tsdu indicator.
  124  *
  125  * RETURNS:
  126  *      0  OK
  127  *      ENOBUFS
  128  *      E* returned from net layer output rtn
  129  *
  130  * SIDE EFFECTS:
  131  *
  132  * NOTES:
  133  *
  134  *      WE ASSUME that the tp header + all options will fit in ONE mbuf.
  135  *      If mbufs are 256 this will most likely be true, but if they are 128 it's
  136  *      possible that they won't.
  137  *      If you used every option on the CR + max. user data you'd overrun
  138  *      112 but unless you used > 115 bytes for the security
  139  *      parameter, it would fit in a 256-byte mbuf (240 bytes for the header)
  140  *      We don't support the security parameter, so this isn't a problem.
  141  *      If security is added, we ought to remove this assumption.
  142  *
  143  *  We do not implement the flow control confirmation "element of procedure".
  144  *  A) it should not affect interoperability,
  145  *  B) it should not be necessary - the protocol will eventually
  146  *      straighten things out w/o FCC, as long as we don't have severely
  147  *              mismatched keepalive and inactivity timers, and
  148  *      C) it appears not to be REQUIRED, and
  149  *  D) it's incredibly grotesque, and no doubt will lengthen a few
  150  *      critical paths.
  151  *  HOWEVER, we're thinking about putting it in anyway, for
  152  *  completeness, just like we did with ack subsequencing.
  153  */
  154 
  155 int
  156 tp_emit(
  157         int             dutype,
  158         struct tp_pcb  *tpcb,
  159         SeqNum          seq,
  160         u_int           eot,
  161         struct mbuf    *data)
  162 {
  163         struct tpdu *hdr;
  164         struct mbuf *m;
  165         int             csum_offset = 0;
  166         int             datalen = 0;
  167         int             error = 0;
  168         SeqNum          olduwe;
  169         int             acking_ooo;
  170 
  171         /*
  172          * NOTE: here we treat tpdu_li as if it DID include the li field, up
  173          * until the end, at which time we subtract 1 THis is because if we
  174          * subtract 1 right away, we end up adding one every time we add an
  175          * option.
  176          */
  177 #ifdef ARGO_DEBUG
  178         if (argo_debug[D_EMIT]) {
  179                 printf(
  180                        "tp_emit dutype 0x%x, tpcb %p, eot 0x%x, seq 0x%x, data %p",
  181                        dutype, tpcb, eot, seq, data);
  182         }
  183 #endif
  184 
  185         if (dutype == CR_TPDU || dutype == CC_TPDU) {
  186                 m = (struct mbuf *) malloc((u_long) 256, M_MBUF, M_DONTWAIT);
  187                 if (m) {
  188                         m->m_type = TPMT_TPHDR;
  189                         mbstat.m_mtypes[TPMT_TPHDR]++;
  190                         m->m_next = NULL;
  191                         m->m_nextpkt = NULL;
  192                         m->m_data = m->m_pktdat;
  193                         m->m_flags = M_PKTHDR;
  194                         bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
  195                 }
  196         } else {
  197                 MGETHDR(m, M_DONTWAIT, TPMT_TPHDR);
  198         }
  199         if (m == NULL) {
  200                 if (data != (struct mbuf *) 0)
  201                         m_freem(data);
  202                 error = ENOBUFS;
  203                 goto done;
  204         }
  205         m->m_data += max_hdr;
  206         m->m_len = sizeof(struct tpdu);
  207         m->m_nextpkt = NULL;
  208 
  209         hdr = mtod(m, struct tpdu *);
  210         bzero((caddr_t) hdr, sizeof(struct tpdu));
  211 
  212         {
  213                 hdr->tpdu_type = dutype;
  214                 hdr->tpdu_li = tp_headersize(dutype, tpcb);
  215                 /*
  216                  * class 0 doesn't use this for DT
  217                  * it'll just get overwritten below
  218                  */
  219                 hdr->tpdu_dref = htons(tpcb->tp_fref);
  220                 if (tpcb->tp_use_checksum ||
  221                 (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4))) {
  222                         csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */
  223                         ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */ );
  224 #ifdef ARGO_DEBUG
  225                         if (argo_debug[D_CHKSUM]) {
  226                                 printf(
  227                                        "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  228                                        csum_offset, hdr->tpdu_li);
  229                         }
  230 #endif
  231                 }
  232                 /*
  233                  * VARIABLE PARTS...
  234                  */
  235                 switch (dutype) {
  236 
  237                 case CR_TPDU_type:
  238                         hdr->tpdu_CRdref_0 = 0; /* must be zero */
  239                 case CC_TPDU_type:
  240                         if (!tpcb->tp_cebit_off) {
  241                                 tpcb->tp_win_recv = tp_start_win << 8;
  242                                 LOCAL_CREDIT(tpcb);
  243                                 CONG_INIT_SAMPLE(tpcb);
  244                         } else
  245                                 LOCAL_CREDIT(tpcb);
  246 
  247                         /* Case CC_TPDU_type used to be here */
  248                         {
  249                                 u_char          x;
  250 
  251                                 hdr->tpdu_CCsref = htons(tpcb->tp_lref);        /* same as CRsref */
  252 
  253                                 if (tpcb->tp_class > TP_CLASS_1) {
  254                                         tpcb->tp_sent_uwe = tpcb->tp_lcredit - 1;
  255                                         tpcb->tp_sent_rcvnxt = 1;
  256                                         tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
  257                                         hdr->tpdu_cdt = tpcb->tp_lcredit;
  258                                 } else {
  259 #ifdef TPCONS
  260                                         if (tpcb->tp_netservice == ISO_CONS) {
  261                                                 struct isopcb  *isop = (struct isopcb *) tpcb->tp_npcb;
  262                                                 struct pklcd   *lcp = (struct pklcd *) (isop->isop_chan);
  263                                                 lcp->lcd_flags &= ~X25_DG_CIRCUIT;
  264                                         }
  265 #endif
  266                                         hdr->tpdu_cdt = 0;
  267                                 }
  268                                 hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class);
  269                                 hdr->tpdu_CCoptions =
  270                                         (tpcb->tp_xtd_format ? TPO_XTD_FMT : 0) |
  271                                         (tpcb->tp_use_efc ? TPO_USE_EFC : 0);
  272 
  273 #ifdef TP_PERF_MEAS
  274                                 if (DOPERF(tpcb)) {
  275                                         u_char  perf_meas = tpcb->tp_perf_on;
  276                                         ADDOPTION(TPP_perf_meas, hdr,
  277                                                   sizeof(perf_meas), perf_meas);
  278                                 }
  279 #endif
  280 
  281                                         if (dutype == CR_TPDU_type) {
  282                                         IncStat(ts_CR_sent);
  283 
  284                                         ASSERT(tpcb->tp_lsuffixlen > 0);
  285                                         ASSERT(tpcb->tp_fsuffixlen > 0);
  286 
  287                                         ADDOPTION(TPP_calling_sufx, hdr,
  288                                                   tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]);
  289                                         ADDOPTION(TPP_called_sufx, hdr,
  290                                                   tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]);
  291                                 } else {
  292                                         IncStat(ts_CC_sent);
  293                                 }
  294 
  295                                 ADDOPTION(TPP_tpdu_size, hdr,
  296                                           sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize);
  297 
  298                                 if (tpcb->tp_class != TP_CLASS_0) {
  299                                         short           millisec = 500 * (tpcb->tp_sendack_ticks);
  300 
  301                                         millisec = htons(millisec);
  302                                         ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec);
  303 
  304                                         x = (tpcb->tp_use_nxpd ? TPAO_USE_NXPD : 0)
  305                                                 | (tpcb->tp_use_rcc ? TPAO_USE_RCC : 0)
  306                                                 | (tpcb->tp_use_checksum ? 0 : TPAO_NO_CSUM)
  307                                                 | (tpcb->tp_xpd_service ? TPAO_USE_TXPD : 0);
  308                                         ADDOPTION(TPP_addl_opt, hdr, 1, x);
  309 
  310                                         if ((tpcb->tp_l_tpdusize ^ (1 << tpcb->tp_tpdusize)) != 0) {
  311                                                 u_short         size_s = tpcb->tp_l_tpdusize >> 7;
  312                                                 u_char          size_c = size_s;
  313                                                 ASSERT(tpcb->tp_l_tpdusize < 65536 * 128);
  314                                                 if (dutype == CR_TPDU_type)
  315                                                         tpcb->tp_ptpdusize = size_s;
  316                                                 if (size_s < 256) {
  317                                                         ADDOPTION(TPP_ptpdu_size, hdr, 1, size_c);
  318                                                 } else {
  319                                                         size_s = htons(size_s);
  320                                                         ADDOPTION(TPP_ptpdu_size, hdr, 2, size_s);
  321                                                 }
  322                                         }
  323                                 }
  324                                 if ((dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)) {
  325 
  326                                         ASSERT(1 == sizeof(tpcb->tp_vers));
  327                                         ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers);
  328 
  329                                         /*
  330                                          * for each alt protocol class x, x =
  331                                          * x<<4; option = concat(option, x);
  332                                          * Well, for now we only have TP0 for
  333                                          * an alternative so... this is easy.
  334                                          *
  335                                          * HOWEVER... There should be NO alt
  336                                          * protocol class over CLNS.  Need to
  337                                          * see if the route suggests CONS,
  338                                          * and iff so add alt class.
  339                                          */
  340                                         x = 0;
  341                                         ADDOPTION(TPP_alt_class, hdr, 1, x);
  342                                 }
  343 #if 0
  344                                 if (hdr->tpdu_li > MLEN)
  345                                         panic("tp_emit CR/CC");
  346 #endif
  347                         }
  348                         break;
  349 
  350                 case DR_TPDU_type:
  351                         if (hdr->tpdu_DRdref == 0) {
  352                                 /* don't issue the DR */
  353                                 goto done;
  354                         }
  355                         hdr->tpdu_cdt = 0;
  356                         hdr->tpdu_DRsref = htons(tpcb->tp_lref);
  357                         hdr->tpdu_DRreason = (u_char) eot;      /* WHICH BYTE OF THIS??? */
  358 
  359                         /* forget the add'l information variable part */
  360                         IncStat(ts_DR_sent);
  361                         break;
  362 
  363                 case DC_TPDU_type:      /* not used in class 0 */
  364                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  365                         hdr->tpdu_DCsref = htons(tpcb->tp_lref);
  366                         hdr->tpdu_cdt = 0;
  367                         data = (struct mbuf *) 0;
  368                         IncStat(ts_DC_sent);
  369                         break;
  370 
  371                 case XAK_TPDU_type:     /* xak not used in class 0 */
  372                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  373                         hdr->tpdu_cdt = 0;
  374 
  375 #ifdef TPPT
  376                         if (tp_traceflags[D_XPD]) {
  377                                 tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0);
  378                         }
  379 #endif
  380                         data = (struct mbuf *) 0;
  381                         if (tpcb->tp_xtd_format) {
  382 #ifdef BYTE_ORDER
  383                                 union seq_type  seqeotX;
  384 
  385                                 seqeotX.s_seq = seq;
  386                                 seqeotX.s_eot = 1;
  387                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  388 #else
  389                                 hdr->tpdu_XAKseqX = seq;
  390 #endif                          /* BYTE_ORDER */
  391                         } else {
  392                                 hdr->tpdu_XAKseq = seq;
  393                         }
  394                         IncStat(ts_XAK_sent);
  395                         IncPStat(tpcb, tps_XAK_sent);
  396                         break;
  397 
  398                 case XPD_TPDU_type:     /* xpd not used in class 0 */
  399                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  400                         hdr->tpdu_cdt = 0;
  401                         if (tpcb->tp_xtd_format) {
  402 #ifdef BYTE_ORDER
  403                                 union seq_type  seqeotX;
  404 
  405                                 seqeotX.s_seq = seq;
  406                                 seqeotX.s_eot = 1;
  407                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  408 #else
  409                                 hdr->tpdu_XPDseqX = seq;
  410                                 hdr->tpdu_XPDeotX = 1;  /* always 1 for XPD tpdu */
  411 #endif                          /* BYTE_ORDER */
  412                         } else {
  413                                 hdr->tpdu_XPDseq = seq;
  414                                 hdr->tpdu_XPDeot = 1;   /* always 1 for XPD tpdu */
  415                         }
  416                         IncStat(ts_XPD_sent);
  417                         IncPStat(tpcb, tps_XPD_sent);
  418 
  419                         /* kludge to test the input size checking */
  420 #ifdef ARGO_DEBUG
  421                         if (argo_debug[D_SIZE_CHECK]) {
  422 #if 0
  423                                  if (data->m_len <= 16 &&
  424                                      data->m_off < (MLEN-18)) {
  425                                         printf("Sending too much data on XPD: 18 bytes\n");
  426                                         data->m_len = 18;
  427                                 }
  428 #endif
  429                         }
  430 #endif
  431                         break;
  432 
  433                 case DT_TPDU_type:
  434                         hdr->tpdu_cdt = 0;
  435 #ifdef TPPT
  436                         if (tp_traceflags[D_DATA]) {
  437                                 tptraceTPCB(TPPTmisc,
  438                                             "emit DT: eot seq tpdu_li", eot,
  439                                             seq, hdr->tpdu_li, 0);
  440                         }
  441 #endif
  442                         if (tpcb->tp_xtd_format) {
  443 #ifdef BYTE_ORDER
  444                                 union seq_type  seqeotX;
  445 
  446                                 seqeotX.s_seq = seq;
  447                                 seqeotX.s_eot = eot;
  448                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  449 #else
  450                                 hdr->tpdu_DTseqX = seq;
  451                                 hdr->tpdu_DTeotX = eot;
  452 #endif                          /* BYTE_ORDER */
  453                         } else if (tpcb->tp_class == TP_CLASS_0) {
  454 #ifdef ARGO_DEBUG
  455                                 if (argo_debug[D_EMIT]) {
  456                                         printf("DT tpdu: class 0 m %p hdr %p\n", m, hdr);
  457                                         dump_buf(hdr, hdr->tpdu_li + 1);
  458                                 }
  459 #endif
  460                                 ((struct tp0du *) hdr)->tp0du_eot = eot;
  461                                 ((struct tp0du *) hdr)->tp0du_mbz = 0;
  462 #ifdef ARGO_DEBUG
  463                                 if (argo_debug[D_EMIT]) {
  464                                         printf("DT 2 tpdu: class 0 m %p hdr %p\n", m, hdr);
  465                                         dump_buf(hdr, hdr->tpdu_li + 1);
  466                                 }
  467 #endif
  468                         } else {
  469                                 hdr->tpdu_DTseq = seq;
  470                                 hdr->tpdu_DTeot = eot;
  471                         }
  472                         if (eot) {
  473                                 IncStat(ts_EOT_sent);
  474                         }
  475                         IncStat(ts_DT_sent);
  476                         IncPStat(tpcb, tps_DT_sent);
  477                         break;
  478 
  479                 case AK_TPDU_type:      /* ak not used in class 0 */
  480                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  481                         data = (struct mbuf *) 0;
  482                         olduwe = tpcb->tp_sent_uwe;
  483 
  484                         if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) {
  485                                 LOCAL_CREDIT(tpcb);
  486                                 tpcb->tp_sent_uwe =
  487                                         SEQ(tpcb, tpcb->tp_rcvnxt + tpcb->tp_lcredit - 1);
  488                                 tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
  489                                 acking_ooo = 0;
  490                         } else
  491                                 acking_ooo = 1;
  492 
  493 #ifdef ARGO_DEBUG
  494                         if (argo_debug[D_RENEG]) {
  495                                 /*
  496                                  * occasionally fake a reneging so you can test
  497                                  * subsequencing
  498                                  */
  499                                 if (olduwe & 0x1) {
  500                                         tpcb->tp_reneged = 1;
  501                                         IncStat(ts_ldebug);
  502                                 }
  503                         }
  504 #endif
  505                         /*
  506                          * Are we about to reneg on credit? When might we do
  507                          * so? a) when using optimistic credit (which we no
  508                          * longer do). b) when drain() gets implemented (not
  509                          * in the plans). c) when D_RENEG is on. d) when DEC
  510                          * BIT response is implemented. (not- when we do
  511                          * this, we'll need to implement flow control
  512                          * confirmation)
  513                          */
  514                         if (SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe)) {
  515                                 tpcb->tp_reneged = 1;
  516                                 IncStat(ts_lcdt_reduced);
  517 #ifdef TPPT
  518                                 if (tp_traceflags[D_CREDIT]) {
  519                                         tptraceTPCB(TPPTmisc,
  520                                       "RENEG: olduwe newuwe lcredit rcvnxt",
  521                                                     olduwe,
  522                                         tpcb->tp_sent_uwe, tpcb->tp_lcredit,
  523                                                     tpcb->tp_rcvnxt);
  524                                 }
  525 #endif
  526                         }
  527 #ifdef TP_PERF_MEAS
  528                         if (DOPERF(tpcb)) {
  529                                 /*
  530                                  * new lwe is less than old uwe means we're
  531                                  * acking before we received a whole window full
  532                                  */
  533                                 if (SEQ_LT(tpcb, tpcb->tp_rcvnxt, olduwe)) {
  534                                         /*
  535                                          * tmp1 = number of pkts fewer than
  536                                          * the full window
  537                                          */
  538                                         int    tmp1 =
  539                                         (int) SEQ_SUB(tpcb, olduwe,
  540                                                       tpcb->tp_rcvnxt);
  541 
  542                                         if (tmp1 > TP_PM_MAX)
  543                                                 tmp1 = TP_PM_MAX;
  544                                         IncPStat(tpcb, tps_ack_early[tmp1]);
  545 
  546                                         /*
  547                                          * tmp1 = amt of new cdt we're
  548                                          * advertising
  549                                          */
  550                                         tmp1 = SEQ_SUB(tpcb, seq,
  551                                                        tpcb->tp_sent_rcvnxt);
  552                                         if (tmp1 > TP_PM_MAX)
  553                                                 tmp1 = TP_PM_MAX;
  554 
  555                                         IncPStat(tpcb,
  556                                                  tps_cdt_acked[tmp1]
  557                                                  [((tpcb->tp_lcredit >
  558                                                     TP_PM_MAX) ?
  559                                                    TP_PM_MAX :
  560                                                    tpcb->tp_lcredit)]);
  561 
  562                                 }
  563                         }
  564 #endif
  565 
  566 #ifdef TPPT
  567                         if (tp_traceflags[D_ACKSEND]) {
  568                                 tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit,
  569                                             tpcb->tp_sent_uwe,
  570                                             tpcb->tp_r_subseq, 0);
  571                         }
  572 #endif
  573                         if (tpcb->tp_xtd_format) {
  574 #ifdef BYTE_ORDER
  575                                 union seq_type  seqeotX;
  576 
  577                                 seqeotX.s_seq = seq;
  578                                 seqeotX.s_eot = 0;
  579                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  580                                 hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit);
  581 #else
  582                                 hdr->tpdu_cdt = 0;
  583                                 hdr->tpdu_AKseqX = seq;
  584                                 hdr->tpdu_AKcdtX = tpcb->tp_lcredit;
  585 #endif                          /* BYTE_ORDER */
  586                         } else {
  587                                 hdr->tpdu_AKseq = seq;
  588                                 hdr->tpdu_AKcdt = tpcb->tp_lcredit;
  589                         }
  590                         if ((tpcb->tp_class == TP_CLASS_4) &&
  591                             (tpcb->tp_reneged || acking_ooo)) {
  592                                 /*
  593                                  * Ack subsequence parameter req'd if WE
  594                                  * reneged on credit offered.  (ISO 8073,
  595                                  * 12.2.3.8.2, p. 74)
  596                                  */
  597 #ifdef ARGO_DEBUG
  598                                 if (argo_debug[D_RENEG]) {
  599                                         printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq);
  600                                 }
  601 #endif
  602                                 tpcb->tp_s_subseq++;
  603                                 /*
  604                                  * add tmp subseq and do a htons on it.
  605                                  */
  606                                 ADDOPTION(TPP_subseq, hdr,
  607                                           sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq);
  608                         } else
  609                                 tpcb->tp_s_subseq = 0;
  610 
  611                         if (tpcb->tp_sendfcc || eot) {  /* overloaded to mean
  612                                                          * SEND FCC */
  613                                 /*
  614                                  * Rules for sending FCC ("should" send when)
  615                                  * : %a) received an ack from peer with NO
  616                                  * NEWS whatsoever, and it did not contain an
  617                                  * FCC b) received an ack from peer that
  618                                  * opens its closed window. c) received an
  619                                  * ack from peer after it reneged on its
  620                                  * offered credit, AND this ack raises UWE
  621                                  * but LWE is same and below UWE at time of
  622                                  * reneging (reduction) Now, ISO 8073
  623                                  * 12.2.3.8.3 says that a retransmitted AK
  624                                  * shall not contain the FCC parameter.  Now,
  625                                  * how the hell you tell the difference
  626                                  * between a retransmitted ack and an ack
  627                                  * that's sent in response to a received ack,
  628                                  * I don't know, because without any local
  629                                  * activity, and w/o any received DTs, they
  630                                  * will contain exactly the same credit/seq#
  631                                  * information. Anyway, given that the
  632                                  * "retransmission of acks" procedure (ISO
  633                                  * 8073 12.2.3.8.3) is optional, and we don't
  634                                  * do it (although the peer can't tell that),
  635                                  * we ignore this last rule.
  636                                  *
  637                                  * We send FCC for reasons a) and b) only. To
  638                                  * add reason c) would require a ridiculous
  639                                  * amount of state.
  640                                  *
  641                                  */
  642                                 u_short         bogus[4];       /* lwe(32), subseq(16),
  643                                                                  * cdt(16) */
  644                                 SeqNum          lwe;
  645                                 u_short         subseq, fcredit;
  646 
  647                                 tpcb->tp_sendfcc = 0;
  648 
  649                                 lwe = (SeqNum) htonl(tpcb->tp_snduna);
  650                                 subseq = htons(tpcb->tp_r_subseq);
  651                                 fcredit = htons(tpcb->tp_fcredit);
  652 
  653                                 bcopy((caddr_t) & lwe, (caddr_t) & bogus[0], sizeof(SeqNum));
  654                                 bcopy((caddr_t) & subseq, (caddr_t) & bogus[2], sizeof(u_short));
  655                                 bcopy((caddr_t) & fcredit, (caddr_t) & bogus[3], sizeof(u_short));
  656 
  657 #ifdef TPPT
  658                                 if (tp_traceflags[D_ACKSEND]) {
  659                                         tptraceTPCB(TPPTmisc,
  660                                       "emit w/FCC: snduna r_subseq fcredit",
  661                                          tpcb->tp_snduna, tpcb->tp_r_subseq,
  662                                                     tpcb->tp_fcredit, 0);
  663                                 }
  664 #endif
  665 
  666 #ifdef ARGO_DEBUG
  667                                 if (argo_debug[D_ACKSEND]) {
  668                                         printf("Calling ADDOPTION 0x%x, %p, 0x%lx,0x%x\n",
  669                                                TPP_flow_cntl_conf,
  670                                                hdr, (unsigned long)sizeof(bogus), bogus[0]);
  671                                 }
  672 #endif
  673                                 ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]);
  674 #ifdef ARGO_DEBUG
  675                                 if (argo_debug[D_ACKSEND]) {
  676                                         printf("after ADDOPTION hdr %p hdr->tpdu_li 0x%x\n",
  677                                                hdr, hdr->tpdu_li);
  678                                         printf(
  679                                                "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  680                                                csum_offset, hdr->tpdu_li);
  681                                 }
  682 #endif
  683 
  684                         }
  685                         tpcb->tp_reneged = 0;
  686                         tpcb->tp_sent_rcvnxt = seq;
  687                         if (tpcb->tp_fcredit == 0) {
  688                                 int             timo = tpcb->tp_keepalive_ticks;
  689                                 if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT)
  690                                         tpcb->tp_rxtshift++;
  691                                 timo = min(timo, ((int) tpcb->tp_dt_ticks) << tpcb->tp_rxtshift);
  692                                 tp_ctimeout(tpcb, TM_sendack, timo);
  693                         } else
  694                                 tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks);
  695                         IncStat(ts_AK_sent);
  696                         IncPStat(tpcb, tps_AK_sent);
  697 #ifdef ARGO_DEBUG
  698                         if (argo_debug[D_ACKSEND]) {
  699                                 printf(
  700                                        "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  701                                        csum_offset, hdr->tpdu_li);
  702                         }
  703 #endif
  704                         break;
  705 
  706                 case ER_TPDU_type:
  707                         hdr->tpdu_ERreason = eot;
  708                         hdr->tpdu_cdt = 0;
  709                         /* no user data */
  710                         data = (struct mbuf *) 0;
  711                         IncStat(ts_ER_sent);
  712                         break;
  713                 }
  714 
  715         }
  716         ASSERT((int) hdr->tpdu_li != 0);
  717 #if 0
  718         ASSERT((int) hdr->tpdu_li < MLEN);
  719 #endif
  720 
  721         m->m_next = data;
  722 
  723 #if 0
  724         ASSERT(hdr->tpdu_li < MLEN);    /* leave this in */
  725 #endif
  726         ASSERT(hdr->tpdu_li != 0);      /* leave this in */
  727 
  728         m->m_len = hdr->tpdu_li;
  729         hdr->tpdu_li--;         /* doesn't include the li field */
  730 
  731         datalen = m_datalen(m); /* total len */
  732 
  733         ASSERT(datalen <= tpcb->tp_l_tpdusize); /* may become a problem when
  734                                                  * CLNP is used; leave in
  735                                                  * here for the time being */
  736 #ifdef ARGO_DEBUG
  737         if (argo_debug[D_ACKSEND]) {
  738                 printf(
  739                  "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  740                        csum_offset, hdr->tpdu_li);
  741         }
  742 #endif
  743         if (datalen > tpcb->tp_l_tpdusize) {
  744                 printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n",
  745                        datalen, tpcb->tp_l_tpdusize);
  746         }
  747 #ifdef ARGO_DEBUG
  748         if (argo_debug[D_EMIT]) {
  749                 printf(
  750                        "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n",
  751                        m->m_len, csum_offset, datalen);
  752         }
  753 #endif
  754         if (tpcb->tp_use_checksum ||
  755             (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4))) {
  756                 iso_gen_csum(m, csum_offset, datalen);
  757         }
  758 #ifdef ARGO_DEBUG
  759         if (argo_debug[D_EMIT]) {
  760                 printf("tp_emit before tpxxx_output tpcb %p, dutype 0x%x, datalen 0x%x\n",
  761                        tpcb, dutype, datalen);
  762                 dump_buf(mtod(m, caddr_t), datalen);
  763         }
  764 #endif
  765 
  766 #ifdef TP_PERF_MEAS
  767         if (DOPERF(tpcb)) {
  768                 if (dutype == DT_TPDU_type) {
  769                         PStat(tpcb, Nb_to_ll) += (datalen - m->m_len);
  770                         tpmeas(tpcb->tp_lref, TPtime_to_ll, NULL,
  771                                seq, PStat(tpcb, Nb_to_ll),
  772                                (datalen - m->m_len));
  773                 }
  774         }
  775 #endif
  776 
  777 #ifdef TPPT
  778         if (tp_traceflags[D_EMIT]) {
  779                 tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li + 1, datalen, 0);
  780         }
  781 #endif
  782 #ifdef ARGO_DEBUG
  783             if (argo_debug[D_EMIT]) {
  784                 printf("OUTPUT: tpcb %p, isop %p, so %p\n",
  785                        tpcb, tpcb->tp_npcb, tpcb->tp_sock);
  786         }
  787 #endif
  788 
  789         {
  790                 extern char     tp_delay;
  791 
  792                 if (tp_delay)
  793                         if (tpcb->tp_use_checksum == 0) {
  794                                 u_int  i = tp_delay;
  795                                 for (; i != 0; i--)
  796                                         (void) iso_check_csum(m, datalen);
  797                         }
  798         }
  799         ASSERT(m->m_len > 0);
  800         error = (tpcb->tp_nlproto->nlp_output) (m, datalen, tpcb->tp_npcb,
  801                                                 !tpcb->tp_use_checksum);
  802 #ifdef ARGO_DEBUG
  803         if (argo_debug[D_EMIT]) {
  804                 printf("OUTPUT: returned 0x%x\n", error);
  805         }
  806 #endif
  807 #ifdef TPPT
  808         if (tp_traceflags[D_EMIT]) {
  809                 tptraceTPCB(TPPTmisc,
  810                        "tp_emit nlproto->output netservice returns datalen",
  811          tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen);
  812         }
  813 #endif
  814 done:
  815         if (error) {
  816                 if (dutype == AK_TPDU_type)
  817                         tp_ctimeout(tpcb, TM_sendack, 1);
  818                 if (error == E_CO_QFULL) {
  819                         tp_quench((struct inpcb *) tpcb, PRC_QUENCH);
  820                         return 0;
  821                 }
  822         }
  823         return error;
  824 }
  825 /*
  826  * NAME:                tp_error_emit()
  827  * CALLED FROM: tp_input() when a DR or ER is to be issued in
  828  *      response to an input error.
  829  * FUNCTION and ARGUMENTS:
  830  *      The error type is the first argument.
  831  *      The argument (sref) is the source reference on the bad incoming tpdu,
  832  *      and is used for a destination reference on the outgoing packet.
  833  *      (faddr) and (laddr) are the foreign and local addresses for this
  834  *      connection.
  835  *      (erdata) is a ptr to the errant incoming tpdu, and is copied into the
  836  *      outgoing ER, if an ER is to be issued.
  837  *      (erlen)  is the number of octets of the errant tpdu that we should
  838  *      try to copy.
  839  *      (tpcb) is the pcb that describes the connection for which the bad tpdu
  840  *      arrived.
  841  * RETURN VALUES:
  842  *              0 OK
  843  *      ENOBUFS
  844  *      E* from net layer datagram output routine
  845  * SIDE EFFECTS:
  846  *
  847  * NOTES:
  848  */
  849 
  850 int
  851 tp_error_emit(
  852         int             error,
  853         u_long          sref,
  854         struct sockaddr_iso *faddr,
  855         struct sockaddr_iso *laddr,
  856         struct mbuf    *erdata,
  857         int             erlen,
  858         struct tp_pcb  *tpcb,
  859         caddr_t         cons_channel,
  860         int           (*dgout_routine)(struct mbuf *, ...))
  861 {
  862         int             dutype;
  863         int             datalen = 0;
  864         struct tpdu *hdr;
  865         struct mbuf *m;
  866         int             csum_offset;
  867 
  868 #ifdef TPPT
  869         if (tp_traceflags[D_ERROR_EMIT]) {
  870                 tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen",
  871                         error, sref, tpcb, erlen);
  872         }
  873 #endif
  874 #ifdef ARGO_DEBUG
  875         if (argo_debug[D_ERROR_EMIT]) {
  876                 printf(
  877                        "tp_error_emit error 0x%x sref %lx tpcb %p erlen 0x%x chan %p\n",
  878                        error, sref, tpcb, erlen, cons_channel);
  879         }
  880 #endif
  881 
  882         MGET(m, M_DONTWAIT, TPMT_TPHDR);
  883         if (m == NULL) {
  884                 return ENOBUFS;
  885         }
  886         m->m_len = sizeof(struct tpdu);
  887         m->m_nextpkt = NULL;
  888 
  889         hdr = mtod(m, struct tpdu *);
  890 
  891 #ifdef ARGO_DEBUG
  892         if (argo_debug[D_ERROR_EMIT]) {
  893                 printf("[error 0x%x] [error&0xff  0x%x] [(char)error 0x%x]\n",
  894                        error, error & 0xff, (char) error);
  895         }
  896 #endif
  897 
  898 
  899         if (error & TP_ERROR_SNDC)
  900                 dutype = DC_TPDU_type;
  901         else if (error & 0x40) {
  902                 error &= ~0x40;
  903                 dutype = ER_TPDU_type;
  904         } else
  905                 dutype = DR_TPDU_type;
  906         error &= 0xff;
  907 
  908         hdr->tpdu_type = dutype;
  909         hdr->tpdu_cdt = 0;
  910 
  911         switch (dutype) {
  912 
  913         case DC_TPDU_type:
  914                 IncStat(ts_DC_sent);
  915                 hdr->tpdu_li = 6;
  916                 hdr->tpdu_DCdref = htons(sref);
  917                 hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0;
  918 #ifdef ARGO_DEBUG
  919                 if (argo_debug[D_ERROR_EMIT]) {
  920                         printf("DC case:\n");
  921                         dump_buf(hdr, 6);
  922                 }
  923 #endif
  924                 /* forget the add'l information variable part */
  925                 break;
  926 
  927         case DR_TPDU_type:
  928                 IncStat(ts_DR_sent);
  929                 hdr->tpdu_li = 7;
  930                 hdr->tpdu_DRdref = htons(sref);
  931                 hdr->tpdu_DRsref = 0;
  932                 hdr->tpdu_DRreason = (char) error;
  933 #ifdef ARGO_DEBUG
  934                 if (argo_debug[D_ERROR_EMIT]) {
  935                         printf("DR case:\n");
  936                         dump_buf(hdr, 7);
  937                 }
  938 #endif
  939                 /* forget the add'l information variable part */
  940                 break;
  941 
  942         case ER_TPDU_type:
  943                 IncStat(ts_ER_sent);
  944                 hdr->tpdu_li = 5;
  945                 hdr->tpdu_ERreason = (char) error;
  946                 hdr->tpdu_ERdref = htons(sref);
  947                 break;
  948 
  949         default:
  950                 ASSERT(0);
  951                 printf("TP PANIC: bad dutype 0x%x\n", dutype);
  952         }
  953 
  954         if (tpcb)
  955                 if (tpcb->tp_use_checksum) {
  956                         ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */ );
  957                         csum_offset = hdr->tpdu_li - 2;
  958                 }
  959 #if 0
  960         ASSERT(hdr->tpdu_li < MLEN);
  961 #endif
  962 
  963         if (dutype == ER_TPDU_type) {
  964                 /* copy the errant tpdu into another 'variable part' */
  965                 caddr_t P;
  966 
  967 #ifdef TPPT
  968                 if (tp_traceflags[D_ERROR_EMIT]) {
  969                         tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li,
  970                                 0, 0);
  971                 }
  972 #endif
  973 #ifdef ARGO_DEBUG
  974                 if (argo_debug[D_ERROR_EMIT]) {
  975                         printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li);
  976                 }
  977 #endif
  978 
  979                 /* copy at most as many octets for which you have room */
  980                 if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN)
  981                         erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2;
  982 
  983                 /* add the "invalid tpdu" parameter : required in class 0 */
  984                 P = (caddr_t) hdr + (int) (hdr->tpdu_li);
  985                 vbptr(P)->tpv_code = TPP_invalid_tpdu;  /* parameter code */
  986                 vbptr(P)->tpv_len = erlen;      /* parameter length */
  987                 m->m_len = hdr->tpdu_li + 2;    /* 1 for code, 1 for length */
  988 
  989                 /*
  990                  * tp_input very likely handed us an mbuf chain w/ nothing in
  991                  * the first mbuf and the data following the empty mbuf
  992                  */
  993                 if (erdata->m_len == 0) {
  994                         erdata = m_free(erdata);        /* returns the next mbuf
  995                                                          * on the chain */
  996                 }
  997                 /*
  998                  * copy only up to the bad octet
  999                  * (or max that will fit in a header
 1000                  */
 1001                 m->m_next = m_copy(erdata, 0, erlen);
 1002                 hdr->tpdu_li += erlen + 2;
 1003                 m_freem(erdata);
 1004         } else {
 1005 #ifdef ARGO_DEBUG
 1006                 if (argo_debug[D_ERROR_EMIT]) {
 1007                         printf("error_emit DR error %d tpduli %x\n", error, hdr->tpdu_li);
 1008                         dump_buf((char *) hdr, hdr->tpdu_li);
 1009                 }
 1010 #endif
 1011                 m->m_len = hdr->tpdu_li;
 1012                 m_freem(erdata);
 1013         }
 1014 
 1015         hdr->tpdu_li--;
 1016 #ifdef TPPT
 1017         if (tp_traceflags[D_ERROR_EMIT]) {
 1018                 tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li + 1, 0, 0);
 1019         }
 1020 #endif
 1021 
 1022         datalen = m_datalen(m);
 1023         if (tpcb) {
 1024                 if (tpcb->tp_use_checksum) {
 1025 #ifdef TPPT
 1026                         if (tp_traceflags[D_ERROR_EMIT]) {
 1027                                 tptrace(TPPTmisc, "before gen csum datalen", datalen, 0, 0, 0);
 1028                         }
 1029 #endif
 1030 #ifdef ARGO_DEBUG
 1031                         if (argo_debug[D_ERROR_EMIT]) {
 1032                                 printf("before gen csum datalen 0x%x, csum_offset 0x%x\n",
 1033                                        datalen, csum_offset);
 1034                         }
 1035 #endif
 1036 
 1037                         iso_gen_csum(m, csum_offset, datalen);
 1038                 }
 1039 #ifdef ARGO_DEBUG
 1040                 if (argo_debug[D_ERROR_EMIT]) {
 1041                         printf("OUTPUT: tpcb %p, isop %p, so %p\n",
 1042                                tpcb, tpcb->tp_npcb, tpcb->tp_sock);
 1043                 }
 1044 #endif
 1045         }
 1046         if (cons_channel) {
 1047 #ifdef TPCONS
 1048                 struct pklcd   *lcp = (struct pklcd *) cons_channel;
 1049 #ifdef notdef
 1050                 struct isopcb  *isop = (struct isopcb *) lcp->lcd_upnext;
 1051 #endif
 1052                 tpcons_output_dg(m, datalen, cons_channel);
 1053 #ifdef notdef
 1054                 if (tpcb == 0) iso_pcbdetach(isop);
 1055 #endif
 1056                 /*
 1057                  * but other side may want to try again over same VC, so,
 1058                  * we'll depend on him closing it, but in case it gets
 1059                  * forgotten we'll mark it for garbage collection
 1060                  */
 1061                 lcp->lcd_flags |= X25_DG_CIRCUIT;
 1062 #ifdef ARGO_DEBUG
 1063                 if (argo_debug[D_ERROR_EMIT]) {
 1064                         printf("OUTPUT: dutype %#x channel %p\n",
 1065                                dutype, cons_channel);
 1066                 }
 1067 #endif
 1068 #else
 1069                 printf("TP panic! cons channel %p but not cons configured\n",
 1070                        cons_channel);
 1071 #endif
 1072                 return 0;
 1073         } else if (tpcb) {
 1074 
 1075 #ifdef ARGO_DEBUG
 1076                 if (argo_debug[D_ERROR_EMIT]) {
 1077                         printf("tp_error_emit 1 sending DG: Laddr\n");
 1078                         dump_addr(sisotosa(laddr));
 1079                         printf("Faddr\n");
 1080                         dump_addr(sisotosa(faddr));
 1081                 }
 1082 #endif
 1083                 return (*tpcb->tp_nlproto->nlp_dgoutput) (m, datalen,
 1084                                                          &laddr->siso_addr,
 1085                                                          &faddr->siso_addr,
 1086                         /* no route */ (caddr_t) 0, !tpcb->tp_use_checksum);
 1087         } else if (dgout_routine) {
 1088 #ifdef ARGO_DEBUG
 1089                 if (argo_debug[D_ERROR_EMIT]) {
 1090                         printf("tp_error_emit sending DG: Laddr\n");
 1091                         dump_addr(sisotosa(laddr));
 1092                         printf("Faddr\n");
 1093                         dump_addr(sisotosa(faddr));
 1094                 }
 1095 #endif
 1096                 return (*dgout_routine) (m, datalen, &laddr->siso_addr, &faddr->siso_addr,
 1097                                         (caddr_t) 0, /* nochecksum==false */ 0);
 1098         } else {
 1099 #ifdef ARGO_DEBUG
 1100                 if (argo_debug[D_ERROR_EMIT]) {
 1101                         printf("tp_error_emit DROPPING %p\n", m);
 1102                 }
 1103 #endif
 1104                 IncStat(ts_send_drop);
 1105                 m_freem(m);
 1106                 return 0;
 1107         }
 1108 }

Cache object: 7ae0a5b7fbc216fb046d22bdc97c456a


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