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