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/net80211/ieee80211_ageq.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009 Sam Leffler, Errno Consulting
    5  * 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  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * IEEE 802.11 age queue support.
   33  */
   34 #include "opt_wlan.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h> 
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 
   41 #include <sys/socket.h>
   42 
   43 #include <net/if.h>
   44 #include <net/if_var.h>
   45 #include <net/if_media.h>
   46 #include <net/ethernet.h>
   47 
   48 #include <net80211/ieee80211_var.h>
   49 
   50 /*
   51  * Initialize an ageq.
   52  */
   53 void
   54 ieee80211_ageq_init(struct ieee80211_ageq *aq, int maxlen, const char *name)
   55 {
   56         memset(aq, 0, sizeof(*aq));
   57         aq->aq_maxlen = maxlen;
   58         IEEE80211_AGEQ_INIT(aq, name);          /* OS-dependent setup */
   59 }
   60 
   61 /*
   62  * Cleanup an ageq initialized with ieee80211_ageq_init.  Note
   63  * the queue is assumed empty; this can be done with ieee80211_ageq_drain.
   64  */
   65 void
   66 ieee80211_ageq_cleanup(struct ieee80211_ageq *aq)
   67 {
   68         KASSERT(aq->aq_len == 0, ("%d frames on ageq", aq->aq_len));
   69         IEEE80211_AGEQ_DESTROY(aq);             /* OS-dependent cleanup */
   70 }
   71 
   72 /*
   73  * Free an mbuf according to ageq rules: if marked as holding
   74  * and 802.11 frame then also reclaim a node reference from
   75  * the packet header; this handles packets q'd in the tx path.
   76  */
   77 static void
   78 ageq_mfree(struct mbuf *m)
   79 {
   80         if (m->m_flags & M_ENCAP) {
   81                 struct ieee80211_node *ni = (void *) m->m_pkthdr.rcvif;
   82                 ieee80211_free_node(ni);
   83         }
   84         m->m_nextpkt = NULL;
   85         m_freem(m);
   86 }
   87 
   88 /*
   89  * Free a list of mbufs using ageq rules (see above).
   90  */
   91 void
   92 ieee80211_ageq_mfree(struct mbuf *m)
   93 {
   94         struct mbuf *next;
   95 
   96         for (; m != NULL; m = next) {
   97                 next = m->m_nextpkt;
   98                 ageq_mfree(m);
   99         }
  100 }
  101 
  102 /*
  103  * Append an mbuf to the ageq and mark it with the specified max age
  104  * If the frame is not removed before the age (in seconds) expires
  105  * then it is reclaimed (along with any node reference).
  106  */
  107 int
  108 ieee80211_ageq_append(struct ieee80211_ageq *aq, struct mbuf *m, int age)
  109 {
  110         IEEE80211_AGEQ_LOCK(aq);
  111         if (__predict_true(aq->aq_len < aq->aq_maxlen)) {
  112                 if (aq->aq_tail == NULL) {
  113                         aq->aq_head = m;
  114                 } else {
  115                         aq->aq_tail->m_nextpkt = m;
  116                         age -= M_AGE_GET(aq->aq_head);
  117                 }
  118                 KASSERT(age >= 0, ("age %d", age));
  119                 M_AGE_SET(m, age);
  120                 m->m_nextpkt = NULL;
  121                 aq->aq_tail = m;
  122                 aq->aq_len++;
  123                 IEEE80211_AGEQ_UNLOCK(aq);
  124                 return 0;
  125         } else {
  126                 /*
  127                  * No space, drop and cleanup references.
  128                  */
  129                 aq->aq_drops++;
  130                 IEEE80211_AGEQ_UNLOCK(aq);
  131                 /* XXX tail drop? */
  132                 ageq_mfree(m);
  133                 return ENOSPC;
  134         }
  135 }
  136 
  137 /*
  138  * Drain/reclaim all frames from an ageq.
  139  */
  140 void
  141 ieee80211_ageq_drain(struct ieee80211_ageq *aq)
  142 {
  143         ieee80211_ageq_mfree(ieee80211_ageq_remove(aq, NULL));
  144 }
  145 
  146 /*
  147  * Drain/reclaim frames associated with a specific node from an ageq.
  148  */
  149 void
  150 ieee80211_ageq_drain_node(struct ieee80211_ageq *aq,
  151         struct ieee80211_node *ni)
  152 {
  153         ieee80211_ageq_mfree(ieee80211_ageq_remove(aq, ni));
  154 }
  155 
  156 /*
  157  * Age frames on the age queue.  Ages are stored as time
  158  * deltas (in seconds) relative to the head so we can check
  159  * and/or adjust only the head of the list.  If a frame's age
  160  * exceeds the time quanta then remove it.  The list of removed
  161  * frames is returned to the caller joined by m_nextpkt.
  162  */
  163 struct mbuf *
  164 ieee80211_ageq_age(struct ieee80211_ageq *aq, int quanta)
  165 {
  166         struct mbuf *head, **phead;
  167         struct mbuf *m;
  168 
  169         phead = &head;
  170         if (aq->aq_len != 0) {
  171                 IEEE80211_AGEQ_LOCK(aq);
  172                 while ((m = aq->aq_head) != NULL && M_AGE_GET(m) < quanta) {
  173                         if ((aq->aq_head = m->m_nextpkt) == NULL)
  174                                 aq->aq_tail = NULL;
  175                         KASSERT(aq->aq_len > 0, ("aq len %d", aq->aq_len));
  176                         aq->aq_len--;
  177                         /* add to private list for return */
  178                         *phead = m;
  179                         phead = &m->m_nextpkt;
  180                 }
  181                 if (m != NULL)
  182                         M_AGE_SUB(m, quanta);
  183                 IEEE80211_AGEQ_UNLOCK(aq);
  184         }
  185         *phead = NULL;
  186         return head;
  187 }
  188 
  189 /*
  190  * Remove all frames matching the specified node identifier
  191  * (NULL matches all).  Frames are returned as a list joined
  192  * by m_nextpkt.
  193  */
  194 struct mbuf *
  195 ieee80211_ageq_remove(struct ieee80211_ageq *aq,
  196         struct ieee80211_node *match)
  197 {
  198         struct mbuf *m, **prev, *ohead;
  199         struct mbuf *head, **phead;
  200 
  201         IEEE80211_AGEQ_LOCK(aq);
  202         ohead = aq->aq_head;
  203         prev = &aq->aq_head;
  204         phead = &head;
  205         while ((m = *prev) != NULL) {
  206                 if (match != NULL && m->m_pkthdr.rcvif != (void *) match) {
  207                         prev = &m->m_nextpkt;
  208                         continue;
  209                 }
  210                 /*
  211                  * Adjust q length.
  212                  */
  213                 KASSERT(aq->aq_len > 0, ("aq len %d", aq->aq_len));
  214                 aq->aq_len--;
  215                 /*
  216                  * Remove from forward list; tail pointer is harder.
  217                  */
  218                 if (aq->aq_tail == m) {
  219                         KASSERT(m->m_nextpkt == NULL, ("not last"));
  220                         if (aq->aq_head == m) {         /* list empty */
  221                                 KASSERT(aq->aq_len == 0,
  222                                     ("not empty, len %d", aq->aq_len));
  223                                 aq->aq_tail = NULL;
  224                         } else {                        /* must be one before */
  225                                 aq->aq_tail = (struct mbuf *)((uintptr_t)prev -
  226                                     offsetof(struct mbuf, m_nextpkt));
  227                         }
  228                 }
  229                 *prev = m->m_nextpkt;
  230 
  231                 /* add to private list for return */
  232                 *phead = m;
  233                 phead = &m->m_nextpkt;
  234         }
  235         if (head == ohead && aq->aq_head != NULL)       /* correct age */
  236                 M_AGE_SET(aq->aq_head, M_AGE_GET(head));
  237         IEEE80211_AGEQ_UNLOCK(aq);
  238 
  239         *phead = NULL;
  240         return head;
  241 }

Cache object: 6617e506df271ee412b20efa668340c5


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