Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Apr 2012 14:59:51 GMT
From:      Andrew Atrens <andrew@atrens.ca>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/166641: mbuf/cluster leak in AP mode in 802.11 power saving support
Message-ID:  <201204041459.q34ExpRS042990@red.freebsd.org>
Resent-Message-ID: <201204041500.q34F0A4f098078@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         166641
>Category:       kern
>Synopsis:       mbuf/cluster leak in AP mode in 802.11 power saving support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Apr 04 15:00:09 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Andrew Atrens
>Release:        trunk
>Organization:
>Environment:
generic - will affect all supported platforms.
>Description:
If one has a FreeBSD AP and clients (like iPods and macbooks) that are constantly going into/out-of power saving mode, the AP will leak mbufs for fragmented packets added to the sleeping node's power saving queue.

Eventually (depending on activity, available kvm) the AP will run out of mbuf/clusters and become incommunicado.

--Andrew


>How-To-Repeat:
See above.
>Fix:
Here's my patch -

$ svn diff ieee80211_power.c
Index: ieee80211_power.c
===================================================================
--- ieee80211_power.c   (revision 233759)
+++ ieee80211_power.c   (working copy)
@@ -323,6 +323,7 @@
        struct ieee80211com *ic = ni->ni_ic;
        struct ieee80211_psq_head *qhead;
        int qlen, age;
+       struct mbuf *m0;
 
        IEEE80211_PSQ_LOCK(psq);
        if (psq->psq_len >= psq->psq_maxlen) {
@@ -336,7 +337,9 @@
                        ieee80211_dump_pkt(ni->ni_ic, mtod(m, caddr_t),
                            m->m_len, -1, -1);
 #endif
-               psq_mfree(m);
+               for (m0 = m; (m0=m) != NULL ; m = m->m_nextpkt) {
+                       psq_mfree(m0);
+               }
                return ENOSPC;
        }
        /*
@@ -386,10 +389,25 @@
        }
        KASSERT(age >= 0, ("age %d", age));
        M_AGE_SET(m, age);
        qhead->tail = m;
        qhead->len++;
        qlen = ++(psq->psq_len);
+
+       /*
+        *  We could have a fragmented frame that has multiple packets.
+        *  In that case we want to enqueue them all.
+        *
+        *  Make sure they're all tagged with the same age.
+         */
+
+       while ((m = m->m_nextpkt)) {
+               M_AGE_SET(m, age);
+               qhead->len++;
+               qlen = ++(psq->psq_len);
+               if (!m->m_nextpkt)
+                       qhead->tail = m;
+       }
+
        IEEE80211_PSQ_UNLOCK(psq);
 
        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204041459.q34ExpRS042990>