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

qcacld-3.0: use nl interface for eapol

For latest chipsets use nl interface for eapol handshake for all
device modes.

Change-Id: I5f5b5f2b34687ec90c93f406b39196fc18c31375
CRs-Fixed: 3021188
Arun Kumar Khandavalli пре 3 година
родитељ
комит
7876d018c4

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

@@ -82,6 +82,12 @@ struct hdd_context;
 #define SME_QOS_UAPSD_CFG_VI_CHANGED_MASK     0xF4
 #define SME_QOS_UAPSD_CFG_VO_CHANGED_MASK     0xF8
 
+#ifdef WLAN_FEATURE_11BE_MLO
+#define SEND_EAPOL_OVER_NL true
+#else
+#define SEND_EAPOL_OVER_NL  false
+#endif
+
 netdev_tx_t hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /**

+ 77 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -17237,6 +17237,22 @@ wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
 }
 #endif
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
+{
+	wiphy_ext_feature_set(wiphy,
+			      NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
+	wiphy_ext_feature_set(wiphy,
+		       NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS);
+	wiphy_ext_feature_set(wiphy,
+			      NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
+}
+#else
+static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
+{
+}
+#endif
+
 /*
  * FUNCTION: wlan_hdd_cfg80211_init
  * This function is called by hdd_wlan_startup()
@@ -17376,6 +17392,8 @@ int wlan_hdd_cfg80211_init(struct device *dev,
 
 	wlan_hdd_set_nan_supported_bands(wiphy);
 
+	wlan_hdd_update_eapol_over_nl80211_flags(wiphy);
+
 	hdd_exit();
 	return 0;
 
@@ -22777,6 +22795,62 @@ static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
 	return errno;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static int __wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
+					       struct net_device *dev,
+					       const u8 *buf,
+					       size_t len, const u8 *dest,
+						__be16 proto, bool unencrypted)
+{
+	qdf_nbuf_t nbuf;
+	struct ethhdr *ehdr;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+	nbuf = qdf_nbuf_alloc(NULL, (len + sizeof(struct ethhdr)), 0, 4, false);
+	if (!nbuf)
+		return -ENOMEM;
+	qdf_nbuf_reserve(nbuf, sizeof(struct ethhdr));
+	skb_put_data(nbuf, buf, len);
+	ehdr = skb_push(nbuf, sizeof(struct ethhdr));
+	qdf_mem_copy(ehdr->h_dest, dest, ETH_ALEN);
+	qdf_mem_copy(ehdr->h_source, adapter->mac_addr.bytes, ETH_ALEN);
+	ehdr->h_proto = proto;
+
+	nbuf->dev = dev;
+	nbuf->protocol = htons(ETH_P_PAE);
+	skb_reset_network_header(nbuf);
+	skb_reset_mac_header(nbuf);
+	hdd_select_queue(dev, nbuf, NULL, NULL);
+
+	netif_tx_lock(dev);
+	dev->netdev_ops->ndo_start_xmit(nbuf, dev);
+	netif_tx_unlock(dev);
+
+	return 0;
+}
+
+static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     const u8 *buf,
+					     size_t len, const u8 *dest,
+					     __be16 proto, bool unencrypted)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len, dest,
+						    proto, unencrypted);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
+#endif
+
 /**
  * struct cfg80211_ops - cfg80211_ops
  *
@@ -22926,4 +23000,7 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
 	.get_antenna = wlan_hdd_cfg80211_get_chainmask,
 	.get_channel = wlan_hdd_cfg80211_get_channel,
 	.set_bitrate_mask = wlan_hdd_cfg80211_set_bitrate_mask,
+#ifdef WLAN_FEATURE_11BE_MLO
+	.tx_control_port = wlan_hdd_cfg80211_tx_control_port,
+#endif
 };

+ 14 - 2
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -1106,6 +1106,7 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf)
 	struct hdd_context *hdd_ctx = NULL;
 	struct qdf_mac_addr *src_mac;
 	struct hdd_station_info *sta_info;
+	bool is_eapol = false;
 
 	/* Sanity check on inputs */
 	if (unlikely((!adapter_context) || (!rx_buf))) {
@@ -1173,7 +1174,10 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf)
 					     STA_INFO_SOFTAP_RX_PACKET_CBK);
 		}
 
-		if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(skb) &&
+		if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
+			is_eapol = true;
+
+		if (qdf_unlikely(is_eapol &&
 				 qdf_mem_cmp(qdf_nbuf_data(skb) +
 					     QDF_NBUF_DEST_MAC_OFFSET,
 					     adapter->mac_addr.bytes,
@@ -1215,7 +1219,15 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf)
 
 		hdd_softap_tsf_timestamp_rx(hdd_ctx, skb);
 
-		qdf_status = hdd_rx_deliver_to_stack(adapter, skb);
+		if (is_eapol && SEND_EAPOL_OVER_NL) {
+			if(cfg80211_rx_control_port(adapter->dev, skb, false))
+				qdf_status = QDF_STATUS_SUCCESS;
+			else
+				qdf_status = QDF_STATUS_E_INVAL;
+			dev_kfree_skb(skb);
+		} else {
+			qdf_status = hdd_rx_deliver_to_stack(adapter, skb);
+		}
 
 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
 			++adapter->hdd_stats.tx_rx_stats.rx_delivered[cpu_index];

+ 12 - 2
core/hdd/src/wlan_hdd_tx_rx.c

@@ -2497,7 +2497,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *adapter_context,
 	bool track_arp = false;
 	struct wlan_objmgr_vdev *vdev;
 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
-	bool is_eapol;
+	bool is_eapol, send_over_nl;
 	bool is_dhcp;
 
 	/* Sanity check on inputs */
@@ -2532,6 +2532,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *adapter_context,
 		skb->next = NULL;
 		is_eapol = false;
 		is_dhcp = false;
+		send_over_nl = false;
 
 		if (qdf_nbuf_is_ipv4_arp_pkt(skb)) {
 			if (qdf_nbuf_data_is_arp_rsp(skb) &&
@@ -2547,6 +2548,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *adapter_context,
 			}
 		} else if (qdf_nbuf_is_ipv4_eapol_pkt(skb)) {
 			subtype = qdf_nbuf_get_eapol_subtype(skb);
+			send_over_nl = true;
 			if (subtype == QDF_PROTO_EAPOL_M1) {
 				++adapter->hdd_stats.hdd_eapol_stats.
 						eapol_m1_count;
@@ -2653,7 +2655,15 @@ QDF_STATUS hdd_rx_packet_cbk(void *adapter_context,
 
 		hdd_tsf_timestamp_rx(hdd_ctx, skb, ktime_to_us(skb->tstamp));
 
-		qdf_status = hdd_rx_deliver_to_stack(adapter, skb);
+		if (send_over_nl && SEND_EAPOL_OVER_NL) {
+			if(cfg80211_rx_control_port(adapter->dev, skb, false))
+				qdf_status = QDF_STATUS_SUCCESS;
+			else
+				qdf_status = QDF_STATUS_E_INVAL;
+			dev_kfree_skb(skb);
+		} else {
+			qdf_status = hdd_rx_deliver_to_stack(adapter, skb);
+		}
 
 		if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
 			++adapter->hdd_stats.tx_rx_stats.