With A-MSDUs enabled in -current people are seeing a lot of

        input packet decapsulations failed

events in netstat -W iwm0.

This fixes the issue on iwm 8265 for me. There are between 6 and 8 bytes of
trailing data in the A-MSDU frame buffer. This results in a decap failure
being counted when m_pullup() fails to fetch ETHER_HDR_LEN + LLC_SNAPFRAMELEN
bytes.

I suppose such bytes are padding left by the hardware, most likely due to
decryption. It should be safe to ignore these. A TCP stream that uses
A-MSDUs looks clean, so we're not losing any packets. This problem is
just a cosmetic one.

ok?

iwm(4) 9260+ and iwx(4) have another issue because these devices actually
decapsulate A-MSDUs in hardware and our code doesn't handle that yet.
I will send a separate patch for this soon.

diff b0e5533ef47f577f6c3be1bfdbb89151a76d3add /usr/src
blob - 2c9ee3ab48a212ce9730860568ca59d17d3d4636
file + sys/net80211/ieee80211_input.c
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -1148,14 +1148,13 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
        /* strip 802.11 header */
        m_adj(m, hdrlen);
 
-       for (;;) {
+       while (m->m_pkthdr.len >= ETHER_HDR_LEN + LLC_SNAPFRAMELEN) {
                /* 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) {
-                               ic->ic_stats.is_rx_decap++;
-                               break;
-                       }
+               len = m->m_pkthdr.len;
+               m = m_pullup(m, ETHER_HDR_LEN + LLC_SNAPFRAMELEN);
+               if (m == NULL) {
+                       ic->ic_stats.is_rx_decap++;
+                       break;
                }
                eh = mtod(m, struct ether_header *);
                /* examine 802.3 header */
@@ -1202,15 +1201,13 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
                }
                ieee80211_enqueue_data(ic, m, ni, mcast, ml);
 
-               if (n->m_pkthdr.len == 0) {
-                       m_freem(n);
-                       break;
-               }
                m = n;
                /* remove padding */
                pad = ((len + 3) & ~3) - len;
                m_adj(m, pad);
        }
+
+       m_freem(m);
 }
 
 /*

Reply via email to