Explorar el Código

qcacld-3.0: Add support for GCMP in rx de-fragmentation

GCMP header and MIC are not removed for received
fragments which will result in incorrect ethertype
and presence of LLC hdr in the data when the frames
are sent to network stack.

Fix is to add support for GCMP in rx de-fragmentation
path.

Change-Id: I83ed29a766e40e32f4b712342ebd40d08a2c65e0
CRs-Fixed: 2942099
Yeshwanth Sriram Guntuka hace 4 años
padre
commit
e4322f1e96
Se han modificado 1 ficheros con 97 adiciones y 0 borrados
  1. 97 0
      core/dp/txrx/ol_rx_defrag.c

+ 97 - 0
core/dp/txrx/ol_rx_defrag.c

@@ -95,6 +95,13 @@ const struct ol_rx_defrag_cipher f_wep = {
 	0,
 };
 
+const struct ol_rx_defrag_cipher f_gcmp = {
+	"AES-GCMP",
+	WLAN_IEEE80211_GCMP_HEADERLEN,
+	WLAN_IEEE80211_GCMP_MICLEN,
+	WLAN_IEEE80211_GCMP_MICLEN,
+};
+
 #if defined(CONFIG_HL_SUPPORT)
 
 /**
@@ -663,6 +670,79 @@ void ol_rx_defrag_waitlist_flush(struct ol_txrx_pdev_t *pdev)
 	}
 }
 
+/**
+ * ol_rx_frag_gcmp_decap() - Remove GCMP header from fragment
+ * @pdev - data path pdev handle
+ * @nbuf - network buffer
+ * @hdrlen - MAC header len
+ *
+ * Return: OL_RX_DEFRAG_OK on success else failure code
+ */
+static int
+ol_rx_frag_gcmp_decap(ol_txrx_pdev_handle pdev,
+		      qdf_nbuf_t nbuf, uint16_t hdrlen)
+{
+	uint8_t *ivp, *orig_hdr;
+	void *rx_desc_old_position = NULL;
+	void *ind_old_position = NULL;
+	int rx_desc_len = 0;
+
+	ol_rx_frag_desc_adjust(pdev,
+			       nbuf,
+			       &rx_desc_old_position,
+			       &ind_old_position, &rx_desc_len);
+
+	orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len);
+	ivp = orig_hdr + hdrlen;
+	if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
+		return OL_RX_DEFRAG_ERR;
+
+	qdf_mem_move(orig_hdr + f_gcmp.ic_header, orig_hdr, hdrlen);
+	ol_rx_frag_restructure(
+			pdev,
+			nbuf,
+			rx_desc_old_position,
+			ind_old_position,
+			&f_gcmp,
+			rx_desc_len);
+	qdf_nbuf_pull_head(nbuf, f_gcmp.ic_header);
+
+	return OL_RX_DEFRAG_OK;
+}
+
+/**
+ * ol_rx_frag_gcmp_demic() - Remove MIC info from GCMP fragment
+ * @pdev - data path pdev handle
+ * @nbuf - network buffer
+ * @hdrlen - MAC header len
+ *
+ * Return: OL_RX_DEFRAG_OK on success else failure code
+ */
+static int
+ol_rx_frag_gcmp_demic(ol_txrx_pdev_handle pdev,
+		      qdf_nbuf_t wbuf, uint16_t hdrlen)
+{
+	uint8_t *ivp, *orig_hdr;
+	void *rx_desc_old_position = NULL;
+	void *ind_old_position = NULL;
+	int rx_desc_len = 0;
+
+	ol_rx_frag_desc_adjust(pdev,
+			       wbuf,
+			       &rx_desc_old_position,
+			       &ind_old_position, &rx_desc_len);
+
+	orig_hdr = (uint8_t *)(qdf_nbuf_data(wbuf) + rx_desc_len);
+
+	ivp = orig_hdr + hdrlen;
+	if (!(ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV))
+		return OL_RX_DEFRAG_ERR;
+
+	qdf_nbuf_trim_tail(wbuf, f_gcmp.ic_trailer);
+
+	return OL_RX_DEFRAG_OK;
+}
+
 /*
  * Handling security checking and processing fragments
  */
@@ -780,7 +860,24 @@ ol_rx_defrag(ol_txrx_pdev_handle pdev,
 			cur = tmp_next;
 		}
 		break;
+	case htt_sec_type_aes_gcmp:
+	case htt_sec_type_aes_gcmp_256:
+		while (cur) {
+			tmp_next = qdf_nbuf_next(cur);
+			if (!ol_rx_frag_gcmp_demic(pdev, cur, hdr_space)) {
+				ol_rx_frames_free(htt_pdev, frag_list);
+				ol_txrx_err("GCMP demic failed");
+				return;
+			}
+			if (!ol_rx_frag_gcmp_decap(pdev, cur, hdr_space)) {
+				ol_rx_frames_free(htt_pdev, frag_list);
+				ol_txrx_err("GCMP decap failed");
+				return;
+			}
+			cur = tmp_next;
+		}
 
+		break;
 	default:
 		break;
 	}