On Sat, Dec 12, 2015 at 03:08:00PM +0100, Mark Kettenis wrote:
> > @@ -1072,6 +1079,10 @@ ieee80211_amsdu_decap(struct ieee80211co
> >             }
> >             ieee80211_deliver_data(ic, m, ni);
> >  
> > +           if (n->m_len == 0) {
> > +                   m_freem(n);
> > +                   break;
> > +           }
> 
> Can this really happen?  I would expect that m_split() would have
> returned NULL if we'd tried to split the packet in a way that there is
> nothing left.  Not sure if that can happen though, but ouldn't it be a
> bug if it did?

It's definitely happening during my testing.
An empty mbuf is the result of a successful split with an empty remainder
(note the second to last line):

ieee80211_amsdu_decap: A-MSDU mbuf 0xffffff0009378900 m_len=3072 
m_pkthdr.len=3072 hdrlen=26
ieee80211_amsdu_decap: 0 mbuf 0xffffff0009378900 m_len=3046 m_pkthdr.len=3046
ieee80211_amsdu_decap: subframe DA=34:13:e8:29:7f:61 SA=34:13:e8:29:7f:61 
len=1508
ieee80211_amsdu_decap: m_split returned 0xffffff00cbb43900 m_len=1524 
m_pkthdr.len=1524
ieee80211_amsdu_decap: delivering mbuf 0xffffff0009378900 m_len=1514 
m_pkthdr.len=1514
ieee80211_amsdu_decap: mbuf 0xffffff00cbb43900 pad=2
ieee80211_amsdu_decap: 1 mbuf 0xffffff00cbb43900 m_len=1522 m_pkthdr.len=1522
ieee80211_amsdu_decap: subframe DA=34:13:e8:29:7f:61 SA=34:13:e8:29:7f:61 
len=1508
ieee80211_amsdu_decap: m_split returned 0xffffff00cbb43a00 m_len=0 
m_pkthdr.len=0
ieee80211_amsdu_decap: delivering mbuf 0xffffff00cbb43900 m_len=1514 
m_pkthdr.len=1514

This should be the if (remain == 0) code path in m_split.
I could add more printfs in there to show what happens.
I believe a NULL return would indicate an error.

To get above values printed I used the following debug printfs:

Index: ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.145
diff -u -p -r1.145 ieee80211_input.c
--- ieee80211_input.c   12 Dec 2015 13:56:10 -0000      1.145
+++ ieee80211_input.c   12 Dec 2015 14:30:43 -0000
@@ -1021,15 +1021,22 @@ ieee80211_amsdu_decap(struct ieee80211co
        struct ether_header *eh;
        struct llc *llc;
        int len, pad;
+       int i = 0;
+
+       printf("%s: A-MSDU mbuf %p m_len=%d m_pkthdr.len=%d hdrlen=%d\n", 
__func__,
+           m, m->m_len, m->m_pkthdr.len, hdrlen);
 
        /* strip 802.11 header */
        m_adj(m, hdrlen);
 
        for (;;) {
+               printf("%s: %d mbuf %p m_len=%d m_pkthdr.len=%d\n", __func__,
+                   i++, m, m->m_len, m->m_pkthdr.len);
                /* process an A-MSDU subframe */
                if (m->m_len < ETHER_HDR_LEN + LLC_SNAPFRAMELEN) {
                        m = m_pullup(m, ETHER_HDR_LEN + LLC_SNAPFRAMELEN);
                        if (m == NULL) {
+                               printf("%s: m_pullup failed\n", __func__);
                                ic->ic_stats.is_rx_decap++;
                                break;
                        }
@@ -1037,8 +1044,11 @@ ieee80211_amsdu_decap(struct ieee80211co
                eh = mtod(m, struct ether_header *);
                /* examine 802.3 header */
                len = ntohs(eh->ether_type);
+               printf("%s: subframe DA=%s SA=%s len=%d\n", __func__,
+                   ether_sprintf(eh->ether_dhost),
+                   ether_sprintf(eh->ether_shost), len);
                if (len < LLC_SNAPFRAMELEN) {
-                       DPRINTF(("A-MSDU subframe too short (%d)\n", len));
+                       printf("A-MSDU subframe too short (%d)\n", len);
                        /* stop processing A-MSDU subframes */
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
@@ -1063,7 +1073,7 @@ ieee80211_amsdu_decap(struct ieee80211co
                len += ETHER_HDR_LEN;
                if (len > m->m_pkthdr.len) {
                        /* stop processing A-MSDU subframes */
-                       DPRINTF(("A-MSDU subframe too long (%d)\n", len));
+                       printf("A-MSDU subframe too long (%d)\n", len);
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
                        break;
@@ -1073,10 +1083,18 @@ ieee80211_amsdu_decap(struct ieee80211co
                n = m_split(m, len, M_NOWAIT);
                if (n == NULL) {
                        /* stop processing A-MSDU subframes */
+                       printf("%s: m_split failed mbuf %p m_len=%d "
+                           "m_pkthdr.len=%d\n", __func__, m, m->m_len,
+                       m->m_pkthdr.len);
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
                        break;
                }
+               printf("%s: m_split returned %p m_len=%d m_pkthdr.len=%d\n",
+                   __func__, n, n->m_len, n->m_pkthdr.len);
+
+               printf("%s: delivering mbuf %p m_len=%d m_pkthdr.len=%d\n",
+                   __func__, m, m->m_len, m->m_pkthdr.len);
                ieee80211_deliver_data(ic, m, ni);
 
                if (n->m_len == 0) {
@@ -1087,6 +1105,7 @@ ieee80211_amsdu_decap(struct ieee80211co
                /* remove padding */
                pad = ((len + 3) & ~3) - len;
                m_adj(m, pad);
+               printf("%s: mbuf %p removed pad=%d bytes\n", __func__, m, pad);
        }
 }
 #endif /* !IEEE80211_NO_HT */


Reply via email to