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/netatm/atm_subr.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 /*-
    2  * ===================================
    3  * HARP  |  Host ATM Research Platform
    4  * ===================================
    5  *
    6  *
    7  * This Host ATM Research Platform ("HARP") file (the "Software") is
    8  * made available by Network Computing Services, Inc. ("NetworkCS")
    9  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   10  * support of any kind.
   11  *
   12  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   13  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   14  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   15  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   16  * In no event shall NetworkCS be responsible for any damages, including
   17  * but not limited to consequential damages, arising from or relating to
   18  * any use of the Software or related support.
   19  *
   20  * Copyright 1994-1998 Network Computing Services, Inc.
   21  *
   22  * Copies of this Software may be made, however, the above copyright
   23  * notice must be reproduced on all copies.
   24  */
   25 
   26 /*
   27  * Core ATM Services
   28  * -----------------
   29  *
   30  * Miscellaneous ATM subroutines
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/errno.h>
   39 #include <sys/malloc.h>
   40 #include <sys/time.h>
   41 #include <sys/kernel.h>
   42 #include <sys/socket.h>
   43 #include <sys/socketvar.h>
   44 #include <sys/sysctl.h>
   45 #include <net/if.h>
   46 #include <net/netisr.h>
   47 #include <netatm/port.h>
   48 #include <netatm/queue.h>
   49 #include <netatm/atm.h>
   50 #include <netatm/atm_sys.h>
   51 #include <netatm/atm_sap.h>
   52 #include <netatm/atm_cm.h>
   53 #include <netatm/atm_if.h>
   54 #include <netatm/atm_stack.h>
   55 #include <netatm/atm_pcb.h>
   56 #include <netatm/atm_var.h>
   57 #include <vm/uma.h>
   58 
   59 /*
   60  * Global variables
   61  */
   62 struct atm_pif          *atm_interface_head = NULL;
   63 struct atm_ncm          *atm_netconv_head = NULL;
   64 Atm_endpoint            *atm_endpoints[ENDPT_MAX+1] = {NULL};
   65 struct stackq_entry     *atm_stackq_head = NULL, *atm_stackq_tail;
   66 struct atm_sock_stat    atm_sock_stat = { { 0 } };
   67 int                     atm_init = 0;
   68 int                     atm_version = ATM_VERSION;
   69 struct timeval          atm_debugtime = {0, 0};
   70 struct ifqueue          atm_intrq;
   71 
   72 uma_zone_t atm_attributes_zone;
   73 
   74 /*
   75  * net.harp.atm.atm_debug
   76  */
   77 int atm_debug;
   78 SYSCTL_INT(_net_harp_atm, OID_AUTO, atm_debug, CTLFLAG_RW,
   79     &atm_debug, 0, "HARP ATM layer debugging flag");
   80 
   81 /*
   82  * net.harp.atm.atm_dev_print
   83  */
   84 int atm_dev_print;
   85 SYSCTL_INT(_net_harp_atm, OID_AUTO, atm_dev_print, CTLFLAG_RW,
   86     &atm_dev_print, 0, "display ATM CPCS headers");
   87 
   88 /*
   89  * net.harp.atm.atm_print_data
   90  */
   91 int atm_print_data;
   92 SYSCTL_INT(_net_harp_atm, OID_AUTO, atm_print_data, CTLFLAG_RW,
   93     &atm_print_data, 0, "display ATM CPCS payloads");
   94 
   95 /*
   96  * Local functions
   97  */
   98 static KTimeout_ret     atm_timexp(void *);
   99 static void             atm_intr(struct mbuf *);
  100 
  101 /*
  102  * Local variables
  103  */
  104 static struct atm_time  *atm_timeq = NULL;
  105 static uma_zone_t atm_stackq_zone;
  106 
  107 /*
  108  * Initialize ATM kernel
  109  * 
  110  * Performs any initialization required before things really get underway.
  111  * Called from ATM domain initialization or from first registration function 
  112  * which gets called.
  113  *
  114  * Arguments:
  115  *      none
  116  *
  117  * Returns:
  118  *      none
  119  *
  120  */
  121 void
  122 atm_initialize()
  123 {
  124         /*
  125          * Never called from interrupts, so no locking needed
  126          */
  127         if (atm_init)
  128                 return;
  129         atm_init = 1;
  130 
  131         atm_attributes_zone = uma_zcreate("atm attributes",
  132             sizeof(Atm_attributes), NULL, NULL, NULL, NULL,
  133             UMA_ALIGN_PTR, 0);
  134         if (atm_attributes_zone == NULL)
  135                 panic("atm_initialize: unable to create attributes zone");
  136 
  137         atm_stackq_zone = uma_zcreate("atm stackq", sizeof(struct stackq_entry),
  138             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  139         if (atm_stackq_zone == NULL)
  140                 panic("atm_initialize: unable to create stackq zone");
  141 
  142         atm_intrq.ifq_maxlen = ATM_INTRQ_MAX;
  143         mtx_init(&atm_intrq.ifq_mtx, "atm_inq", NULL, MTX_DEF);
  144         netisr_register(NETISR_ATM, atm_intr, &atm_intrq, 0);
  145 
  146         /*
  147          * Initialize subsystems
  148          */
  149         atm_sock_init();
  150         atm_cm_init();
  151         atm_aal5_init();
  152 
  153         /*
  154          * Prime the timer
  155          */
  156         (void)timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  157 }
  158 
  159 
  160 /*
  161  * Handle timer tick expiration
  162  * 
  163  * Decrement tick count in first block on timer queue.  If there
  164  * are blocks with expired timers, call their timeout function.
  165  * This function is called ATM_HZ times per second.
  166  *
  167  * Arguments:
  168  *      arg     argument passed on timeout() call
  169  *
  170  * Returns:
  171  *      none
  172  *
  173  */
  174 static KTimeout_ret
  175 atm_timexp(arg)
  176         void    *arg;
  177 {
  178         struct atm_time *tip;
  179         int             s = splimp();
  180 
  181 
  182         /*
  183          * Decrement tick count
  184          */
  185         if (((tip = atm_timeq) == NULL) || (--tip->ti_ticks > 0)) {
  186                 goto restart;
  187         }
  188 
  189         /*
  190          * Stack queue should have been drained
  191          */
  192         KASSERT(atm_stackq_head == NULL, ("atm_timexp: stack queue not empty"));
  193 
  194         /*
  195          * Dispatch expired timers
  196          */
  197         while (((tip = atm_timeq) != NULL) && (tip->ti_ticks == 0)) {
  198                 void    (*func)(struct atm_time *);
  199 
  200                 /*
  201                  * Remove expired block from queue
  202                  */
  203                 atm_timeq = tip->ti_next;
  204                 tip->ti_flag &= ~TIF_QUEUED;
  205 
  206                 /*
  207                  * Call timeout handler (with network interrupts locked out)
  208                  */
  209                 func = tip->ti_func;
  210                 (void) splx(s);
  211                 s = splnet();
  212                 (*func)(tip);
  213                 (void) splx(s);
  214                 s = splimp();
  215 
  216                 /*
  217                  * Drain any deferred calls
  218                  */
  219                 STACK_DRAIN();
  220         }
  221 
  222 restart:
  223         /*
  224          * Restart the timer
  225          */
  226         (void) splx(s);
  227         (void) timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  228 
  229         return;
  230 }
  231 
  232 
  233 /*
  234  * Schedule a control block timeout
  235  * 
  236  * Place the supplied timer control block on the timer queue.  The
  237  * function (func) will be called in 't' timer ticks with the
  238  * control block address as its only argument.  There are ATM_HZ
  239  * timer ticks per second.  The ticks value stored in each block is
  240  * a delta of the number of ticks from the previous block in the queue.
  241  * Thus, for each tick interval, only the first block in the queue 
  242  * needs to have its tick value decremented.
  243  *
  244  * Arguments:
  245  *      tip     pointer to timer control block
  246  *      t       number of timer ticks until expiration
  247  *      func    pointer to function to call at expiration 
  248  *
  249  * Returns:
  250  *      none
  251  *
  252  */
  253 void
  254 atm_timeout(tip, t, func)
  255         struct atm_time *tip;
  256         int             t;
  257         void            (*func)(struct atm_time *);
  258 {
  259         struct atm_time *tip1, *tip2;
  260         int             s;
  261 
  262 
  263         /*
  264          * Check for double queueing error
  265          */
  266         if (tip->ti_flag & TIF_QUEUED)
  267                 panic("atm_timeout: double queueing");
  268 
  269         /*
  270          * Make sure we delay at least a little bit
  271          */
  272         if (t <= 0)
  273                 t = 1;
  274 
  275         /*
  276          * Find out where we belong on the queue
  277          */
  278         s = splimp();
  279         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2->ti_ticks <= t); 
  280                                             tip1 = tip2, tip2 = tip1->ti_next) {
  281                 t -= tip2->ti_ticks;
  282         }
  283 
  284         /*
  285          * Place ourselves on queue and update timer deltas
  286          */
  287         if (tip1 == NULL)
  288                 atm_timeq = tip;
  289         else
  290                 tip1->ti_next = tip;
  291         tip->ti_next = tip2;
  292 
  293         if (tip2)
  294                 tip2->ti_ticks -= t;
  295         
  296         /*
  297          * Setup timer block
  298          */
  299         tip->ti_flag |= TIF_QUEUED;
  300         tip->ti_ticks = t;
  301         tip->ti_func = func;
  302 
  303         (void) splx(s);
  304         return;
  305 }
  306 
  307 
  308 /*
  309  * Cancel a timeout
  310  * 
  311  * Remove the supplied timer control block from the timer queue.
  312  *
  313  * Arguments:
  314  *      tip     pointer to timer control block
  315  *
  316  * Returns:
  317  *      0       control block successfully dequeued
  318  *      1       control block not on timer queue
  319  *
  320  */
  321 int
  322 atm_untimeout(tip)
  323         struct atm_time *tip;
  324 {
  325         struct atm_time *tip1, *tip2;
  326         int             s;
  327 
  328         /*
  329          * Is control block queued?
  330          */
  331         if ((tip->ti_flag & TIF_QUEUED) == 0)
  332                 return(1);
  333 
  334         /*
  335          * Find control block on the queue
  336          */
  337         s = splimp();
  338         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2 != tip); 
  339                                             tip1 = tip2, tip2 = tip1->ti_next) {
  340         }
  341 
  342         if (tip2 == NULL) {
  343                 (void) splx(s);
  344                 return (1);
  345         }
  346 
  347         /*
  348          * Remove block from queue and update timer deltas
  349          */
  350         tip2 = tip->ti_next;
  351         if (tip1 == NULL)
  352                 atm_timeq = tip2;
  353         else
  354                 tip1->ti_next = tip2;
  355 
  356         if (tip2)
  357                 tip2->ti_ticks += tip->ti_ticks;
  358         
  359         /*
  360          * Reset timer block
  361          */
  362         tip->ti_flag &= ~TIF_QUEUED;
  363 
  364         (void) splx(s);
  365         return (0);
  366 }
  367 
  368 
  369 /*
  370  * Queue a Stack Call 
  371  * 
  372  * Queues a stack call which must be deferred to the global stack queue.
  373  * The call parameters are stored in entries which are allocated from the
  374  * stack queue storage pool.
  375  *
  376  * Arguments:
  377  *      cmd     stack command
  378  *      func    destination function
  379  *      token   destination layer's token
  380  *      cvp     pointer to  connection vcc
  381  *      arg1    command argument
  382  *      arg2    command argument
  383  *
  384  * Returns:
  385  *      0       call queued
  386  *      errno   call not queued - reason indicated
  387  *
  388  */
  389 int
  390 atm_stack_enq(cmd, func, token, cvp, arg1, arg2)
  391         int             cmd;
  392         void            (*func)(int, void *, intptr_t, intptr_t);
  393         void            *token;
  394         Atm_connvc      *cvp;
  395         intptr_t        arg1;
  396         intptr_t        arg2;
  397 {
  398         struct stackq_entry     *sqp;
  399         int             s = splnet();
  400 
  401         /*
  402          * Get a new queue entry for this call
  403          */
  404         sqp = uma_zalloc(atm_stackq_zone, M_NOWAIT | M_ZERO);
  405         if (sqp == NULL) {
  406                 (void) splx(s);
  407                 return (ENOMEM);
  408         }
  409 
  410         /*
  411          * Fill in new entry
  412          */
  413         sqp->sq_next = NULL;
  414         sqp->sq_cmd = cmd;
  415         sqp->sq_func = func;
  416         sqp->sq_token = token;
  417         sqp->sq_arg1 = arg1;
  418         sqp->sq_arg2 = arg2;
  419         sqp->sq_connvc = cvp;
  420 
  421         /*
  422          * Put new entry at end of queue
  423          */
  424         if (atm_stackq_head == NULL)
  425                 atm_stackq_head = sqp;
  426         else
  427                 atm_stackq_tail->sq_next = sqp;
  428         atm_stackq_tail = sqp;
  429 
  430         (void) splx(s);
  431         return (0);
  432 }
  433 
  434 
  435 /*
  436  * Drain the Stack Queue
  437  * 
  438  * Dequeues and processes entries from the global stack queue.  
  439  *
  440  * Arguments:
  441  *      none
  442  *
  443  * Returns:
  444  *      none
  445  *
  446  */
  447 void
  448 atm_stack_drain()
  449 {
  450         struct stackq_entry     *sqp, *qprev, *qnext;
  451         int             s = splnet();
  452         int             cnt;
  453 
  454         /*
  455          * Loop thru entire queue until queue is empty
  456          *      (but panic rather loop forever)
  457          */
  458         do {
  459                 cnt = 0;
  460                 qprev = NULL;
  461                 for (sqp = atm_stackq_head; sqp; ) {
  462 
  463                         /*
  464                          * Got an eligible entry, do STACK_CALL stuff
  465                          */
  466                         if (sqp->sq_cmd & STKCMD_UP) {
  467                                 if (sqp->sq_connvc->cvc_downcnt) {
  468 
  469                                         /*
  470                                          * Cant process now, skip it
  471                                          */
  472                                         qprev = sqp;
  473                                         sqp = sqp->sq_next;
  474                                         continue;
  475                                 }
  476 
  477                                 /*
  478                                  * OK, dispatch the call
  479                                  */
  480                                 sqp->sq_connvc->cvc_upcnt++;
  481                                 (*sqp->sq_func)(sqp->sq_cmd, 
  482                                                 sqp->sq_token,
  483                                                 sqp->sq_arg1,
  484                                                 sqp->sq_arg2);
  485                                 sqp->sq_connvc->cvc_upcnt--;
  486                         } else {
  487                                 if (sqp->sq_connvc->cvc_upcnt) {
  488 
  489                                         /*
  490                                          * Cant process now, skip it
  491                                          */
  492                                         qprev = sqp;
  493                                         sqp = sqp->sq_next;
  494                                         continue;
  495                                 }
  496 
  497                                 /*
  498                                  * OK, dispatch the call
  499                                  */
  500                                 sqp->sq_connvc->cvc_downcnt++;
  501                                 (*sqp->sq_func)(sqp->sq_cmd, 
  502                                                 sqp->sq_token,
  503                                                 sqp->sq_arg1,
  504                                                 sqp->sq_arg2);
  505                                 sqp->sq_connvc->cvc_downcnt--;
  506                         }
  507 
  508                         /*
  509                          * Dequeue processed entry and free it
  510                          */
  511                         cnt++;
  512                         qnext = sqp->sq_next;
  513                         if (qprev)
  514                                 qprev->sq_next = qnext;
  515                         else
  516                                 atm_stackq_head = qnext;
  517                         if (qnext == NULL)
  518                                 atm_stackq_tail = qprev;
  519                         uma_zfree(atm_stackq_zone, sqp);
  520                         sqp = qnext;
  521                 }
  522         } while (cnt > 0);
  523 
  524         /*
  525          * Make sure entire queue was drained
  526          */
  527         if (atm_stackq_head != NULL)
  528                 panic("atm_stack_drain: Queue not emptied");
  529 
  530         (void) splx(s);
  531 }
  532 
  533 
  534 /*
  535  * Process Interrupt Queue
  536  * 
  537  * Processes entries on the ATM interrupt queue.  This queue is used by
  538  * device interface drivers in order to schedule events from the driver's 
  539  * lower (interrupt) half to the driver's stack services.
  540  *
  541  * The interrupt routines must store the stack processing function to call
  542  * and a token (typically a driver/stack control block) at the front of the
  543  * queued buffer.  We assume that the function pointer and token values are 
  544  * both contained (and properly aligned) in the first buffer of the chain.
  545  * The size of these two fields is not accounted for in the packet header
  546  * length field. The packet header itself must be in the first mbuf.
  547  *
  548  * Arguments:
  549  *      none
  550  *
  551  * Returns:
  552  *      none
  553  *
  554  */
  555 static void
  556 atm_intr(struct mbuf *m)
  557 {
  558         caddr_t         cp;
  559         atm_intr_func_t func;
  560         void            *token;
  561 
  562         GIANT_REQUIRED;
  563 
  564         /*
  565          * Get function to call and token value
  566          */
  567         cp = mtod(m, caddr_t);
  568         func = *(atm_intr_func_t *)cp;
  569         cp += sizeof(func);
  570         token = *(void **)cp;
  571 
  572         m->m_len -= sizeof(func) + sizeof(token);
  573         m->m_data += sizeof(func) + sizeof(token);
  574 
  575         /*
  576          * Call processing function
  577          */
  578         (*func)(token, m);
  579 
  580         /*
  581          * Drain any deferred calls
  582          */
  583         STACK_DRAIN();
  584 }
  585 
  586 /*
  587  * Print a pdu buffer chain
  588  * 
  589  * Arguments:
  590  *      m       pointer to pdu buffer chain
  591  *      msg     pointer to message header string
  592  *
  593  * Returns:
  594  *      none
  595  *
  596  */
  597 void
  598 atm_pdu_print(const KBuffer *m, const char *msg)
  599 {
  600         const u_char    *cp;
  601         int             i;
  602         char            c = ' ';
  603 
  604         printf("%s:", msg);
  605         while (m) { 
  606                 KB_DATASTART(m, cp, const u_char *);
  607                 printf("%cbfr=%p data=%p len=%d: ",
  608                         c, m, cp, KB_LEN(m));
  609                 c = '\t';
  610                 if (atm_print_data) {
  611                         for (i = 0; i < KB_LEN(m); i++) {
  612                                 printf("%2x ", *cp++);
  613                         }
  614                         printf("<end_bfr>\n");
  615                 } else {
  616                         printf("\n");
  617                 }
  618                 m = KB_NEXT(m);
  619         }
  620 }

Cache object: 2a1f3fe4fb830555016e08186c84b95e


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