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_subr2.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_subr2.c,v 1.22 2003/08/11 15:17:31 itojun 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_subr2.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  * Some auxiliary routines: tp_protocol_error: required by xebec- called when
   62  * a combo of state, event, predicate isn't covered for by the transition
   63  * file. tp_indicate: gives indications(signals) to the user process
   64  * tp_getoptions: initializes variables that are affected by the options
   65  * chosen.
   66  */
   67 
   68 #include <sys/cdefs.h>
   69 __KERNEL_RCSID(0, "$NetBSD: tp_subr2.c,v 1.22 2003/08/11 15:17:31 itojun Exp $");
   70 
   71 /*
   72  * this def'n is to cause the expansion of this macro in the routine
   73  * tp_local_credit :
   74  */
   75 #define LOCAL_CREDIT_EXPAND
   76 
   77 #include "opt_inet.h"
   78 #include "opt_ccitt.h"
   79 #include "opt_iso.h"
   80 
   81 #include <sys/param.h>
   82 #include <sys/systm.h>
   83 #include <sys/mbuf.h>
   84 #include <sys/socket.h>
   85 #include <sys/socketvar.h>
   86 #include <sys/domain.h>
   87 #include <sys/protosw.h>
   88 #include <sys/errno.h>
   89 #include <sys/time.h>
   90 #include <sys/kernel.h>
   91 #include <sys/queue.h>
   92 
   93 #include <net/if.h>
   94 #include <net/if_types.h>
   95 
   96 #include <netiso/argo_debug.h>
   97 #include <netiso/tp_param.h>
   98 #include <netiso/tp_ip.h>
   99 #include <netiso/iso.h>
  100 #include <netiso/iso_errno.h>
  101 #include <netiso/iso_pcb.h>
  102 #include <netiso/iso_var.h>
  103 #include <netiso/tp_timer.h>
  104 #include <netiso/tp_stat.h>
  105 #include <netiso/tp_tpdu.h>
  106 #include <netiso/tp_pcb.h>
  107 #include <netiso/tp_seq.h>
  108 #include <netiso/tp_trace.h>
  109 #include <netiso/tp_user.h>
  110 #include <netiso/tp_var.h>
  111 #include <netiso/cons.h>
  112 #include <netiso/clnp.h>
  113 
  114 #include <netccitt/x25.h>
  115 #include <netccitt/pk.h>
  116 #include <netccitt/pk_var.h>
  117 #include <netccitt/pk_extern.h>
  118 
  119 #if 0
  120 static void copyQOSparms __P((struct tp_conn_param *, struct tp_conn_param *));
  121 #endif
  122 
  123 /*
  124  * NAME:        tp_local_credit()
  125  *
  126  * CALLED FROM:
  127  *  tp_emit(), tp_usrreq()
  128  *
  129  * FUNCTION and ARGUMENTS:
  130  *      Computes the local credit and stashes it in tpcb->tp_lcredit.
  131  *  It's a macro in the production system rather than a procdure.
  132  *
  133  * RETURNS:
  134  *
  135  * SIDE EFFECTS:
  136  *
  137  * NOTES:
  138  *  This doesn't actually get called in a production system -
  139  *  the macro gets expanded instead in place of calls to this proc.
  140  *  But for debugging, we call this and that allows us to add
  141  *  debugging messages easily here.
  142  */
  143 void
  144 tp_local_credit(tpcb)
  145         struct tp_pcb  *tpcb;
  146 {
  147         LOCAL_CREDIT(tpcb);
  148 #ifdef ARGO_DEBUG
  149         if (argo_debug[D_CREDIT]) {
  150                 printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x cong_win 0x%lx\n",
  151                        tpcb->tp_lref,
  152                        tpcb->tp_lcredit,
  153                        tpcb->tp_l_tpdusize,
  154                        tpcb->tp_decbit,
  155                        tpcb->tp_cong_win
  156                         );
  157         }
  158 #endif
  159 #ifdef TPPT
  160         if (tp_traceflags[D_CREDIT]) {
  161                 tptraceTPCB(TPPTmisc,
  162                             "lcdt tpdusz \n",
  163                             tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
  164         }
  165 #endif
  166 }
  167 
  168 /*
  169  * NAME:  tp_protocol_error()
  170  *
  171  * CALLED FROM:
  172  *  tp_driver(), when it doesn't know what to do with
  173  *      a combo of event, state, predicate
  174  *
  175  * FUNCTION and ARGUMENTS:
  176  *  print error mesg
  177  *
  178  * RETURN VALUE:
  179  *  EIO - always
  180  *
  181  * SIDE EFFECTS:
  182  *
  183  * NOTES:
  184  */
  185 int
  186 tp_protocol_error(e, tpcb)
  187         struct tp_event *e;
  188         struct tp_pcb  *tpcb;
  189 {
  190         printf("TP PROTOCOL ERROR! tpcb %p event 0x%x, state 0x%x\n",
  191                tpcb, e->ev_number, tpcb->tp_state);
  192 #ifdef TPPT
  193         if (tp_traceflags[D_DRIVER]) {
  194                 tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
  195                             tpcb, e->ev_number, tpcb->tp_state, 0);
  196         }
  197 #endif
  198         return EIO;     /* for lack of anything better */
  199 }
  200 
  201 
  202 /* Not used at the moment */
  203 void
  204 tp_drain()
  205 {
  206 }
  207 
  208 
  209 /*
  210  * NAME: tp_indicate()
  211  *
  212  * CALLED FROM:
  213  *      tp.trans when XPD arrive, when a connection is being disconnected by
  214  *  the arrival of a DR or ER, and when a connection times out.
  215  *
  216  * FUNCTION and ARGUMENTS:
  217  *  (ind) is the type of indication : T_DISCONNECT, T_XPD
  218  *  (error) is an E* value that will be put in the socket structure
  219  *  to be passed along to the user later.
  220  *      Gives a SIGURG to the user process or group indicated by the socket
  221  *      attached to the tpcb.
  222  *
  223  * RETURNS:  Rien
  224  *
  225  * SIDE EFFECTS:
  226  *
  227  * NOTES:
  228  */
  229 void
  230 tp_indicate(ind, tpcb, error)
  231         int             ind;
  232         u_short         error;
  233         struct tp_pcb *tpcb;
  234 {
  235         struct socket *so = tpcb->tp_sock;
  236 #ifdef TPPT
  237         if (tp_traceflags[D_INDICATION]) {
  238                 tptraceTPCB(TPPTindicate, ind, *(u_short *) (tpcb->tp_lsuffix),
  239                        *(u_short *) (tpcb->tp_fsuffix), error, so->so_pgid);
  240         }
  241 #endif
  242 #ifdef ARGO_DEBUG
  243         if (argo_debug[D_INDICATION]) {
  244                 char           *ls, *fs;
  245                 ls = tpcb->tp_lsuffix,
  246                         fs = tpcb->tp_fsuffix,
  247 
  248                         printf(
  249                                "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x  noind 0x%x ref 0x%x\n",
  250                                ind,
  251                                *ls, *(ls + 1), *fs, *(fs + 1),
  252                                error,   /* so->so_pgrp, */
  253                                tpcb->tp_no_disc_indications,
  254                                tpcb->tp_lref);
  255         }
  256 #endif
  257 
  258         if (ind == ER_TPDU) {
  259                 struct mbuf *m;
  260                 struct tp_disc_reason x;
  261 
  262                 if ((so->so_state & SS_CANTRCVMORE) == 0 &&
  263                     (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
  264 
  265                         x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
  266                         x.dr_hdr.cmsg_level = SOL_TRANSPORT;
  267                         x.dr_hdr.cmsg_type = TPOPT_DISC_REASON;
  268                         x.dr_reason = error;
  269                         *mtod(m, struct tp_disc_reason *) = x;
  270                         sbappendrecord(&tpcb->tp_Xrcv, m);
  271                         error = 0;
  272                 } else
  273                         error = ECONNRESET;
  274         }
  275         so->so_error = error;
  276 
  277         if (ind == T_DISCONNECT) {
  278                 if (error == 0)
  279                         so->so_error = ENOTCONN;
  280                 if (tpcb->tp_no_disc_indications)
  281                         return;
  282         }
  283 #ifdef TPPT
  284         if (tp_traceflags[D_INDICATION]) {
  285                 tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so, 0, 0, 0);
  286         }
  287 #endif
  288         sohasoutofband(so);
  289 }
  290 
  291 /*
  292  * NAME : tp_getoptions()
  293  *
  294  * CALLED FROM:
  295  *      tp.trans whenever we go into OPEN state
  296  *
  297  * FUNCTION and ARGUMENTS:
  298  *  sets the proper flags and values in the tpcb, to control
  299  *  the appropriate actions for the given class, options,
  300  *  sequence space, etc, etc.
  301  *
  302  * RETURNS: Nada
  303  *
  304  * SIDE EFFECTS:
  305  *
  306  * NOTES:
  307  */
  308 void
  309 tp_getoptions(tpcb)
  310         struct tp_pcb  *tpcb;
  311 {
  312         tpcb->tp_seqmask =
  313                 tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK;
  314         tpcb->tp_seqbit =
  315                 tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT;
  316         tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
  317         tpcb->tp_dt_ticks =
  318                 max(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
  319         tp_rsyset(tpcb);
  320 
  321 }
  322 
  323 /*
  324  * NAME:  tp_recycle_tsuffix()
  325  *
  326  * CALLED FROM:
  327  *  Called when a ref is frozen.
  328  *
  329  * FUNCTION and ARGUMENTS:
  330  *  allows the suffix to be reused.
  331  *
  332  * RETURNS: zilch
  333  *
  334  * SIDE EFFECTS:
  335  *
  336  * NOTES:
  337  */
  338 void
  339 tp_recycle_tsuffix(v)
  340         void *v;
  341 {
  342         struct tp_pcb  *tpcb = v;
  343         bzero((caddr_t) tpcb->tp_lsuffix, sizeof(tpcb->tp_lsuffix));
  344         bzero((caddr_t) tpcb->tp_fsuffix, sizeof(tpcb->tp_fsuffix));
  345         tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
  346 
  347         (tpcb->tp_nlproto->nlp_recycle_suffix) (tpcb->tp_npcb);
  348 }
  349 
  350 /*
  351  * NAME: tp_quench()
  352  *
  353  * CALLED FROM:
  354  *  tp{af}_quench() when ICMP source quench or similar thing arrives.
  355  *
  356  * FUNCTION and ARGUMENTS:
  357  *  Drop the congestion window back to 1.
  358  *  Congestion window scheme:
  359  *  Initial value is 1.  ("slow start" as Nagle, et. al. call it)
  360  *  For each good ack that arrives, the congestion window is increased
  361  *  by 1 (up to max size of logical infinity, which is to say,
  362  *      it doesn't wrap around).
  363  *  Source quench causes it to drop back to 1.
  364  *  tp_send() uses the smaller of (regular window, congestion window).
  365  *  One retransmission strategy option is to have any retransmission
  366  *      cause reset the congestion window back  to 1.
  367  *
  368  *      (cmd) is either PRC_QUENCH: source quench, or
  369  *              PRC_QUENCH2: dest. quench (dec bit)
  370  *
  371  * RETURNS:
  372  *
  373  * SIDE EFFECTS:
  374  *
  375  * NOTES:
  376  */
  377 void
  378 tp_quench(ipcb, cmd)
  379         struct inpcb  *ipcb;
  380         int             cmd;
  381 {
  382         struct tp_pcb  *tpcb = (struct tp_pcb *) ipcb;
  383 #ifdef ARGO_DEBUG
  384         if (argo_debug[D_QUENCH]) {
  385                 printf("tp_quench tpcb %p ref 0x%x sufx 0x%x\n",
  386                        tpcb, tpcb->tp_lref, *(u_short *) (tpcb->tp_lsuffix));
  387                 printf("cong_win 0x%lx decbit 0x%x \n",
  388                        tpcb->tp_cong_win, tpcb->tp_decbit);
  389         }
  390 #endif
  391         switch (cmd) {
  392         case PRC_QUENCH:
  393                 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
  394                 IncStat(ts_quench);
  395                 break;
  396         case PRC_QUENCH2:
  397                 /* might as well quench source also */
  398                 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
  399                 tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
  400                 IncStat(ts_rcvdecbit);
  401                 break;
  402         }
  403 }
  404 
  405 
  406 /*
  407  * NAME:        tp_netcmd()
  408  *
  409  * CALLED FROM:
  410  *
  411  * FUNCTION and ARGUMENTS:
  412  *
  413  * RETURNS:
  414  *
  415  * SIDE EFFECTS:
  416  *
  417  * NOTES:
  418  */
  419 void
  420 tp_netcmd(tpcb, cmd)
  421         struct tp_pcb  *tpcb;
  422         int             cmd;
  423 {
  424 #ifdef TPCONS
  425         struct isopcb  *isop;
  426         struct pklcd   *lcp;
  427 
  428         if (tpcb->tp_netservice != ISO_CONS)
  429                 return;
  430         isop = (struct isopcb *) tpcb->tp_npcb;
  431         lcp = (struct pklcd *) isop->isop_chan;
  432         switch (cmd) {
  433 
  434         case CONN_CLOSE:
  435         case CONN_REFUSE:
  436                 if (isop->isop_refcnt == 1) {
  437                         /*
  438                          * This is really superfluous, since it would happen
  439                          * anyway in iso_pcbdetach, although it is a courtesy
  440                          * to free up the x.25 channel before the refwait
  441                          * timer expires.
  442                          */
  443                         lcp->lcd_upper = 0;
  444                         lcp->lcd_upnext = 0;
  445                         pk_disconnect(lcp);
  446                         isop->isop_chan = 0;
  447                         isop->isop_refcnt = 0;
  448                 }
  449                 break;
  450 
  451         default:
  452                 printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
  453                 break;
  454         }
  455 #else                           /* TPCONS */
  456         printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
  457 #endif
  458 }
  459 
  460 /*
  461  * CALLED FROM:
  462  *  tp_ctloutput() and tp_emit()
  463  * FUNCTION and ARGUMENTS:
  464  *      Convert a class mask to the highest numeric value it represents.
  465  */
  466 int
  467 tp_mask_to_num(x)
  468         u_char          x;
  469 {
  470         int    j;
  471 
  472         for (j = 4; j >= 0; j--) {
  473                 if (x & (1 << j))
  474                         break;
  475         }
  476         ASSERT((j == 4) || (j == 0));   /* for now */
  477         if ((j != 4) && (j != 0)) {
  478                 printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
  479                        x, j);
  480         }
  481 #ifdef TPPT
  482         if (tp_traceflags[D_TPINPUT]) {
  483                 tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
  484         }
  485 #endif
  486 #ifdef ARGO_DEBUG
  487         if (argo_debug[D_TPINPUT]) {
  488                 printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
  489         }
  490 #endif
  491         return j;
  492 }
  493 
  494 #if 0
  495 static void
  496 copyQOSparms(src, dst)
  497         struct tp_conn_param *src, *dst;
  498 {
  499         /* copy all but the bits stuff at the end */
  500 #define COPYSIZE (12 * sizeof(short))
  501 
  502         bcopy((caddr_t) src, (caddr_t) dst, COPYSIZE);
  503         dst->p_tpdusize = src->p_tpdusize;
  504         dst->p_ack_strat = src->p_ack_strat;
  505         dst->p_rx_strat = src->p_rx_strat;
  506 #undef COPYSIZE
  507 }
  508 #endif
  509 
  510 /*
  511  * Determine a reasonable value for maxseg size.
  512  * If the route is known, check route for mtu.
  513  * We also initialize the congestion/slow start
  514  * window to be a single segment if the destination isn't local.
  515  * While looking at the routing entry, we also initialize other path-dependent
  516  * parameters from pre-set or cached values in the routing entry.
  517  */
  518 void
  519 tp_mss(tpcb, nhdr_size)
  520         struct tp_pcb *tpcb;
  521         int             nhdr_size;
  522 {
  523         struct rtentry *rt;
  524         struct ifnet   *ifp;
  525         int    rtt, mss;
  526         u_long          bufsize;
  527         int             i, ssthresh = 0, rt_mss;
  528         struct socket  *so;
  529 
  530         if (tpcb->tp_ptpdusize)
  531                 mss = tpcb->tp_ptpdusize << 7;
  532         else
  533                 mss = 1 << tpcb->tp_tpdusize;
  534         so = tpcb->tp_sock;
  535         if ((rt = *(tpcb->tp_routep)) == 0) {
  536                 bufsize = so->so_rcv.sb_hiwat;
  537                 goto punt_route;
  538         }
  539         ifp = rt->rt_ifp;
  540 
  541 #ifdef RTV_MTU                  /* if route characteristics exist ... */
  542         /*
  543          * While we're here, check if there's an initial rtt
  544          * or rttvar.  Convert from the route-table units
  545          * to hz ticks for the smoothed timers and slow-timeout units
  546          * for other inital variables.
  547          */
  548         if (tpcb->tp_rtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
  549                 tpcb->tp_rtt = rtt * hz / RTM_RTTUNIT;
  550                 if (rt->rt_rmx.rmx_rttvar)
  551                         tpcb->tp_rtv = rt->rt_rmx.rmx_rttvar
  552                                 * hz / RTM_RTTUNIT;
  553                 else
  554                         tpcb->tp_rtv = tpcb->tp_rtt;
  555         }
  556         /*
  557          * if there's an mtu associated with the route, use it
  558          */
  559         if (rt->rt_rmx.rmx_mtu)
  560                 rt_mss = rt->rt_rmx.rmx_mtu - nhdr_size;
  561         else
  562 #endif                          /* RTV_MTU */
  563                 rt_mss = (ifp->if_mtu - nhdr_size);
  564         if (tpcb->tp_ptpdusize == 0 ||  /* assume application doesn't care */
  565             mss > rt_mss /* network won't support what was asked for */ )
  566                 mss = rt_mss;
  567         /* can propose mtu which are multiples of 128 */
  568         mss &= ~0x7f;
  569         /*
  570          * If there's a pipesize, change the socket buffer
  571          * to that size.
  572          */
  573 #ifdef RTV_SPIPE
  574         if ((bufsize = rt->rt_rmx.rmx_sendpipe) > 0) {
  575 #endif
  576                 bufsize = min(bufsize, so->so_snd.sb_hiwat);
  577                 (void) sbreserve(&so->so_snd, bufsize);
  578         }
  579 #ifdef RTV_SPIPE
  580         if ((bufsize = rt->rt_rmx.rmx_recvpipe) > 0) {
  581 #endif
  582                 bufsize = min(bufsize, so->so_rcv.sb_hiwat);
  583                 (void) sbreserve(&so->so_rcv, bufsize);
  584         } else
  585                 bufsize = so->so_rcv.sb_hiwat;
  586 #ifdef RTV_SSTHRESH
  587         /*
  588          * There's some sort of gateway or interface
  589          * buffer limit on the path.  Use this to set
  590          * the slow start threshhold, but set the
  591          * threshold to no less than 2*mss.
  592          */
  593         ssthresh = rt->rt_rmx.rmx_ssthresh;
  594 punt_route:
  595         /*
  596          * The current mss is initialized to the default value.
  597          * If we compute a smaller value, reduce the current mss.
  598          * If we compute a larger value, return it for use in sending
  599          * a max seg size option.
  600          * If we received an offer, don't exceed it.
  601          * However, do not accept offers under 128 bytes.
  602          */
  603         if (tpcb->tp_l_tpdusize)
  604                 mss = min(mss, tpcb->tp_l_tpdusize);
  605         /*
  606          * We want a minimum recv window of 4 packets to
  607          * signal packet loss by duplicate acks.
  608          */
  609         mss = min(mss, bufsize >> 2) & ~0x7f;
  610         mss = max(mss, 128);    /* sanity */
  611         tpcb->tp_cong_win =
  612                 (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) ? mss : bufsize;
  613         tpcb->tp_l_tpdusize = mss;
  614         tp_rsyset(tpcb);
  615         tpcb->tp_ssthresh = max(2 * mss, ssthresh);
  616         /* Calculate log2 of mss */
  617         for (i = TP_MIN_TPDUSIZE + 1; i <= TP_MAX_TPDUSIZE; i++)
  618                 if ((1 << i) > mss)
  619                         break;
  620         i--;
  621         tpcb->tp_tpdusize = i;
  622 #endif  /* RTV_MTU */
  623 }
  624 
  625 /*
  626  * CALLED FROM:
  627  *  tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
  628  *
  629  * FUNCTION and ARGUMENTS:
  630  *      -- An mbuf containing the peer's network address.
  631  *  -- Our control block, which will be modified
  632  *  -- In the case of cons, a control block for that layer.
  633  *
  634  *
  635  * RETURNS:
  636  *      errno value      :
  637  *      EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
  638  *      ECONNREFUSED if trying to run TP0 with non-type 37 address
  639  *  possibly other E* returned from cons_netcmd()
  640  *
  641  * SIDE EFFECTS:
  642  *   Determines recommended tpdusize, buffering and intial delays
  643  *       based on information cached on the route.
  644  */
  645 int
  646 tp_route_to(m, tpcb, channel)
  647         struct mbuf    *m;
  648         struct tp_pcb *tpcb;
  649         caddr_t         channel;
  650 {
  651         struct sockaddr_iso *siso;      /* NOTE: this may be a
  652                                                  * sockaddr_in */
  653         int             error = 0, save_netservice = tpcb->tp_netservice;
  654         struct rtentry *rt = 0;
  655         int             nhdr_size;
  656 
  657         siso = mtod(m, struct sockaddr_iso *);
  658 #ifdef TPPT
  659         if (tp_traceflags[D_CONN]) {
  660                 tptraceTPCB(TPPTmisc,
  661                             "route_to: so  afi netservice class",
  662         tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
  663                             tpcb->tp_class);
  664         }
  665 #endif
  666 #ifdef ARGO_DEBUG
  667                 if (argo_debug[D_CONN]) {
  668                 printf("tp_route_to( m %p, channel %p, tpcb %p netserv 0x%x)\n",
  669                        m, channel, tpcb, tpcb->tp_netservice);
  670                 printf("m->mlen x%x, m->m_data:\n", m->m_len);
  671                 dump_buf(mtod(m, caddr_t), m->m_len);
  672         }
  673 #endif
  674         if (channel) {
  675 #ifdef TPCONS
  676                 struct pklcd   *lcp = (struct pklcd *) channel;
  677                 struct isopcb  *isop = (struct isopcb *) lcp->lcd_upnext,
  678                                *isop_new = (struct isopcb *) tpcb->tp_npcb;
  679                 /*
  680                  * The next 2 lines believe that you haven't set any network
  681                  * level options or done a pcbconnect and XXXXXXX'edly apply
  682                  * to both inpcb's and isopcb's
  683                  */
  684                 remque(isop_new);
  685                 free(isop_new, M_PCB);
  686                 tpcb->tp_npcb = (caddr_t) isop;
  687                 tpcb->tp_netservice = ISO_CONS;
  688                 tpcb->tp_nlproto = nl_protosw + ISO_CONS;
  689                 if (isop->isop_refcnt++ == 0) {
  690                         iso_putsufx(isop, tpcb->tp_lsuffix,
  691                                     tpcb->tp_lsuffixlen, TP_LOCAL);
  692                         isop->isop_socket = tpcb->tp_sock;
  693                 }
  694 #endif
  695         } else {
  696                 switch (siso->siso_family) {
  697                 default:
  698                         error = EAFNOSUPPORT;
  699                         goto done;
  700 #ifdef ISO
  701                 case AF_ISO:
  702                         {
  703                                 struct isopcb  *isop = (struct isopcb *) tpcb->tp_npcb;
  704                                 int             flags = tpcb->tp_sock->so_options & SO_DONTROUTE;
  705                                 tpcb->tp_netservice = ISO_CLNS;
  706                                 if (clnp_route(&siso->siso_addr, &isop->isop_route,
  707                                     flags, NULL, NULL) == 0) {
  708                                         rt = isop->isop_route.ro_rt;
  709                                         if (rt && rt->rt_flags & RTF_PROTO1)
  710                                                 tpcb->tp_netservice = ISO_CONS;
  711                                 }
  712                         } break;
  713 #endif
  714 #ifdef INET
  715                 case AF_INET:
  716                         tpcb->tp_netservice = IN_CLNS;
  717 #endif
  718                 }
  719                 if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) {
  720 #ifdef ARGO_DEBUG
  721                         if (argo_debug[D_CONN]) {
  722                                 printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
  723                                        save_netservice, tpcb->tp_netservice);
  724                         }
  725 #endif
  726                         if ((error = tp_set_npcb(tpcb)) != 0)
  727                                 goto done;
  728                 }
  729 #ifdef ARGO_DEBUG
  730                 if (argo_debug[D_CONN]) {
  731                         printf("tp_route_to  calling nlp_pcbconn, netserv %d\n",
  732                                tpcb->tp_netservice);
  733                 }
  734 #endif
  735                 tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice;
  736                 error = (*tpcb->tp_nlproto->nlp_pcbconn) (tpcb->tp_npcb, m);
  737         }
  738         if (error)
  739                 goto done;
  740         /* only gets common info */
  741         nhdr_size = (*tpcb->tp_nlproto->nlp_mtu)(tpcb);
  742         tp_mss(tpcb, nhdr_size);
  743 done:
  744 #ifdef ARGO_DEBUG
  745         if (argo_debug[D_CONN]) {
  746                 printf("tp_route_to  returns 0x%x\n", error);
  747         }
  748 #endif
  749 #ifdef TPPT
  750         if (tp_traceflags[D_CONN]) {
  751                 tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
  752                             tpcb->tp_netservice, tpcb->tp_class, 0);
  753         }
  754 #endif
  755         return error;
  756 }
  757 
  758 #ifndef CCITT
  759 void
  760 pk_flowcontrol(lcp, foo, bar)
  761         struct pklcd *lcp;
  762         int foo, bar;
  763 {
  764 }
  765 #endif
  766 
  767 /* class zero version */
  768 void
  769 tp0_stash(tpcb, e)
  770         struct tp_pcb *tpcb;
  771         struct tp_event *e;
  772 {
  773 #define E e->TPDU_ATTR(DT)
  774 
  775         struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
  776         struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
  777 
  778 #ifdef TP_PERF_MEAS
  779         if (DOPERF(tpcb)) {
  780                 PStat(tpcb, Nb_from_ll) += E.e_datalen;
  781         tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
  782                E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
  783         }
  784 #endif
  785 
  786 #ifdef ARGO_DEBUG
  787                 if (argo_debug[D_STASH]) {
  788                 printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
  789                        E.e_seq, E.e_datalen, E.e_eot);
  790         }
  791 #endif
  792 
  793 #ifdef TPPT
  794         if (tp_traceflags[D_STASH]) {
  795                 tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
  796                             E.e_seq, E.e_datalen, E.e_eot, 0);
  797         }
  798 #endif
  799 
  800         if (E.e_eot) {
  801                 struct mbuf *n = E.e_data;
  802                 n->m_flags |= M_EOR;
  803                 n->m_nextpkt = NULL;    /* set on tp_input */
  804         }
  805         sbappend(sb, E.e_data);
  806 #ifdef ARGO_DEBUG
  807         if (argo_debug[D_STASH]) {
  808                 dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
  809         }
  810 #endif
  811         if (tpcb->tp_netservice != ISO_CONS)
  812                 printf("tp0_stash: tp running over something weird\n");
  813         else {
  814                 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
  815                 pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
  816         }
  817 }
  818 
  819 void
  820 tp0_openflow(tpcb)
  821         struct tp_pcb *tpcb;
  822 {
  823         struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
  824         if (tpcb->tp_netservice != ISO_CONS)
  825                 printf("tp0_openflow: tp running over something weird\n");
  826         else {
  827                 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
  828                 if (lcp->lcd_rxrnr_condition)
  829                         pk_flowcontrol(lcp, 0, 0);
  830         }
  831 }
  832 
  833 #ifdef TP_PERF_MEAS
  834 /*
  835  * CALLED FROM:
  836  *  tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
  837  *  and tp_newsocket() when a new connection is made from
  838  *  a listening socket with tp_perf_on == true.
  839  * FUNCTION and ARGUMENTS:
  840  *  (tpcb) is the usual; this procedure gets a clear cluster mbuf for
  841  *  a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
  842  * RETURN VALUE:
  843  *  ENOBUFS if it cannot get a cluster mbuf.
  844  */
  845 
  846 int
  847 tp_setup_perf(tpcb)
  848         struct tp_pcb *tpcb;
  849 {
  850         if (tpcb->tp_p_meas == 0) {
  851                 tpcb->tp_p_meas = malloc(sizeof(struct tp_pmeas), M_PCB, M_WAITOK);
  852                 bzero((caddr_t)tpcb->tp_p_meas, sizeof(struct tp_pmeas));
  853 #ifdef ARGO_DEBUG
  854                 if (argo_debug[D_PERF_MEAS]) {
  855                         printf(
  856                                "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
  857                                tpcb, tpcb->tp_sock, tpcb->tp_lref,
  858                                tpcb->tp_p_meas, tpcb->tp_perf_on);
  859                 }
  860 #endif
  861                 tpcb->tp_perf_on = 1;
  862         }
  863         return 0;
  864 }
  865 #endif                          /* TP_PERF_MEAS */
  866 
  867 #ifdef ARGO_DEBUG
  868 void
  869 dump_addr(addr)
  870         struct sockaddr *addr;
  871 {
  872         switch (addr->sa_family) {
  873         case AF_INET:
  874                 dump_inaddr(satosin(addr));
  875                 break;
  876 #ifdef ISO
  877         case AF_ISO:
  878                 dump_isoaddr(satosiso(addr));
  879                 break;
  880 #endif                          /* ISO */
  881         default:
  882                 printf("BAD AF: 0x%x\n", addr->sa_family);
  883                 break;
  884         }
  885 }
  886 
  887 #define MAX_COLUMNS     8
  888 /*
  889  *      Dump the buffer to the screen in a readable format. Format is:
  890  *
  891  *              hex/dec  where hex is the hex format, dec is the decimal format.
  892  *              columns of hex/dec numbers will be printed, followed by the
  893  *              character representations (if printable).
  894  */
  895 void
  896 Dump_buf(buf, len)
  897         caddr_t         buf;
  898         int             len;
  899 {
  900         int             i, j;
  901 #define Buf ((u_char *)buf)
  902         printf("Dump buf %p len 0x%x\n", buf, len);
  903         for (i = 0; i < len; i += MAX_COLUMNS) {
  904                 printf("+%d:\t", i);
  905                 for (j = 0; j < MAX_COLUMNS; j++) {
  906                         if (i + j < len) {
  907                                 printf("%x/%d\t", Buf[i + j], Buf[i + j]);
  908                         } else {
  909                                 printf("        ");
  910                         }
  911                 }
  912 
  913                 for (j = 0; j < MAX_COLUMNS; j++) {
  914                         if (i + j < len) {
  915                                 if (((Buf[i + j]) > 31) && ((Buf[i + j]) < 128))
  916                                         printf("%c", Buf[i + j]);
  917                                 else
  918                                         printf(".");
  919                         }
  920                 }
  921                 printf("\n");
  922         }
  923 }
  924 #endif /* ARGO_DEBUG */

Cache object: 33b12f967cc9e3a3792851b8d5fd37c7


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