Преглед изворни кода

qcacld-3.0: Parse tx packets only once in tx datapath

Classify tx packets at one place and store packet type in
skb cb structure to avoid multiple check to determine
packet type at various layers.

Change-Id: Id2ea9b08bdcbc62b1d96d983d19bcf71becc9c42
CRs-Fixed: 1022454
Nirav Shah пре 8 година
родитељ
комит
5e74bb81d5

+ 4 - 2
core/dp/txrx/ol_tx.c

@@ -1215,8 +1215,10 @@ struct ol_tx_desc_t *ol_tx_hl_desc_alloc(struct ol_txrx_pdev_t *pdev,
 			TXRX_HL_TX_DESC_HI_PRIO_RESERVED) {
 		tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
 	} else if (qdf_nbuf_is_ipv4_pkt(msdu) == true) {
-		if ((qdf_nbuf_is_ipv4_dhcp_pkt(msdu) == true) ||
-		    (qdf_nbuf_is_ipv4_eapol_pkt(msdu) == true)) {
+		if ((QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
+				QDF_NBUF_CB_PACKET_TYPE_DHCP) ||
+		    (QDF_NBUF_CB_GET_PACKET_TYPE(msdu) ==
+			QDF_NBUF_CB_PACKET_TYPE_EAPOL)) {
 			tx_desc = ol_tx_desc_hl(pdev, vdev, msdu, msdu_info);
 			TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
 				   "Provided tx descriptor from reserve pool for DHCP/EAPOL\n");

+ 4 - 2
core/dp/txrx/ol_tx_classify.c

@@ -428,7 +428,8 @@ ol_tx_classify(
 				OL_TXRX_PEER_SECURITY_MULTICAST].sec_type
 						!= htt_sec_type_wapi) &&
 				   (qdf_nbuf_is_ipv4_pkt(tx_nbuf) == true)) {
-				if (true == qdf_nbuf_is_ipv4_dhcp_pkt(
+				if (QDF_NBUF_CB_PACKET_TYPE_DHCP ==
+						QDF_NBUF_CB_GET_PACKET_TYPE(
 								tx_nbuf)) {
 					/* DHCP frame to go with
 					 * voice priority
@@ -561,7 +562,8 @@ ol_tx_classify(
 				OL_TXRX_PEER_SECURITY_UNICAST].sec_type
 					!= htt_sec_type_wapi) &&
 			   (qdf_nbuf_is_ipv4_pkt(tx_nbuf) == true)) {
-			if (true == qdf_nbuf_is_ipv4_dhcp_pkt(tx_nbuf))
+			if (QDF_NBUF_CB_PACKET_TYPE_DHCP ==
+					QDF_NBUF_CB_GET_PACKET_TYPE(tx_nbuf))
 				/* DHCP frame to go with voice priority */
 				tid = TX_DHCP_TID;
 		}

+ 10 - 0
core/hdd/inc/wlan_hdd_tx_rx.h

@@ -114,4 +114,14 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
 		enum netif_action_type action, enum netif_reason_type reason);
 int hdd_set_mon_rx_cb(struct net_device *dev);
 void hdd_send_rps_ind(hdd_adapter_t *adapter);
+void wlan_hdd_classify_pkt(struct sk_buff *skb);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+void hdd_event_eapol_log(struct sk_buff *skb, enum qdf_proto_dir dir);
+#else
+static inline
+void hdd_event_eapol_log(struct sk_buff *skb, enum qdf_proto_dir dir)
+{}
+#endif
+
 #endif /* end #if !defined(WLAN_HDD_TX_RX_H) */

+ 6 - 4
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -251,10 +251,12 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop_pkt;
 	}
 
+	wlan_hdd_classify_pkt(skb);
+
 	pDestMacAddress = (struct qdf_mac_addr *) skb->data;
 
-	if (qdf_is_macaddr_broadcast(pDestMacAddress) ||
-	    qdf_is_macaddr_group(pDestMacAddress)) {
+	if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
+	    QDF_NBUF_CB_GET_IS_MCAST(skb)) {
 		/* The BC/MC station ID is assigned during BSS
 		 * starting phase.  SAP will return the station ID
 		 * used for BC/MC traffic.
@@ -324,8 +326,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	pAdapter->stats.tx_bytes += skb->len;
 	++pAdapter->stats.tx_packets;
 
-	/* Zero out skb's context buffer for the driver to use */
-	qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
+	hdd_event_eapol_log(skb, QDF_TX);
 	qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
 	QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
 	QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
@@ -593,6 +594,7 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
 	++pAdapter->stats.rx_packets;
 	pAdapter->stats.rx_bytes += skb->len;
 
+	hdd_event_eapol_log(skb, QDF_RX);
 	DPTRACE(qdf_dp_trace(rxBuf,
 		QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
 		qdf_nbuf_data_addr(rxBuf),

+ 81 - 32
core/hdd/src/wlan_hdd_tx_rx.c

@@ -265,36 +265,80 @@ void hdd_get_tx_resource(hdd_adapter_t *adapter,
 
 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
 
-
 /**
- * wlan_hdd_is_eapol_or_wai() - Check if frame is EAPOL or WAPI
- * @skb:    skb data
- *
- * This function checks if the frame is EAPOL or WAPI.
- * single routine call will check for both types, thus avoiding
- * data path performance penalty.
- *
- * Return: true (1) if packet is EAPOL or WAPI
+ * qdf_event_eapol_log() - send event to wlan diag
+ * @skb: skb ptr
+ * @dir: direction
+ * @eapol_key_info: eapol key info
  *
+ * Return: None
  */
-static bool wlan_hdd_is_eapol_or_wai(struct sk_buff *skb)
+void hdd_event_eapol_log(struct sk_buff *skb, enum qdf_proto_dir dir)
 {
-	uint16_t ether_type;
+	int16_t eapol_key_info;
 
-	if (!skb) {
-		hdd_err(FL("skb is NULL"));
-		return false;
-	}
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_event_wlan_eapol);
+
+	if ((dir == QDF_TX &&
+		(QDF_NBUF_CB_PACKET_TYPE_EAPOL !=
+		 QDF_NBUF_CB_GET_PACKET_TYPE(skb))))
+		return;
+	else if (!qdf_nbuf_is_ipv4_eapol_pkt(skb))
+		return;
+
+	eapol_key_info = (uint16_t)(*(uint16_t *)
+				(skb->data + EAPOL_KEY_INFO_OFFSET));
+
+	wlan_diag_event.event_sub_type =
+		(dir == QDF_TX ?
+		 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED :
+		 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
+	wlan_diag_event.eapol_packet_type = (uint8_t)(*(uint8_t *)
+				(skb->data + EAPOL_PACKET_TYPE_OFFSET));
+	wlan_diag_event.eapol_key_info = eapol_key_info;
+	wlan_diag_event.eapol_rate = 0;
+	qdf_mem_copy(wlan_diag_event.dest_addr,
+			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
+			sizeof(wlan_diag_event.dest_addr));
+	qdf_mem_copy(wlan_diag_event.src_addr,
+			(skb->data + QDF_NBUF_SRC_MAC_OFFSET),
+			sizeof(wlan_diag_event.src_addr));
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
+}
 
-	ether_type = (uint16_t)(*(uint16_t *)
-			(skb->data + HDD_ETHERTYPE_802_1_X_FRAME_OFFSET));
 
-	if (ether_type == QDF_SWAP_U16(HDD_ETHERTYPE_802_1_X) ||
-	    ether_type == QDF_SWAP_U16(HDD_ETHERTYPE_WAI))
-		return true;
+/**
+ * wlan_hdd_classify_pkt() - classify packet
+ * @skb - sk buff
+ *
+ * Return: none
+ */
+void wlan_hdd_classify_pkt(struct sk_buff *skb)
+{
+	struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+	qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
+
+	/* check destination mac address is broadcast/multicast */
+	if (is_broadcast_ether_addr((uint8_t *)eh))
+		QDF_NBUF_CB_GET_IS_BCAST(skb) = true;
+	else if (is_multicast_ether_addr((uint8_t *)eh))
+		QDF_NBUF_CB_GET_IS_MCAST(skb) = true;
+
+	if (qdf_nbuf_is_ipv4_arp_pkt(skb))
+		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
+			QDF_NBUF_CB_PACKET_TYPE_ARP;
+	else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb))
+		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
+			QDF_NBUF_CB_PACKET_TYPE_DHCP;
+	else if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
+		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
+			QDF_NBUF_CB_PACKET_TYPE_EAPOL;
+	else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
+		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
+			QDF_NBUF_CB_PACKET_TYPE_WAPI;
 
-	/* No error msg handled since this will happen often */
-	return false;
 }
 
 /**
@@ -309,15 +353,17 @@ static bool wlan_hdd_is_eapol_or_wai(struct sk_buff *skb)
  * Returns: None
  */
 static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
-			struct qdf_mac_addr *dst_addr, uint8_t *station_id)
+			struct sk_buff *skb, uint8_t *station_id)
 {
 	bool mcbc_addr = false;
 	hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+	struct qdf_mac_addr *dst_addr = NULL;
 
+	dst_addr = (struct qdf_mac_addr *)skb->data;
 	hdd_get_peer_sta_id(sta_ctx, dst_addr, station_id);
 	if (*station_id == HDD_WLAN_INVALID_STA_ID) {
-		if (qdf_is_macaddr_broadcast(dst_addr) ||
-				qdf_is_macaddr_group(dst_addr)) {
+		if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
+				QDF_NBUF_CB_GET_IS_MCAST(skb)) {
 			hdd_info("Received MC/BC packet for transmission");
 			mcbc_addr = true;
 		}
@@ -362,9 +408,8 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	sme_QosWmmUpType up;
 	hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	bool granted;
-	uint8_t STAId = WLAN_MAX_STA_COUNT;
+	uint8_t STAId;
 	hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
-	struct qdf_mac_addr *pDestMacAddress = NULL;
 #ifdef QCA_PKT_PROTO_TRACE
 	uint8_t proto_type = 0;
 #endif /* QCA_PKT_PROTO_TRACE */
@@ -384,10 +429,11 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop_pkt;
 	}
 
-	pDestMacAddress = (struct qdf_mac_addr *)skb->data;
+	wlan_hdd_classify_pkt(skb);
+
 	STAId = HDD_WLAN_INVALID_STA_ID;
 
-	hdd_get_transmit_sta_id(pAdapter, pDestMacAddress, &STAId);
+	hdd_get_transmit_sta_id(pAdapter, skb, &STAId);
 	if (STAId >= WLAN_MAX_STA_COUNT) {
 		hddLog(LOGE, "Invalid station id, transmit operation suspended");
 		goto drop_pkt;
@@ -436,7 +482,10 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].
 			wmmAcAccessAllowed)) ||
 		((pHddStaCtx->conn_info.uIsAuthenticated == false) &&
-		 wlan_hdd_is_eapol_or_wai(skb))) {
+		 (QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
+			QDF_NBUF_CB_GET_PACKET_TYPE(skb) ||
+		  QDF_NBUF_CB_PACKET_TYPE_WAPI ==
+			QDF_NBUF_CB_GET_PACKET_TYPE(skb)))) {
 		granted = true;
 	} else {
 		status = hdd_wmm_acquire_access(pAdapter, ac, &granted);
@@ -500,8 +549,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	++pAdapter->stats.tx_packets;
 
-	/* Zero out skb's context buffer for the driver to use */
-	qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
+	hdd_event_eapol_log(skb, QDF_TX);
 	qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX);
 	QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
 	QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD);
@@ -864,6 +912,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
 		return QDF_STATUS_SUCCESS;
 	}
 
+	hdd_event_eapol_log(skb, QDF_RX);
 	DPTRACE(qdf_dp_trace(rxBuf,
 		QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
 		qdf_nbuf_data_addr(rxBuf),