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/netccitt/llc_output.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: llc_output.c,v 1.12 2005/02/26 22:45:10 perry Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Dirk Husemann and the Computer Science Department (IV) of
    9  * the University of Erlangen-Nuremberg, Germany.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)llc_output.c        8.1 (Berkeley) 6/10/93
   36  */
   37 
   38 /*
   39  * Copyright (c) 1990, 1991, 1992
   40  *              Dirk Husemann, Computer Science Department IV,
   41  *              University of Erlangen-Nuremberg, Germany.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * Dirk Husemann and the Computer Science Department (IV) of
   45  * the University of Erlangen-Nuremberg, Germany.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. All advertising materials mentioning features or use of this software
   56  *    must display the following acknowledgement:
   57  *      This product includes software developed by the University of
   58  *      California, Berkeley and its contributors.
   59  * 4. Neither the name of the University nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  *
   75  *      @(#)llc_output.c        8.1 (Berkeley) 6/10/93
   76  */
   77 
   78 #include <sys/cdefs.h>
   79 __KERNEL_RCSID(0, "$NetBSD: llc_output.c,v 1.12 2005/02/26 22:45:10 perry Exp $");
   80 
   81 #include <sys/param.h>
   82 #include <sys/systm.h>
   83 #include <sys/mbuf.h>
   84 #include <sys/domain.h>
   85 #include <sys/socket.h>
   86 #include <sys/protosw.h>
   87 #include <sys/errno.h>
   88 #include <sys/time.h>
   89 #include <sys/kernel.h>
   90 
   91 #include <net/if.h>
   92 #include <net/if_dl.h>
   93 #include <net/if_llc.h>
   94 #include <net/route.h>
   95 
   96 #include <netccitt/dll.h>
   97 #include <netccitt/llc_var.h>
   98 
   99 #include <machine/stdarg.h>
  100 
  101 /*
  102  * llc_output() --- called by an upper layer (network layer) entity whenever
  103  *                  there is an INFO frame to be transmitted. We enqueue the
  104  *                  info frame and call llc_start() to do the actual sending.
  105  */
  106 
  107 int
  108 llc_output(struct mbuf *m, ...)
  109 {
  110         struct llc_linkcb *linkp;
  111         int    i = splnet();
  112         va_list ap;
  113 
  114         va_start(ap, m);
  115         linkp = va_arg(ap, struct llc_linkcb *);
  116         va_end(ap);
  117 
  118         LLC_ENQUEUE(linkp, m);
  119         llc_start(linkp);
  120         splx(i);
  121         return 0;
  122 }
  123 
  124 
  125 /*
  126  * llc_start() --- We try to subsequently dequeue all the frames available and
  127  *                 send them out.
  128  */
  129 void
  130 llc_start(linkp)
  131         struct llc_linkcb *linkp;
  132 {
  133         struct mbuf *m;
  134 
  135         while ((LLC_STATEEQ(linkp,NORMAL) || LLC_STATEEQ(linkp,BUSY) ||
  136                 LLC_STATEEQ(linkp,REJECT)) &&
  137                (linkp->llcl_slotsfree > 0) &&
  138                (LLC_GETFLAG(linkp,REMOTE_BUSY) == 0)) {
  139                 LLC_DEQUEUE(linkp,m);
  140                 if (m == NULL)
  141                         break;
  142                 LLC_SETFRAME(linkp, m);
  143                 (void) llc_statehandler(linkp, NULL, NL_DATA_REQUEST, 0, 0);
  144         }
  145 }
  146 
  147 
  148 /*
  149  * llc_send() --- Handles single frames. If dealing with INFO frames we need to
  150  *                prepend the LLC header, otherwise we just allocate an mbuf.
  151  *                In both cases the actual send is done by llc_rawsend().
  152  */
  153 void
  154 llc_send(linkp, frame_kind, cmdrsp, pollfinal)
  155         struct llc_linkcb *linkp;
  156         int frame_kind;
  157         int cmdrsp;
  158         int pollfinal;
  159 {
  160         struct mbuf *m = (struct mbuf *) 0;
  161         struct llc *frame;
  162 
  163         if (frame_kind == LLCFT_INFO)
  164                 m = linkp->llcl_output_buffers[llc_seq2slot(linkp,
  165                                                             linkp->llcl_vs)];
  166         LLC_GETHDR(frame, m);
  167 
  168         /* pass it on to llc_rawsend() */
  169         llc_rawsend(linkp, m, frame, frame_kind, linkp->llcl_vs, cmdrsp, pollfinal);
  170 
  171         if (frame_kind == LLCFT_INFO)
  172                 LLC_INC(linkp->llcl_vs);
  173 }
  174 
  175 /*
  176  * llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames.
  177  */
  178 void
  179 llc_resend(linkp, cmdrsp, pollfinal)
  180         struct llc_linkcb *linkp;
  181         int cmdrsp;
  182         int pollfinal;
  183 {
  184         struct llc *frame;
  185         struct mbuf *m;
  186         int   slot;
  187 
  188         if (linkp->llcl_slotsfree < linkp->llcl_window)
  189                 /* assert lock between nr_received & V(S) */
  190                 if (linkp->llcl_nr_received != linkp->llcl_vs)
  191                         panic("llc: V(S) != N(R) received");
  192 
  193         for (slot = llc_seq2slot(linkp, linkp->llcl_vs);
  194              slot != linkp->llcl_freeslot;
  195              LLC_INC(linkp->llcl_vs),
  196              slot = llc_seq2slot(linkp, linkp->llcl_vs)) {
  197                 m = linkp->llcl_output_buffers[slot];
  198                 LLC_GETHDR(frame, m);
  199                 llc_rawsend(linkp, m, frame, LLCFT_INFO, linkp->llcl_vs,
  200                             cmdrsp, pollfinal);
  201                 pollfinal = 0;
  202         }
  203 }
  204 
  205 /*
  206  * llc_rawsend() --- constructs an LLC frame and sends it out via the
  207  *                   associated interface of the link control block.
  208  *
  209  * We need to make sure that outgoing frames have the correct length,
  210  * in particular the 4 byte ones (RR, RNR, REJ) as LLC_GETHDR() will
  211  * set the mbuf len to 3 as default len for non INFO frames ...
  212  *
  213  * Frame kind             Length (w/o MAC header, {D,S}SAP incl.)
  214  * --------------------------------------------------------------
  215  * DISC, SABME, UA, DM    3 bytes  ({D,S}SAP + CONTROL)
  216  * RR, RNR, REJ           4 bytes  ({D,S}SAP + CONTROL0 + CONTROL1)
  217  * XID                    6 bytes  ({D,S}SAP + CONTROL0 + FI,CLASS,WINDOW)
  218  * FRMR                   7 bytes  ({D,S}SAP + CONTROL0 + REJ CONTROL,V(S),V(R),CAUSE)
  219  * INFO                   4 -- MTU
  220  * UI, TEST               3 -- MTU
  221  *
  222  */
  223 #define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l)
  224 
  225 void
  226 llc_rawsend(linkp, m, frame, frame_kind, vs, cmdrsp, pollfinal)
  227         struct llc_linkcb *linkp;
  228         struct mbuf *m;
  229         struct llc *frame;
  230         int frame_kind;
  231         int vs;
  232         int cmdrsp;
  233         int pollfinal;
  234 {
  235         short  adjust = LLC_UFRAMELEN;
  236         struct ifnet   *ifp;
  237 
  238         switch (frame_kind) {
  239                 /* supervisory and information frames */
  240         case LLCFT_INFO:
  241                 frame->llc_control = LLC_INFO;
  242                 LLCSBITS(frame->llc_control, i_ns, vs);
  243                 LLCSBITS(frame->llc_control_ext, i_nr, linkp->llcl_vr);
  244                 adjust = LLC_ISFRAMELEN;
  245                 break;
  246         case LLCFT_RR:
  247                 frame->llc_control = LLC_RR;
  248                 LLC_SETLEN(m, LLC_ISFRAMELEN);
  249                 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
  250                 adjust = LLC_ISFRAMELEN;
  251                 break;
  252         case LLCFT_RNR:
  253                 frame->llc_control = LLC_RNR;
  254                 LLC_SETLEN(m, LLC_ISFRAMELEN);
  255                 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
  256                 adjust = LLC_ISFRAMELEN;
  257                 break;
  258         case LLCFT_REJ:
  259                 frame->llc_control = LLC_REJ;
  260                 LLC_SETLEN(m, LLC_ISFRAMELEN);
  261                 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
  262                 adjust = LLC_ISFRAMELEN;
  263                 break;
  264                 /* unnumbered frames */
  265         case LLCFT_DM:
  266                 frame->llc_control = LLC_DM;
  267                 break;
  268         case LLCFT_SABME:
  269                 frame->llc_control = LLC_SABME;
  270                 break;
  271         case LLCFT_DISC:
  272                 frame->llc_control = LLC_DISC;
  273                 break;
  274         case LLCFT_UA:
  275                 frame->llc_control = LLC_UA;
  276                 break;
  277         case LLCFT_UI:
  278                 frame->llc_control = LLC_UI;
  279                 break;
  280         case LLCFT_FRMR:
  281                 frame->llc_control = LLC_FRMR;
  282                 /* get more space --- FRMR frame are longer than usual */
  283                 LLC_SETLEN(m, LLC_FRMRLEN);
  284                 bcopy((caddr_t) & linkp->llcl_frmrinfo,
  285                       (caddr_t) & frame->llc_frmrinfo,
  286                       sizeof(struct frmrinfo));
  287                 break;
  288         default:
  289                 /*
  290                  * We don't send {XID, TEST} frames
  291                  */
  292                 if (m)
  293                         m_freem(m);
  294                 return;
  295         }
  296 
  297         /*
  298          * Fill in DSAP/SSAP
  299          */
  300         frame->llc_dsap = frame->llc_ssap = LLSAPADDR(&linkp->llcl_addr);
  301         frame->llc_ssap |= cmdrsp;
  302 
  303         /*
  304          * Check for delayed action pending. ISO 8802-2, 7.9.2 (5)
  305          * and ISO 8802-2, 7.9.2.3 (32), (34), (36) pertain to this
  306          * piece of code --- hopefully we got it right here (i.e.
  307          * in the spirit of (32), (34), and (36) ...
  308          */
  309         switch (frame_kind) {
  310         case LLCFT_RR:
  311         case LLCFT_RNR:
  312         case LLCFT_REJ:
  313         case LLCFT_INFO:
  314                 switch (LLC_GETFLAG(linkp,DACTION)) {
  315                 case LLC_DACKCMD:
  316                 case LLC_DACKRSP:
  317                         LLC_STOPTIMER(linkp,DACTION);
  318                         break;
  319                 case LLC_DACKCMDPOLL:
  320                         if (cmdrsp == LLC_CMD) {
  321                                 pollfinal = 1;
  322                                 LLC_STOPTIMER(linkp,DACTION);
  323                         }
  324                         break;
  325                 case LLC_DACKRSPFINAL:
  326                         if (cmdrsp == LLC_RSP) {
  327                                 pollfinal = 1;
  328                                 LLC_STOPTIMER(linkp,DACTION);
  329                         }
  330                         break;
  331                 }
  332                 break;
  333         }
  334 
  335         if (adjust == LLC_UFRAMELEN)
  336                 LLCSBITS(frame->llc_control,u_pf,pollfinal);
  337         else
  338                 LLCSBITS(frame->llc_control_ext,s_pf,pollfinal);
  339 
  340         /*
  341          * Get interface to send frame onto
  342          */
  343         ifp = linkp->llcl_if;
  344         if (frame_kind == LLCFT_INFO) {
  345                 /*
  346                  * send out a copy of the frame, retain the original
  347                  */
  348                 (*ifp->if_output) (ifp, m_copy(m, 0, (int) M_COPYALL),
  349                                    rt_key(linkp->llcl_nlrt),
  350                                    linkp->llcl_nlrt);
  351                 /*
  352                  * Account for the LLC header and let it ``disappear''
  353                  * as the raw info frame payload is what we hold in
  354                  * the output_buffers of the link.
  355                  */
  356                 m_adj(m, LLC_ISFRAMELEN);
  357         } else
  358                 (*ifp->if_output) (ifp, m,
  359                                    rt_key(linkp->llcl_nlrt),
  360                                    linkp->llcl_nlrt);
  361 }

Cache object: bdba7ae81dd0e102147ab0eb67304b0e


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