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.10 2003/08/07 16:33:02 agc 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.10 2003/08/07 16:33:02 agc 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 #if __STDC__
  109 llc_output(struct mbuf *m, ...)
  110 #else
  111 llc_output(m, va_alist)
  112         struct mbuf *m;
  113         va_dcl
  114 #endif
  115 {
  116         struct llc_linkcb *linkp;
  117         int    i = splnet();
  118         va_list ap;
  119 
  120         va_start(ap, m);
  121         linkp = va_arg(ap, struct llc_linkcb *);
  122         va_end(ap);
  123 
  124         LLC_ENQUEUE(linkp, m);
  125         llc_start(linkp);
  126         splx(i);
  127         return 0;
  128 }
  129 
  130 
  131 /*
  132  * llc_start() --- We try to subsequently dequeue all the frames available and
  133  *                 send them out.
  134  */
  135 void
  136 llc_start(linkp)
  137         struct llc_linkcb *linkp;
  138 {
  139         struct mbuf *m;
  140 
  141         while ((LLC_STATEEQ(linkp,NORMAL) || LLC_STATEEQ(linkp,BUSY) ||
  142                 LLC_STATEEQ(linkp,REJECT)) &&
  143                (linkp->llcl_slotsfree > 0) &&
  144                (LLC_GETFLAG(linkp,REMOTE_BUSY) == 0)) {
  145                 LLC_DEQUEUE(linkp,m);
  146                 if (m == NULL)
  147                         break;
  148                 LLC_SETFRAME(linkp, m);
  149                 (void) llc_statehandler(linkp, NULL, NL_DATA_REQUEST, 0, 0);
  150         }
  151 }
  152 
  153 
  154 /*
  155  * llc_send() --- Handles single frames. If dealing with INFO frames we need to
  156  *                prepend the LLC header, otherwise we just allocate an mbuf.
  157  *                In both cases the actual send is done by llc_rawsend().
  158  */
  159 void
  160 llc_send(linkp, frame_kind, cmdrsp, pollfinal)
  161         struct llc_linkcb *linkp;
  162         int frame_kind;
  163         int cmdrsp;
  164         int pollfinal;
  165 {
  166         struct mbuf *m = (struct mbuf *) 0;
  167         struct llc *frame;
  168 
  169         if (frame_kind == LLCFT_INFO)
  170                 m = linkp->llcl_output_buffers[llc_seq2slot(linkp,
  171                                                             linkp->llcl_vs)];
  172         LLC_GETHDR(frame, m);
  173 
  174         /* pass it on to llc_rawsend() */
  175         llc_rawsend(linkp, m, frame, frame_kind, linkp->llcl_vs, cmdrsp, pollfinal);
  176 
  177         if (frame_kind == LLCFT_INFO)
  178                 LLC_INC(linkp->llcl_vs);
  179 }
  180 
  181 /*
  182  * llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames.
  183  */
  184 void
  185 llc_resend(linkp, cmdrsp, pollfinal)
  186         struct llc_linkcb *linkp;
  187         int cmdrsp;
  188         int pollfinal;
  189 {
  190         struct llc *frame;
  191         struct mbuf *m;
  192         int   slot;
  193 
  194         if (linkp->llcl_slotsfree < linkp->llcl_window)
  195                 /* assert lock between nr_received & V(S) */
  196                 if (linkp->llcl_nr_received != linkp->llcl_vs)
  197                         panic("llc: V(S) != N(R) received");
  198 
  199         for (slot = llc_seq2slot(linkp, linkp->llcl_vs);
  200              slot != linkp->llcl_freeslot;
  201              LLC_INC(linkp->llcl_vs),
  202              slot = llc_seq2slot(linkp, linkp->llcl_vs)) {
  203                 m = linkp->llcl_output_buffers[slot];
  204                 LLC_GETHDR(frame, m);
  205                 llc_rawsend(linkp, m, frame, LLCFT_INFO, linkp->llcl_vs,
  206                             cmdrsp, pollfinal);
  207                 pollfinal = 0;
  208         }
  209 }
  210 
  211 /*
  212  * llc_rawsend() --- constructs an LLC frame and sends it out via the
  213  *                   associated interface of the link control block.
  214  *
  215  * We need to make sure that outgoing frames have the correct length,
  216  * in particular the 4 byte ones (RR, RNR, REJ) as LLC_GETHDR() will
  217  * set the mbuf len to 3 as default len for non INFO frames ...
  218  *
  219  * Frame kind             Length (w/o MAC header, {D,S}SAP incl.)
  220  * --------------------------------------------------------------
  221  * DISC, SABME, UA, DM    3 bytes  ({D,S}SAP + CONTROL)
  222  * RR, RNR, REJ           4 bytes  ({D,S}SAP + CONTROL0 + CONTROL1)
  223  * XID                    6 bytes  ({D,S}SAP + CONTROL0 + FI,CLASS,WINDOW)
  224  * FRMR                   7 bytes  ({D,S}SAP + CONTROL0 + REJ CONTROL,V(S),V(R),CAUSE)
  225  * INFO                   4 -- MTU
  226  * UI, TEST               3 -- MTU
  227  *
  228  */
  229 #define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l)
  230 
  231 void
  232 llc_rawsend(linkp, m, frame, frame_kind, vs, cmdrsp, pollfinal)
  233         struct llc_linkcb *linkp;
  234         struct mbuf *m;
  235         struct llc *frame;
  236         int frame_kind;
  237         int vs;
  238         int cmdrsp;
  239         int pollfinal;
  240 {
  241         short  adjust = LLC_UFRAMELEN;
  242         struct ifnet   *ifp;
  243 
  244         switch (frame_kind) {
  245                 /* supervisory and information frames */
  246         case LLCFT_INFO:
  247                 frame->llc_control = LLC_INFO;
  248                 LLCSBITS(frame->llc_control, i_ns, vs);
  249                 LLCSBITS(frame->llc_control_ext, i_nr, linkp->llcl_vr);
  250                 adjust = LLC_ISFRAMELEN;
  251                 break;
  252         case LLCFT_RR:
  253                 frame->llc_control = LLC_RR;
  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_RNR:
  259                 frame->llc_control = LLC_RNR;
  260                 LLC_SETLEN(m, LLC_ISFRAMELEN);
  261                 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
  262                 adjust = LLC_ISFRAMELEN;
  263                 break;
  264         case LLCFT_REJ:
  265                 frame->llc_control = LLC_REJ;
  266                 LLC_SETLEN(m, LLC_ISFRAMELEN);
  267                 LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
  268                 adjust = LLC_ISFRAMELEN;
  269                 break;
  270                 /* unnumbered frames */
  271         case LLCFT_DM:
  272                 frame->llc_control = LLC_DM;
  273                 break;
  274         case LLCFT_SABME:
  275                 frame->llc_control = LLC_SABME;
  276                 break;
  277         case LLCFT_DISC:
  278                 frame->llc_control = LLC_DISC;
  279                 break;
  280         case LLCFT_UA:
  281                 frame->llc_control = LLC_UA;
  282                 break;
  283         case LLCFT_UI:
  284                 frame->llc_control = LLC_UI;
  285                 break;
  286         case LLCFT_FRMR:
  287                 frame->llc_control = LLC_FRMR;
  288                 /* get more space --- FRMR frame are longer than usual */
  289                 LLC_SETLEN(m, LLC_FRMRLEN);
  290                 bcopy((caddr_t) & linkp->llcl_frmrinfo,
  291                       (caddr_t) & frame->llc_frmrinfo,
  292                       sizeof(struct frmrinfo));
  293                 break;
  294         default:
  295                 /*
  296                  * We don't send {XID, TEST} frames
  297                  */
  298                 if (m)
  299                         m_freem(m);
  300                 return;
  301         }
  302 
  303         /*
  304          * Fill in DSAP/SSAP
  305          */
  306         frame->llc_dsap = frame->llc_ssap = LLSAPADDR(&linkp->llcl_addr);
  307         frame->llc_ssap |= cmdrsp;
  308 
  309         /*
  310          * Check for delayed action pending. ISO 8802-2, 7.9.2 (5)
  311          * and ISO 8802-2, 7.9.2.3 (32), (34), (36) pertain to this
  312          * piece of code --- hopefully we got it right here (i.e.
  313          * in the spirit of (32), (34), and (36) ...
  314          */
  315         switch (frame_kind) {
  316         case LLCFT_RR:
  317         case LLCFT_RNR:
  318         case LLCFT_REJ:
  319         case LLCFT_INFO:
  320                 switch (LLC_GETFLAG(linkp,DACTION)) {
  321                 case LLC_DACKCMD:
  322                 case LLC_DACKRSP:
  323                         LLC_STOPTIMER(linkp,DACTION);
  324                         break;
  325                 case LLC_DACKCMDPOLL:
  326                         if (cmdrsp == LLC_CMD) {
  327                                 pollfinal = 1;
  328                                 LLC_STOPTIMER(linkp,DACTION);
  329                         }
  330                         break;
  331                 case LLC_DACKRSPFINAL:
  332                         if (cmdrsp == LLC_RSP) {
  333                                 pollfinal = 1;
  334                                 LLC_STOPTIMER(linkp,DACTION);
  335                         }
  336                         break;
  337                 }
  338                 break;
  339         }
  340 
  341         if (adjust == LLC_UFRAMELEN)
  342                 LLCSBITS(frame->llc_control,u_pf,pollfinal);
  343         else
  344                 LLCSBITS(frame->llc_control_ext,s_pf,pollfinal);
  345 
  346         /*
  347          * Get interface to send frame onto
  348          */
  349         ifp = linkp->llcl_if;
  350         if (frame_kind == LLCFT_INFO) {
  351                 /*
  352                  * send out a copy of the frame, retain the original
  353                  */
  354                 (*ifp->if_output) (ifp, m_copy(m, 0, (int) M_COPYALL),
  355                                    rt_key(linkp->llcl_nlrt),
  356                                    linkp->llcl_nlrt);
  357                 /*
  358                  * Account for the LLC header and let it ``disappear''
  359                  * as the raw info frame payload is what we hold in
  360                  * the output_buffers of the link.
  361                  */
  362                 m_adj(m, LLC_ISFRAMELEN);
  363         } else
  364                 (*ifp->if_output) (ifp, m,
  365                                    rt_key(linkp->llcl_nlrt),
  366                                    linkp->llcl_nlrt);
  367 }

Cache object: f56f178919a8dbd140a999c11ca58312


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