瀏覽代碼

qcacld-3.0: Use peer to get the cipher to decide MIC length

Driver uses cipher stored in vdev to get the MIC length, which
may get updated if multiple peer(TDLS peer in STA case) get
connected to the vdev. Thus depending on latest peer cipher type
the MIC length will be calculated for all peers.

To fix store cipher info in peer and use it to calculate MIC length
for the frame.

Change-Id: I8afbf9a3bb43c294dbacbbaa7fa0746600937d11
CRs-Fixed: 2428482
Abhishek Singh 6 年之前
父節點
當前提交
64350c5d68

+ 93 - 2
mlme/core/inc/wlan_mlme_main.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -27,7 +27,7 @@
 #include <wlan_objmgr_global_obj.h>
 #include <wlan_objmgr_global_obj.h>
 #include <wlan_cmn.h>
 #include <wlan_cmn.h>
 #include <wlan_objmgr_vdev_obj.h>
 #include <wlan_objmgr_vdev_obj.h>
-
+#include <wlan_objmgr_peer_obj.h>
 
 
 #define mlme_fatal(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_MLME, params)
 #define mlme_fatal(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_MLME, params)
 #define mlme_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_MLME, params)
 #define mlme_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_MLME, params)
@@ -43,6 +43,14 @@ struct wlan_mlme_psoc_obj {
 	struct wlan_mlme_cfg cfg;
 	struct wlan_mlme_cfg cfg;
 };
 };
 
 
