[driver][wlan] Hotfix for Ralink zero-padding for QoSData data frame

NET-297

Change-Id: I883118a7d34e25cce145f15f875872264238cabf
diff --git a/drivers/wlan/wlan/dispatcher.cpp b/drivers/wlan/wlan/dispatcher.cpp
index 4a466c8..748929e 100644
--- a/drivers/wlan/wlan/dispatcher.cpp
+++ b/drivers/wlan/wlan/dispatcher.cpp
@@ -189,7 +189,31 @@
         return ZX_OK;
     }
 
-    auto llc = packet->field<LlcHeader>(hdr->len());
+    auto llc_offset = hdr->len();
+    {  // TODO(porce): Factor out as a function.
+
+        // Ralink aligns the Mac frame header in 4 bytes,
+        // before passing it to the device driver.
+        // The rx frame's rx_descriptor has l2pad boolean flag
+        // to indicate if the frame was zero-padded.
+        // In case of data frame with subtype kQosData(8),
+        // two bytes of QoS Control field is appended
+        // after the Addr3, and BEFORE LLC header.
+        // This offset calculation should compensate that
+        // before the frame may be passed to next level.
+
+        // TODO(porce): Replace the conditional by rxinfo's upcoming field: l2pad
+        // Alignment size is 4 bytes. This is the case for Ralink implementation.
+        // Not necessarilly generally applicable to all chipsets.
+        constexpr size_t l2padding_align = 4;  // bytes
+        if ((llc_offset % l2padding_align) != 0) { llc_offset += llc_offset % l2padding_align; }
+
+        // Alternative implementation:
+        // constexpr size_t l2padding_bytes = 2;
+        // if (hdr->fc.subtype() == kQosdata) { llc_offset += l2padding_bytes; }
+    }
+
+    auto llc = packet->field<LlcHeader>(llc_offset);
     if (llc == nullptr) {
         errorf("short data packet len=%zu\n", packet->len());
         return ZX_ERR_IO;
@@ -198,7 +222,7 @@
         errorf("short LLC packet len=%zu\n", packet->len());
         return ZX_ERR_IO;
     }
-    size_t llc_len = packet->len() - hdr->len();
+    size_t llc_len = packet->len() - llc_offset;
     auto frame = DataFrame<LlcHeader>(hdr, llc, llc_len);
     return mlme_->HandleFrame(frame, *rxinfo);
 }
diff --git a/drivers/wlan/wlan/station.cpp b/drivers/wlan/wlan/station.cpp
index 23a0497..76c7292 100644
--- a/drivers/wlan/wlan/station.cpp
+++ b/drivers/wlan/wlan/station.cpp
@@ -607,7 +607,6 @@
 zx_status_t Station::HandleDataFrame(const DataFrame<LlcHeader>& frame,
                                      const wlan_rx_info_t& rxinfo) {
     debugfn();
-    ZX_DEBUG_ASSERT(frame.hdr->fc.subtype() == 0);
     ZX_DEBUG_ASSERT(bssid() != nullptr);
     ZX_DEBUG_ASSERT(frame.hdr->addr2 == common::MacAddr(bss_->bssid.data()));
     ZX_DEBUG_ASSERT(state_ == WlanState::kAssociated);