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.27 2008/04/23 09:57:59 plunky 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.27 2008/04/23 09:57:59 plunky 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((void *) 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                                         hdr->tpdu_cdt = 0;
  260                                 }
  261                                 hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class);
  262                                 hdr->tpdu_CCoptions =
  263                                         (tpcb->tp_xtd_format ? TPO_XTD_FMT : 0) |
  264                                         (tpcb->tp_use_efc ? TPO_USE_EFC : 0);
  265 
  266 #ifdef TP_PERF_MEAS
  267                                 if (DOPERF(tpcb)) {
  268                                         u_char  perf_meas = tpcb->tp_perf_on;
  269                                         ADDOPTION(TPP_perf_meas, hdr,
  270                                                   sizeof(perf_meas), perf_meas);
  271                                 }
  272 #endif
  273 
  274                                         if (dutype == CR_TPDU_type) {
  275                                         IncStat(ts_CR_sent);
  276 
  277                                         ASSERT(tpcb->tp_lsuffixlen > 0);
  278                                         ASSERT(tpcb->tp_fsuffixlen > 0);
  279 
  280                                         ADDOPTION(TPP_calling_sufx, hdr,
  281                                                   tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]);
  282                                         ADDOPTION(TPP_called_sufx, hdr,
  283                                                   tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]);
  284                                 } else {
  285                                         IncStat(ts_CC_sent);
  286                                 }
  287 
  288                                 ADDOPTION(TPP_tpdu_size, hdr,
  289                                           sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize);
  290 
  291                                 if (tpcb->tp_class != TP_CLASS_0) {
  292                                         short           millisec = 500 * (tpcb->tp_sendack_ticks);
  293 
  294                                         millisec = htons(millisec);
  295                                         ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec);
  296 
  297                                         x = (tpcb->tp_use_nxpd ? TPAO_USE_NXPD : 0)
  298                                                 | (tpcb->tp_use_rcc ? TPAO_USE_RCC : 0)
  299                                                 | (tpcb->tp_use_checksum ? 0 : TPAO_NO_CSUM)
  300                                                 | (tpcb->tp_xpd_service ? TPAO_USE_TXPD : 0);
  301                                         ADDOPTION(TPP_addl_opt, hdr, 1, x);
  302 
  303                                         if ((tpcb->tp_l_tpdusize ^ (1 << tpcb->tp_tpdusize)) != 0) {
  304                                                 u_short         size_s = tpcb->tp_l_tpdusize >> 7;
  305                                                 u_char          size_c = size_s;
  306                                                 ASSERT(tpcb->tp_l_tpdusize < 65536 * 128);
  307                                                 if (dutype == CR_TPDU_type)
  308                                                         tpcb->tp_ptpdusize = size_s;
  309                                                 if (size_s < 256) {
  310                                                         ADDOPTION(TPP_ptpdu_size, hdr, 1, size_c);
  311                                                 } else {
  312                                                         size_s = htons(size_s);
  313                                                         ADDOPTION(TPP_ptpdu_size, hdr, 2, size_s);
  314                                                 }
  315                                         }
  316                                 }
  317                                 if ((dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)) {
  318 
  319                                         ASSERT(1 == sizeof(tpcb->tp_vers));
  320                                         ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers);
  321 
  322                                         /*
  323                                          * for each alt protocol class x, x =
  324                                          * x<<4; option = concat(option, x);
  325                                          * Well, for now we only have TP0 for
  326                                          * an alternative so... this is easy.
  327                                          *
  328                                          * HOWEVER... There should be NO alt
  329                                          * protocol class over CLNS.  Need to
  330                                          * see if the route suggests CONS,
  331                                          * and iff so add alt class.
  332                                          */
  333                                         x = 0;
  334                                         ADDOPTION(TPP_alt_class, hdr, 1, x);
  335                                 }
  336 #if 0
  337                                 if (hdr->tpdu_li > MLEN)
  338                                         panic("tp_emit CR/CC");
  339 #endif
  340                         }
  341                         break;
  342 
  343                 case DR_TPDU_type:
  344                         if (hdr->tpdu_DRdref == 0) {
  345                                 /* don't issue the DR */
  346                                 goto done;
  347                         }
  348                         hdr->tpdu_cdt = 0;
  349                         hdr->tpdu_DRsref = htons(tpcb->tp_lref);
  350                         hdr->tpdu_DRreason = (u_char) eot;      /* WHICH BYTE OF THIS??? */
  351 
  352                         /* forget the add'l information variable part */
  353                         IncStat(ts_DR_sent);
  354                         break;
  355 
  356                 case DC_TPDU_type:      /* not used in class 0 */
  357                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  358                         hdr->tpdu_DCsref = htons(tpcb->tp_lref);
  359                         hdr->tpdu_cdt = 0;
  360                         data = (struct mbuf *) 0;
  361                         IncStat(ts_DC_sent);
  362                         break;
  363 
  364                 case XAK_TPDU_type:     /* xak not used in class 0 */
  365                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  366                         hdr->tpdu_cdt = 0;
  367 
  368 #ifdef TPPT
  369                         if (tp_traceflags[D_XPD]) {
  370                                 tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0);
  371                         }
  372 #endif
  373                         data = (struct mbuf *) 0;
  374                         if (tpcb->tp_xtd_format) {
  375 #ifdef BYTE_ORDER
  376                                 union seq_type  seqeotX;
  377 
  378                                 seqeotX.s_seq = seq;
  379                                 seqeotX.s_eot = 1;
  380                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  381 #else
  382                                 hdr->tpdu_XAKseqX = seq;
  383 #endif                          /* BYTE_ORDER */
  384                         } else {
  385                                 hdr->tpdu_XAKseq = seq;
  386                         }
  387                         IncStat(ts_XAK_sent);
  388                         IncPStat(tpcb, tps_XAK_sent);
  389                         break;
  390 
  391                 case XPD_TPDU_type:     /* xpd not used in class 0 */
  392                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  393                         hdr->tpdu_cdt = 0;
  394                         if (tpcb->tp_xtd_format) {
  395 #ifdef BYTE_ORDER
  396                                 union seq_type  seqeotX;
  397 
  398                                 seqeotX.s_seq = seq;
  399                                 seqeotX.s_eot = 1;
  400                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  401 #else
  402                                 hdr->tpdu_XPDseqX = seq;
  403                                 hdr->tpdu_XPDeotX = 1;  /* always 1 for XPD tpdu */
  404 #endif                          /* BYTE_ORDER */
  405                         } else {
  406                                 hdr->tpdu_XPDseq = seq;
  407                                 hdr->tpdu_XPDeot = 1;   /* always 1 for XPD tpdu */
  408                         }
  409                         IncStat(ts_XPD_sent);
  410                         IncPStat(tpcb, tps_XPD_sent);
  411 
  412                         /* kludge to test the input size checking */
  413 #ifdef ARGO_DEBUG
  414                         if (argo_debug[D_SIZE_CHECK]) {
  415 #if 0
  416                                  if (data->m_len <= 16 &&
  417                                      data->m_off < (MLEN-18)) {
  418                                         printf("Sending too much data on XPD: 18 bytes\n");
  419                                         data->m_len = 18;
  420                                 }
  421 #endif
  422                         }
  423 #endif
  424                         break;
  425 
  426                 case DT_TPDU_type:
  427                         hdr->tpdu_cdt = 0;
  428 #ifdef TPPT
  429                         if (tp_traceflags[D_DATA]) {
  430                                 tptraceTPCB(TPPTmisc,
  431                                             "emit DT: eot seq tpdu_li", eot,
  432                                             seq, hdr->tpdu_li, 0);
  433                         }
  434 #endif
  435                         if (tpcb->tp_xtd_format) {
  436 #ifdef BYTE_ORDER
  437                                 union seq_type  seqeotX;
  438 
  439                                 seqeotX.s_seq = seq;
  440                                 seqeotX.s_eot = eot;
  441                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  442 #else
  443                                 hdr->tpdu_DTseqX = seq;
  444                                 hdr->tpdu_DTeotX = eot;
  445 #endif                          /* BYTE_ORDER */
  446                         } else if (tpcb->tp_class == TP_CLASS_0) {
  447 #ifdef ARGO_DEBUG
  448                                 if (argo_debug[D_EMIT]) {
  449                                         printf("DT tpdu: class 0 m %p hdr %p\n", m, hdr);
  450                                         dump_buf(hdr, hdr->tpdu_li + 1);
  451                                 }
  452 #endif
  453                                 ((struct tp0du *) hdr)->tp0du_eot = eot;
  454                                 ((struct tp0du *) hdr)->tp0du_mbz = 0;
  455 #ifdef ARGO_DEBUG
  456                                 if (argo_debug[D_EMIT]) {
  457                                         printf("DT 2 tpdu: class 0 m %p hdr %p\n", m, hdr);
  458                                         dump_buf(hdr, hdr->tpdu_li + 1);
  459                                 }
  460 #endif
  461                         } else {
  462                                 hdr->tpdu_DTseq = seq;
  463                                 hdr->tpdu_DTeot = eot;
  464                         }
  465                         if (eot) {
  466                                 IncStat(ts_EOT_sent);
  467                         }
  468                         IncStat(ts_DT_sent);
  469                         IncPStat(tpcb, tps_DT_sent);
  470                         break;
  471 
  472                 case AK_TPDU_type:      /* ak not used in class 0 */
  473                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  474                         data = (struct mbuf *) 0;
  475                         olduwe = tpcb->tp_sent_uwe;
  476 
  477                         if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) {
  478                                 LOCAL_CREDIT(tpcb);
  479                                 tpcb->tp_sent_uwe =
  480                                         SEQ(tpcb, tpcb->tp_rcvnxt + tpcb->tp_lcredit - 1);
  481                                 tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
  482                                 acking_ooo = 0;
  483                         } else
  484                                 acking_ooo = 1;
  485 
  486 #ifdef ARGO_DEBUG
  487                         if (argo_debug[D_RENEG]) {
  488                                 /*
  489                                  * occasionally fake a reneging so you can test
  490                                  * subsequencing
  491                                  */
  492                                 if (olduwe & 0x1) {
  493                                         tpcb->tp_reneged = 1;
  494                                         IncStat(ts_ldebug);
  495                                 }
  496                         }
  497 #endif
  498                         /*
  499                          * Are we about to reneg on credit? When might we do
  500                          * so? a) when using optimistic credit (which we no
  501                          * longer do). b) when drain() gets implemented (not
  502                          * in the plans). c) when D_RENEG is on. d) when DEC
  503                          * BIT response is implemented. (not- when we do
  504                          * this, we'll need to implement flow control
  505                          * confirmation)
  506                          */
  507                         if (SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe)) {
  508                                 tpcb->tp_reneged = 1;
  509                                 IncStat(ts_lcdt_reduced);
  510 #ifdef TPPT
  511                                 if (tp_traceflags[D_CREDIT]) {
  512                                         tptraceTPCB(TPPTmisc,
  513                                       "RENEG: olduwe newuwe lcredit rcvnxt",
  514                                                     olduwe,
  515                                         tpcb->tp_sent_uwe, tpcb->tp_lcredit,
  516                                                     tpcb->tp_rcvnxt);
  517                                 }
  518 #endif
  519                         }
  520 #ifdef TP_PERF_MEAS
  521                         if (DOPERF(tpcb)) {
  522                                 /*
  523                                  * new lwe is less than old uwe means we're
  524                                  * acking before we received a whole window full
  525                                  */
  526                                 if (SEQ_LT(tpcb, tpcb->tp_rcvnxt, olduwe)) {
  527                                         /*
  528                                          * tmp1 = number of pkts fewer than
  529                                          * the full window
  530                                          */
  531                                         int    tmp1 =
  532                                         (int) SEQ_SUB(tpcb, olduwe,
  533                                                       tpcb->tp_rcvnxt);
  534 
  535                                         if (tmp1 > TP_PM_MAX)
  536                                                 tmp1 = TP_PM_MAX;
  537                                         IncPStat(tpcb, tps_ack_early[tmp1]);
  538 
  539                                         /*
  540                                          * tmp1 = amt of new cdt we're
  541                                          * advertising
  542                                          */
  543                                         tmp1 = SEQ_SUB(tpcb, seq,
  544                                                        tpcb->tp_sent_rcvnxt);
  545                                         if (tmp1 > TP_PM_MAX)
  546                                                 tmp1 = TP_PM_MAX;
  547 
  548                                         IncPStat(tpcb,
  549                                                  tps_cdt_acked[tmp1]
  550                                                  [((tpcb->tp_lcredit >
  551                                                     TP_PM_MAX) ?
  552                                                    TP_PM_MAX :
  553                                                    tpcb->tp_lcredit)]);
  554 
  555                                 }
  556                         }
  557 #endif
  558 
  559 #ifdef TPPT
  560                         if (tp_traceflags[D_ACKSEND]) {
  561                                 tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit,
  562                                             tpcb->tp_sent_uwe,
  563                                             tpcb->tp_r_subseq, 0);
  564                         }
  565 #endif
  566                         if (tpcb->tp_xtd_format) {
  567 #ifdef BYTE_ORDER
  568                                 union seq_type  seqeotX;
  569 
  570                                 seqeotX.s_seq = seq;
  571                                 seqeotX.s_eot = 0;
  572                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  573                                 hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit);
  574 #else
  575                                 hdr->tpdu_cdt = 0;
  576                                 hdr->tpdu_AKseqX = seq;
  577                                 hdr->tpdu_AKcdtX = tpcb->tp_lcredit;
  578 #endif                          /* BYTE_ORDER */
  579                         } else {
  580                                 hdr->tpdu_AKseq = seq;
  581                                 hdr->tpdu_AKcdt = tpcb->tp_lcredit;
  582                         }
  583                         if ((tpcb->tp_class == TP_CLASS_4) &&
  584                             (tpcb->tp_reneged || acking_ooo)) {
  585                                 /*
  586                                  * Ack subsequence parameter req'd if WE
  587                                  * reneged on credit offered.  (ISO 8073,
  588                                  * 12.2.3.8.2, p. 74)
  589                                  */
  590 #ifdef ARGO_DEBUG
  591                                 if (argo_debug[D_RENEG]) {
  592                                         printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq);
  593                                 }
  594 #endif
  595                                 tpcb->tp_s_subseq++;
  596                                 /*
  597                                  * add tmp subseq and do a htons on it.
  598                                  */
  599                                 ADDOPTION(TPP_subseq, hdr,
  600                                           sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq);
  601                         } else
  602                                 tpcb->tp_s_subseq = 0;
  603 
  604                         if (tpcb->tp_sendfcc || eot) {  /* overloaded to mean
  605                                                          * SEND FCC */
  606                                 /*
  607                                  * Rules for sending FCC ("should" send when)
  608                                  * : %a) received an ack from peer with NO
  609                                  * NEWS whatsoever, and it did not contain an
  610                                  * FCC b) received an ack from peer that
  611                                  * opens its closed window. c) received an
  612                                  * ack from peer after it reneged on its
  613                                  * offered credit, AND this ack raises UWE
  614                                  * but LWE is same and below UWE at time of
  615                                  * reneging (reduction) Now, ISO 8073
  616                                  * 12.2.3.8.3 says that a retransmitted AK
  617                                  * shall not contain the FCC parameter.  Now,
  618                                  * how the hell you tell the difference
  619                                  * between a retransmitted ack and an ack
  620                                  * that's sent in response to a received ack,
  621                                  * I don't know, because without any local
  622                                  * activity, and w/o any received DTs, they
  623                                  * will contain exactly the same credit/seq#
  624                                  * information. Anyway, given that the
  625                                  * "retransmission of acks" procedure (ISO
  626                                  * 8073 12.2.3.8.3) is optional, and we don't
  627                                  * do it (although the peer can't tell that),
  628                                  * we ignore this last rule.
  629                                  *
  630                                  * We send FCC for reasons a) and b) only. To
  631                                  * add reason c) would require a ridiculous
  632                                  * amount of state.
  633                                  *
  634                                  */
  635                                 u_short         bogus[4];       /* lwe(32), subseq(16),
  636                                                                  * cdt(16) */
  637                                 SeqNum          lwe;
  638                                 u_short         subseq, fcredit;
  639 
  640                                 tpcb->tp_sendfcc = 0;
  641 
  642                                 lwe = (SeqNum) htonl(tpcb->tp_snduna);
  643                                 subseq = htons(tpcb->tp_r_subseq);
  644                                 fcredit = htons(tpcb->tp_fcredit);
  645 
  646                                 bcopy((void *) & lwe, (void *) & bogus[0], sizeof(SeqNum));
  647                                 bcopy((void *) & subseq, (void *) & bogus[2], sizeof(u_short));
  648                                 bcopy((void *) & fcredit, (void *) & bogus[3], sizeof(u_short));
  649 
  650 #ifdef TPPT
  651                                 if (tp_traceflags[D_ACKSEND]) {
  652                                         tptraceTPCB(TPPTmisc,
  653                                       "emit w/FCC: snduna r_subseq fcredit",
  654                                          tpcb->tp_snduna, tpcb->tp_r_subseq,
  655                                                     tpcb->tp_fcredit, 0);
  656                                 }
  657 #endif
  658 
  659 #ifdef ARGO_DEBUG
  660                                 if (argo_debug[D_ACKSEND]) {
  661                                         printf("Calling ADDOPTION 0x%x, %p, 0x%lx,0x%x\n",
  662                                                TPP_flow_cntl_conf,
  663                                                hdr, (unsigned long)sizeof(bogus), bogus[0]);
  664                                 }
  665 #endif
  666                                 ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]);
  667 #ifdef ARGO_DEBUG
  668                                 if (argo_debug[D_ACKSEND]) {
  669                                         printf("after ADDOPTION hdr %p hdr->tpdu_li 0x%x\n",
  670                                                hdr, hdr->tpdu_li);
  671                                         printf(
  672                                                "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  673                                                csum_offset, hdr->tpdu_li);
  674                                 }
  675 #endif
  676 
  677                         }
  678                         tpcb->tp_reneged = 0;
  679                         tpcb->tp_sent_rcvnxt = seq;
  680                         if (tpcb->tp_fcredit == 0) {
  681                                 int             timo = tpcb->tp_keepalive_ticks;
  682                                 if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT)
  683                                         tpcb->tp_rxtshift++;
  684                                 timo = min(timo, ((int) tpcb->tp_dt_ticks) << tpcb->tp_rxtshift);
  685                                 tp_ctimeout(tpcb, TM_sendack, timo);
  686                         } else
  687                                 tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks);
  688                         IncStat(ts_AK_sent);
  689                         IncPStat(tpcb, tps_AK_sent);
  690 #ifdef ARGO_DEBUG
  691                         if (argo_debug[D_ACKSEND]) {
  692                                 printf(
  693                                        "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  694                                        csum_offset, hdr->tpdu_li);
  695                         }
  696 #endif
  697                         break;
  698 
  699                 case ER_TPDU_type:
  700                         hdr->tpdu_ERreason = eot;
  701                         hdr->tpdu_cdt = 0;
  702                         /* no user data */
  703                         data = (struct mbuf *) 0;
  704                         IncStat(ts_ER_sent);
  705                         break;
  706                 }
  707 
  708         }
  709         ASSERT((int) hdr->tpdu_li != 0);
  710 #if 0
  711         ASSERT((int) hdr->tpdu_li < MLEN);
  712 #endif
  713 
  714         m->m_next = data;
  715 
  716 #if 0
  717         ASSERT(hdr->tpdu_li < MLEN);    /* leave this in */
  718 #endif
  719         ASSERT(hdr->tpdu_li != 0);      /* leave this in */
  720 
  721         m->m_len = hdr->tpdu_li;
  722         hdr->tpdu_li--;         /* doesn't include the li field */
  723 
  724         datalen = m_datalen(m); /* total len */
  725 
  726         ASSERT(datalen <= tpcb->tp_l_tpdusize); /* may become a problem when
  727                                                  * CLNP is used; leave in
  728                                                  * here for the time being */
  729 #ifdef ARGO_DEBUG
  730         if (argo_debug[D_ACKSEND]) {
  731                 printf(
  732                  "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  733                        csum_offset, hdr->tpdu_li);
  734         }
  735 #endif
  736         if (datalen > tpcb->tp_l_tpdusize) {
  737                 printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n",
  738                        datalen, tpcb->tp_l_tpdusize);
  739         }
  740 #ifdef ARGO_DEBUG
  741         if (argo_debug[D_EMIT]) {
  742                 printf(
  743                        "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n",
  744                        m->m_len, csum_offset, datalen);
  745         }
  746 #endif
  747         if (tpcb->tp_use_checksum ||
  748             (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4))) {
  749                 iso_gen_csum(m, csum_offset, datalen);
  750         }
  751 #ifdef ARGO_DEBUG
  752         if (argo_debug[D_EMIT]) {
  753                 printf("tp_emit before tpxxx_output tpcb %p, dutype 0x%x, datalen 0x%x\n",
  754                        tpcb, dutype, datalen);
  755                 dump_buf(mtod(m, void *), datalen);
  756         }
  757 #endif
  758 
  759 #ifdef TP_PERF_MEAS
  760         if (DOPERF(tpcb)) {
  761                 if (dutype == DT_TPDU_type) {
  762                         PStat(tpcb, Nb_to_ll) += (datalen - m->m_len);
  763                         tpmeas(tpcb->tp_lref, TPtime_to_ll, NULL,
  764                                seq, PStat(tpcb, Nb_to_ll),
  765                                (datalen - m->m_len));
  766                 }
  767         }
  768 #endif
  769 
  770 #ifdef TPPT
  771         if (tp_traceflags[D_EMIT]) {
  772                 tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li + 1, datalen, 0);
  773         }
  774 #endif
  775 #ifdef ARGO_DEBUG
  776             if (argo_debug[D_EMIT]) {
  777                 printf("OUTPUT: tpcb %p, isop %p, so %p\n",
  778                        tpcb, tpcb->tp_npcb, tpcb->tp_sock);
  779         }
  780 #endif
  781 
  782         {
  783                 extern char     tp_delay;
  784 
  785                 if (tp_delay)
  786                         if (tpcb->tp_use_checksum == 0) {
  787                                 u_int  i = tp_delay;
  788                                 for (; i != 0; i--)
  789                                         (void) iso_check_csum(m, datalen);
  790                         }
  791         }
  792         ASSERT(m->m_len > 0);
  793         error = (tpcb->tp_nlproto->nlp_output) (m, datalen, tpcb->tp_npcb,
  794                                                 !tpcb->tp_use_checksum);
  795 #ifdef ARGO_DEBUG
  796         if (argo_debug[D_EMIT]) {
  797                 printf("OUTPUT: returned 0x%x\n", error);
  798         }
  799 #endif
  800 #ifdef TPPT
  801         if (tp_traceflags[D_EMIT]) {
  802                 tptraceTPCB(TPPTmisc,
  803                        "tp_emit nlproto->output netservice returns datalen",
  804          tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen);
  805         }
  806 #endif
  807 done:
  808         if (error) {
  809                 if (dutype == AK_TPDU_type)
  810                         tp_ctimeout(tpcb, TM_sendack, 1);
  811                 if (error == E_CO_QFULL) {
  812                         tp_quench((struct inpcb *) tpcb, PRC_QUENCH);
  813                         return 0;
  814                 }
  815         }
  816         return error;
  817 }
  818 /*
  819  * NAME:                tp_error_emit()
  820  * CALLED FROM: tp_input() when a DR or ER is to be issued in
  821  *      response to an input error.
  822  * FUNCTION and ARGUMENTS:
  823  *      The error type is the first argument.
  824  *      The argument (sref) is the source reference on the bad incoming tpdu,
  825  *      and is used for a destination reference on the outgoing packet.
  826  *      (faddr) and (laddr) are the foreign and local addresses for this
  827  *      connection.
  828  *      (erdata) is a ptr to the errant incoming tpdu, and is copied into the
  829  *      outgoing ER, if an ER is to be issued.
  830  *      (erlen)  is the number of octets of the errant tpdu that we should
  831  *      try to copy.
  832  *      (tpcb) is the pcb that describes the connection for which the bad tpdu
  833  *      arrived.
  834  * RETURN VALUES:
  835  *              0 OK
  836  *      ENOBUFS
  837  *      E* from net layer datagram output routine
  838  * SIDE EFFECTS:
  839  *
  840  * NOTES:
  841  */
  842 
  843 int
  844 tp_error_emit(
  845         int             error,
  846         u_long          sref,
  847         struct sockaddr_iso *faddr,
  848         struct sockaddr_iso *laddr,
  849         struct mbuf    *erdata,
  850         int             erlen,
  851         struct tp_pcb  *tpcb,
  852         void *        cons_channel,
  853         int           (*dgout_routine)(struct mbuf *, ...))
  854 {
  855         int             dutype;
  856         int             datalen = 0;
  857         struct tpdu *hdr;
  858         struct mbuf *m;
  859         int             csum_offset;
  860 
  861 #ifdef TPPT
  862         if (tp_traceflags[D_ERROR_EMIT]) {
  863                 tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen",
  864                         error, sref, tpcb, erlen);
  865         }
  866 #endif
  867 #ifdef ARGO_DEBUG
  868         if (argo_debug[D_ERROR_EMIT]) {
  869                 printf(
  870                        "tp_error_emit error 0x%x sref %lx tpcb %p erlen 0x%x chan %p\n",
  871                        error, sref, tpcb, erlen, cons_channel);
  872         }
  873 #endif
  874 
  875         MGET(m, M_DONTWAIT, TPMT_TPHDR);
  876         if (m == NULL) {
  877                 return ENOBUFS;
  878         }
  879         m->m_len = sizeof(struct tpdu);
  880         m->m_nextpkt = NULL;
  881 
  882         hdr = mtod(m, struct tpdu *);
  883 
  884 #ifdef ARGO_DEBUG
  885         if (argo_debug[D_ERROR_EMIT]) {
  886                 printf("[error 0x%x] [error&0xff  0x%x] [(char)error 0x%x]\n",
  887                        error, error & 0xff, (char) error);
  888         }
  889 #endif
  890 
  891 
  892         if (error & TP_ERROR_SNDC)
  893                 dutype = DC_TPDU_type;
  894         else if (error & 0x40) {
  895                 error &= ~0x40;
  896                 dutype = ER_TPDU_type;
  897         } else
  898                 dutype = DR_TPDU_type;
  899         error &= 0xff;
  900 
  901         hdr->tpdu_type = dutype;
  902         hdr->tpdu_cdt = 0;
  903 
  904         switch (dutype) {
  905 
  906         case DC_TPDU_type:
  907                 IncStat(ts_DC_sent);
  908                 hdr->tpdu_li = 6;
  909                 hdr->tpdu_DCdref = htons(sref);
  910                 hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0;
  911 #ifdef ARGO_DEBUG
  912                 if (argo_debug[D_ERROR_EMIT]) {
  913                         printf("DC case:\n");
  914                         dump_buf(hdr, 6);
  915                 }
  916 #endif
  917                 /* forget the add'l information variable part */
  918                 break;
  919 
  920         case DR_TPDU_type:
  921                 IncStat(ts_DR_sent);
  922                 hdr->tpdu_li = 7;
  923                 hdr->tpdu_DRdref = htons(sref);
  924                 hdr->tpdu_DRsref = 0;
  925                 hdr->tpdu_DRreason = (char) error;
  926 #ifdef ARGO_DEBUG
  927                 if (argo_debug[D_ERROR_EMIT]) {
  928                         printf("DR case:\n");
  929                         dump_buf(hdr, 7);
  930                 }
  931 #endif
  932                 /* forget the add'l information variable part */
  933                 break;
  934 
  935         case ER_TPDU_type:
  936                 IncStat(ts_ER_sent);
  937                 hdr->tpdu_li = 5;
  938                 hdr->tpdu_ERreason = (char) error;
  939                 hdr->tpdu_ERdref = htons(sref);
  940                 break;
  941 
  942         default:
  943                 ASSERT(0);
  944                 printf("TP PANIC: bad dutype 0x%x\n", dutype);
  945         }
  946 
  947         if (tpcb)
  948                 if (tpcb->tp_use_checksum) {
  949                         ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */ );
  950                         csum_offset = hdr->tpdu_li - 2;
  951                 }
  952 #if 0
  953         ASSERT(hdr->tpdu_li < MLEN);
  954 #endif
  955 
  956         if (dutype == ER_TPDU_type) {
  957                 /* copy the errant tpdu into another 'variable part' */
  958                 void *P;
  959 
  960 #ifdef TPPT
  961                 if (tp_traceflags[D_ERROR_EMIT]) {
  962                         tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li,
  963                                 0, 0);
  964                 }
  965 #endif
  966 #ifdef ARGO_DEBUG
  967                 if (argo_debug[D_ERROR_EMIT]) {
  968                         printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li);
  969                 }
  970 #endif
  971 
  972                 /* copy at most as many octets for which you have room */
  973                 if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN)
  974                         erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2;
  975 
  976                 /* add the "invalid tpdu" parameter : required in class 0 */
  977                 P = (char *) hdr + (int) (hdr->tpdu_li);
  978                 vbptr(P)->tpv_code = TPP_invalid_tpdu;  /* parameter code */
  979                 vbptr(P)->tpv_len = erlen;      /* parameter length */
  980                 m->m_len = hdr->tpdu_li + 2;    /* 1 for code, 1 for length */
  981 
  982                 /*
  983                  * tp_input very likely handed us an mbuf chain w/ nothing in
  984                  * the first mbuf and the data following the empty mbuf
  985                  */
  986                 if (erdata->m_len == 0) {
  987                         erdata = m_free(erdata);        /* returns the next mbuf
  988                                                          * on the chain */
  989                 }
  990                 /*
  991                  * copy only up to the bad octet
  992                  * (or max that will fit in a header
  993                  */
  994                 m->m_next = m_copy(erdata, 0, erlen);
  995                 hdr->tpdu_li += erlen + 2;
  996                 m_freem(erdata);
  997         } else {
  998 #ifdef ARGO_DEBUG
  999                 if (argo_debug[D_ERROR_EMIT]) {
 1000                         printf("error_emit DR error %d tpduli %x\n", error, hdr->tpdu_li);
 1001                         dump_buf((char *) hdr, hdr->tpdu_li);
 1002                 }
 1003 #endif
 1004                 m->m_len = hdr->tpdu_li;
 1005                 m_freem(erdata);
 1006         }
 1007 
 1008         hdr->tpdu_li--;
 1009 #ifdef TPPT
 1010         if (tp_traceflags[D_ERROR_EMIT]) {
 1011                 tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li + 1, 0, 0);
 1012         }
 1013 #endif
 1014 
 1015         datalen = m_datalen(m);
 1016         if (tpcb) {
 1017                 if (tpcb->tp_use_checksum) {
 1018 #ifdef TPPT
 1019                         if (tp_traceflags[D_ERROR_EMIT]) {
 1020                                 tptrace(TPPTmisc, "before gen csum datalen", datalen, 0, 0, 0);
 1021                         }
 1022 #endif
 1023 #ifdef ARGO_DEBUG
 1024                         if (argo_debug[D_ERROR_EMIT]) {
 1025                                 printf("before gen csum datalen 0x%x, csum_offset 0x%x\n",
 1026                                        datalen, csum_offset);
 1027                         }
 1028 #endif
 1029 
 1030                         iso_gen_csum(m, csum_offset, datalen);
 1031                 }
 1032 #ifdef ARGO_DEBUG
 1033                 if (argo_debug[D_ERROR_EMIT]) {
 1034                         printf("OUTPUT: tpcb %p, isop %p, so %p\n",
 1035                                tpcb, tpcb->tp_npcb, tpcb->tp_sock);
 1036                 }
 1037 #endif
 1038         }
 1039         if (cons_channel) {
 1040                 printf("TP panic! cons channel %p but not cons configured\n",
 1041                        cons_channel);
 1042                 return 0;
 1043         } else if (tpcb) {
 1044 
 1045 #ifdef ARGO_DEBUG
 1046                 if (argo_debug[D_ERROR_EMIT]) {
 1047                         printf("tp_error_emit 1 sending DG: Laddr\n");
 1048                         dump_addr(sisotosa(laddr));
 1049                         printf("Faddr\n");
 1050                         dump_addr(sisotosa(faddr));
 1051                 }
 1052 #endif
 1053                 return (*tpcb->tp_nlproto->nlp_dgoutput) (m, datalen,
 1054                                                          &laddr->siso_addr,
 1055                                                          &faddr->siso_addr,
 1056                         /* no route */ (void *) 0, !tpcb->tp_use_checksum);
 1057         } else if (dgout_routine) {
 1058 #ifdef ARGO_DEBUG
 1059                 if (argo_debug[D_ERROR_EMIT]) {
 1060                         printf("tp_error_emit sending DG: Laddr\n");
 1061                         dump_addr(sisotosa(laddr));
 1062                         printf("Faddr\n");
 1063                         dump_addr(sisotosa(faddr));
 1064                 }
 1065 #endif
 1066                 return (*dgout_routine) (m, datalen, &laddr->siso_addr, &faddr->siso_addr,
 1067                                         (void *) 0, /* nochecksum==false */ 0);
 1068         } else {
 1069 #ifdef ARGO_DEBUG
 1070                 if (argo_debug[D_ERROR_EMIT]) {
 1071                         printf("tp_error_emit DROPPING %p\n", m);
 1072                 }
 1073 #endif
 1074                 IncStat(ts_send_drop);
 1075                 m_freem(m);
 1076                 return 0;
 1077         }
 1078 }

Cache object: 823810c0b894ab070a6bf8e048b9e361


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