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 */