+/**
+ * struct peer_mlme_priv_obj - peer MLME component object
+ * @ucast_key_cipher: unicast crypto type.
+ */
+struct peer_mlme_priv_obj {
+	uint32_t ucast_key_cipher;
+};
+
 #ifdef CONFIG_VDEV_SM
 #ifdef CONFIG_VDEV_SM
 
 
 /**
 /**
@@ -119,6 +127,89 @@ mlme_vdev_object_destroyed_notification(struct wlan_objmgr_vdev *vdev,
 
 
 #endif
 #endif
 
 
+/**
+ * wlan_peer_set_unicast_cipher() - set unicast cipher
+ * @peer: PEER object
+ * @value: value to be set
+ *
+ * Return: void
+ */
+static inline
+void wlan_peer_set_unicast_cipher(struct wlan_objmgr_peer *peer, uint32_t value)
+{
+	struct peer_mlme_priv_obj *peer_priv;
+
+	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
+							  WLAN_UMAC_COMP_MLME);
+	if (!peer_priv) {
+		mlme_err(" peer mlme component object is NULL");
+		return;
+	}
+	peer_priv->ucast_key_cipher  = value;
+}
+
+/**
+ * wlan_peer_get_unicast_cipher() - get unicast cipher
+ * @peer: PEER object
+ *
+ * Return: ucast_key_cipher value
+ */
+static inline
+uint32_t wlan_peer_get_unicast_cipher(struct wlan_objmgr_peer *peer)
+{
+	struct peer_mlme_priv_obj *peer_priv;
+
+	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
+							  WLAN_UMAC_COMP_MLME);
+	if (!peer_priv) {
+		mlme_err("peer mlme component object is NULL");
+		return 0;
+	}
+
+	return peer_priv->ucast_key_cipher;
+}
+
+/**
+ * wma_get_peer_mic_len() - get mic hdr len and mic length for peer
+ * @psoc: psoc
+ * @pdev_id: pdev id for the peer
+ * @peer_mac: peer mac
+ * @mic_len: mic length for peer
+ * @mic_hdr_len: mic header length for peer
+ *
+ * Return: Success or Failure status
+ */
+QDF_STATUS mlme_get_peer_mic_len(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
+				 uint8_t *peer_mac, uint8_t *mic_len,
+				 uint8_t *mic_hdr_len);
+
+/**
+ * mlme_peer_object_created_notification(): mlme peer create handler
+ * @peer: peer which is going to created by objmgr
+ * @arg: argument for vdev create handler
+ *
+ * Register this api with objmgr to detect peer is created
+ *
+ * Return: QDF_STATUS status in case of success else return error
+ */
+
+QDF_STATUS
+mlme_peer_object_created_notification(struct wlan_objmgr_peer *peer,
+				      void *arg);
+
+/**
+ * mlme_peer_object_destroyed_notification(): mlme peer delete handler
+ * @peer: peer which is going to delete by objmgr
+ * @arg: argument for vdev delete handler
+ *
+ * Register this api with objmgr to detect peer is deleted
+ *
+ * Return: QDF_STATUS status in case of success else return error
+ */
+QDF_STATUS
+mlme_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
+					void *arg);
+
 /**
 /**
  * mlme_get_dynamic_vdev_config() - get the vdev dynamic config params
  * mlme_get_dynamic_vdev_config() - get the vdev dynamic config params
  * @vdev: vdev pointer
  * @vdev: vdev pointer

+ 96 - 0
mlme/core/src/wlan_mlme_main.c

@@ -239,6 +239,102 @@ out:
 	return status;
 	return status;
 }
 }
 
 
+QDF_STATUS mlme_get_peer_mic_len(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
+				 uint8_t *peer_mac, uint8_t *mic_len,
+				 uint8_t *mic_hdr_len)
+{
+	struct wlan_objmgr_peer *peer;
+	uint32_t key_cipher;
+
+	if (!psoc || !mic_len || !mic_hdr_len || !peer_mac) {
+		mlme_debug("psoc/mic_len/mic_hdr_len/peer_mac null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	peer = wlan_objmgr_get_peer(psoc, pdev_id,
+				    peer_mac, WLAN_LEGACY_MAC_ID);
+	if (!peer) {
+		mlme_debug("Peer of peer_mac %pM not found", peer_mac);
+		return QDF_STATUS_E_INVAL;
+	}
+	key_cipher = wlan_peer_get_unicast_cipher(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
+
+	if (key_cipher == WMI_CIPHER_AES_GCM) {
+		*mic_hdr_len = WLAN_IEEE80211_GCMP_HEADERLEN;
+		*mic_len = WLAN_IEEE80211_GCMP_MICLEN;
+	} else {
+		*mic_hdr_len = IEEE80211_CCMP_HEADERLEN;
+		*mic_len = IEEE80211_CCMP_MICLEN;
+	}
+	mlme_debug("peer %pM hdr_len %d mic_len %d key_cipher %d", peer_mac,
+		   *mic_hdr_len, *mic_len, key_cipher);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mlme_peer_object_created_notification(struct wlan_objmgr_peer *peer,
+				      void *arg)
+{
+	struct peer_mlme_priv_obj *peer_priv;
+	QDF_STATUS status;
+
+	if (!peer) {
+		mlme_err(" peer is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer_priv = qdf_mem_malloc(sizeof(*peer_priv));
+	if (!peer_priv) {
+		mlme_err(" peer_priv component object alloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	status = wlan_objmgr_peer_component_obj_attach(peer,
+						       WLAN_UMAC_COMP_MLME,
+						       (void *)peer_priv,
+						       QDF_STATUS_SUCCESS);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("unable to attach peer_priv obj to peer obj");
+		qdf_mem_free(peer_priv);
+	}
+
+	return status;
+}
+
+QDF_STATUS
+mlme_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
+					void *arg)
+{
+	struct peer_mlme_priv_obj *peer_priv;
+	QDF_STATUS status;
+
+	if (!peer) {
+		mlme_err(" peer is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
+							  WLAN_UMAC_COMP_MLME);
+	if (!peer_priv) {
+		mlme_err(" peer MLME component object is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_peer_component_obj_detach(peer,
+						       WLAN_UMAC_COMP_MLME,
+						       peer_priv);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		mlme_err("unable to detach peer_priv obj to peer obj");
+
+	qdf_mem_free(peer_priv);
+
+	return status;
+}
+
 static void mlme_init_chainmask_cfg(struct wlan_objmgr_psoc *psoc,
 static void mlme_init_chainmask_cfg(struct wlan_objmgr_psoc *psoc,
 				    struct wlan_mlme_chainmask *chainmask_info)
 				    struct wlan_mlme_chainmask *chainmask_info)
 {
 {

+ 35 - 0
mlme/dispatcher/src/wlan_mlme_ucfg_api.c

@@ -125,7 +125,28 @@ QDF_STATUS ucfg_mlme_init(void)
 		mlme_err("unable to register psoc create handle");
 		mlme_err("unable to register psoc create handle");
 		return status;
 		return status;
 	}
 	}
+
 	status = ucfg_mlme_vdev_init();
 	status = ucfg_mlme_vdev_init();
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
+	status = wlan_objmgr_register_peer_create_handler(
+			WLAN_UMAC_COMP_MLME,
+			mlme_peer_object_created_notification,
+			NULL);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("peer create register notification failed");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_register_peer_destroy_handler(
+			WLAN_UMAC_COMP_MLME,
+			mlme_peer_object_destroyed_notification,
+			NULL);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("peer destroy register notification failed");
+		return QDF_STATUS_E_FAILURE;
+	}
 
 
 	return status;
 	return status;
 }
 }
@@ -134,6 +155,20 @@ QDF_STATUS ucfg_mlme_deinit(void)
 {
 {
 	QDF_STATUS status;
 	QDF_STATUS status;
 
 
+	status = wlan_objmgr_unregister_peer_destroy_handler(
+			WLAN_UMAC_COMP_MLME,
+			mlme_peer_object_destroyed_notification,
+			NULL);
+	if (QDF_IS_STATUS_ERROR(status))
+		mlme_err("unable to unregister peer destroy handle");
+
+	status = wlan_objmgr_unregister_peer_create_handler(
+			WLAN_UMAC_COMP_MLME,
+			mlme_peer_object_created_notification,
+			NULL);
+	if (QDF_IS_STATUS_ERROR(status))
+		mlme_err("unable to unregister peer create handle");
+
 	status = ucfg_mlme_vdev_deinit();
 	status = ucfg_mlme_vdev_deinit();
 	if (QDF_IS_STATUS_ERROR(status))
 	if (QDF_IS_STATUS_ERROR(status))
 		mlme_err("unable to unregister vdev destroy handle");
 		mlme_err("unable to unregister vdev destroy handle");

+ 16 - 3
p2p/core/src/wlan_p2p_off_chan_tx.c

@@ -33,6 +33,7 @@
 #include "wlan_p2p_main.h"
 #include "wlan_p2p_main.h"
 #include "wlan_p2p_off_chan_tx.h"
 #include "wlan_p2p_off_chan_tx.h"
 #include "wlan_osif_request_manager.h"
 #include "wlan_osif_request_manager.h"
+#include <wlan_mlme_main.h>
 
 
 /**
 /**
  * p2p_psoc_get_tx_ops() - get p2p tx ops
  * p2p_psoc_get_tx_ops() - get p2p tx ops
@@ -1509,9 +1510,21 @@ static QDF_STATUS p2p_populate_rmf_field(struct tx_action_context *tx_ctx,
 	}
 	}
 	if (!qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) &&
 	if (!qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) &&
 	    !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) {
 	    !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) {
+		uint8_t mic_len, mic_hdr_len, pdev_id;
+
+		pdev_id =
+			wlan_get_pdev_id_from_vdev_id(tx_ctx->p2p_soc_obj->soc,
+						      tx_ctx->vdev_id,
+						      WLAN_P2P_ID);
+		status = mlme_get_peer_mic_len(p2p_soc_obj->soc, pdev_id,
+					       wh->i_addr1, &mic_len,
+					       &mic_hdr_len);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			p2p_err("Failed to get peer mic length.");
+			return status;
+		}
 
 
-		frame_len = *size + IEEE80211_CCMP_HEADERLEN +
-			    IEEE80211_CCMP_MICLEN;
+		frame_len = *size + mic_hdr_len + mic_len;
 		status = p2p_packet_alloc((uint16_t)frame_len, (void **)&frame,
 		status = p2p_packet_alloc((uint16_t)frame_len, (void **)&frame,
 			 &pkt);
 			 &pkt);
 		if (status != QDF_STATUS_SUCCESS) {
 		if (status != QDF_STATUS_SUCCESS) {
@@ -1521,7 +1534,7 @@ static QDF_STATUS p2p_populate_rmf_field(struct tx_action_context *tx_ctx,
 		}
 		}
 
 
 		qdf_mem_copy(frame, wh, sizeof(*wh));
 		qdf_mem_copy(frame, wh, sizeof(*wh));
-		qdf_mem_copy(frame + sizeof(*wh) + IEEE80211_CCMP_HEADERLEN,
+		qdf_mem_copy(frame + sizeof(*wh) + mic_hdr_len,
 			     *ppbuf + sizeof(*wh),
 			     *ppbuf + sizeof(*wh),
 			     *size - sizeof(*wh));
 			     *size - sizeof(*wh));
 		rmf_wh = (struct wlan_frame_hdr *)frame;
 		rmf_wh = (struct wlan_frame_hdr *)frame;