Browse Source

qcacld-3.0: Handle legacy connect request

Handle legacy connect request and create pe_session
for the same.

Change-Id: Ie1e801c42f90d79d613f9d0233ec9a00a2b0d58b
CRs-Fixed: 2808000
gaurank kathpalia 4 years ago
parent
commit
e5fb361504

+ 30 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h

@@ -29,7 +29,7 @@
 #include "scheduler_api.h"
 
 /**
- * struct cm_vdev_join_req - connect req from legacy CM to peer manager
+ * struct cm_vdev_join_req - connect req from legacy CM to vdev manager
  * @vdev_id: vdev id
  * @cm_id: Connect manager id
  * @force_rsne_override: force the arbitrary rsne received in connect req to be
@@ -49,6 +49,16 @@ struct cm_vdev_join_req {
 	struct scan_cache_entry *entry;
 };
 
+/**
+ * struct cm_vdev_join_rsp - connect rsp from vdev mgr to connection mgr
+ * @psoc: psoc object
+ * @connect_rsp: Connect response to be sent to CM
+ */
+struct cm_vdev_join_rsp {
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_cm_connect_rsp connect_rsp;
+};
+
 /**
  * cm_handle_connect_req() - Connection manager ext connect request to start
  * vdev and peer assoc state machine
@@ -156,6 +166,25 @@ QDF_STATUS cm_process_join_req(struct scheduler_msg *msg);
  */
 QDF_STATUS cm_process_disconnect_req(struct scheduler_msg *msg);
 
+/**
+ * wlan_cm_send_connect_rsp() - Process vdev join rsp and send to CM
+ * @msg: scheduler message
+ *
+ * Process connect response and send it to CM SM.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_send_connect_rsp(struct scheduler_msg *msg);
+
+/**
+ * wlan_cm_free_connect_rsp() - Function to free all params in join rsp
+ * @rsp: CM join response
+ *
+ * Function to free up all the memory in join rsp.
+ *
+ * Return: void
+ */
+void wlan_cm_free_connect_rsp(struct cm_vdev_join_rsp *rsp);
 
 #endif /* FEATURE_CM_ENABLE */
 #endif /* __WLAN_CM_VDEV_API_H__ */

+ 64 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -22,6 +22,7 @@
 #include "wlan_cm_vdev_api.h"
 #include "wlan_scan_utils_api.h"
 #include "wlan_mlme_dbg.h"
+#include "wlan_cm_api.h"
 
 void cm_free_join_req(struct cm_vdev_join_req *join_req)
 {
@@ -84,6 +85,35 @@ cm_copy_join_params(struct cm_vdev_join_req *join_req,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS wlan_cm_send_connect_rsp(struct scheduler_msg *msg)
+{
+	struct cm_vdev_join_rsp *rsp;
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+
+	if (!msg || !msg->bodyptr)
+		return QDF_STATUS_E_FAILURE;
+
+	rsp = msg->bodyptr;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(rsp->psoc,
+						    rsp->connect_rsp.vdev_id,
+						    WLAN_MLME_CM_ID);
+	if (!vdev) {
+		mlme_err("vdev_id: %d cm_id 0x%x : vdev not found",
+			 rsp->connect_rsp.vdev_id, rsp->connect_rsp.cm_id);
+		wlan_cm_free_connect_rsp(rsp);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wlan_cm_connect_rsp(vdev, &rsp->connect_rsp);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+
+	wlan_cm_free_connect_rsp(rsp);
+
+	return status;
+}
+
 QDF_STATUS
 cm_handle_connect_req(struct wlan_objmgr_vdev *vdev,
 		      struct wlan_cm_vdev_connect_req *req)
@@ -134,3 +164,37 @@ cm_handle_connect_complete(struct wlan_objmgr_vdev *vdev,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+#ifdef WLAN_FEATURE_FILS_SK
+static inline void wlan_cm_free_fils_ie(struct wlan_connect_rsp_ies *connect_ie)
+{
+	if (!connect_ie->fils_ie)
+		return;
+
+	if (connect_ie->fils_ie->fils_pmk) {
+		qdf_mem_zero(connect_ie->fils_ie->fils_pmk,
+			     connect_ie->fils_ie->fils_pmk_len);
+		qdf_mem_free(connect_ie->fils_ie->fils_pmk);
+	}
+	qdf_mem_zero(connect_ie->fils_ie, sizeof(*connect_ie->fils_ie));
+	qdf_mem_free(connect_ie->fils_ie);
+}
+#else
+static inline void wlan_cm_free_fils_ie(struct wlan_connect_rsp_ies *connect_ie)
+{
+}
+#endif
+
+void wlan_cm_free_connect_rsp(struct cm_vdev_join_rsp *rsp)
+{
+	struct wlan_connect_rsp_ies *connect_ie =
+						&rsp->connect_rsp.connect_ies;
+
+	qdf_mem_free(connect_ie->assoc_req.ptr);
+	qdf_mem_free(connect_ie->bcn_probe_rsp.ptr);
+	qdf_mem_free(connect_ie->assoc_rsp.ptr);
+	qdf_mem_free(connect_ie->ric_resp_ie.ptr);
+	wlan_cm_free_fils_ie(connect_ie);
+	qdf_mem_zero(rsp, sizeof(*rsp));
+	qdf_mem_free(rsp);
+}

+ 4 - 0
core/mac/src/pe/include/lim_session.h

@@ -19,6 +19,7 @@
 #if !defined(__LIM_SESSION_H)
 #define __LIM_SESSION_H
 
+#include "wlan_cm_public_struct.h"
 /**=========================================================================
 
    \file  lim_session.h
@@ -140,6 +141,9 @@ struct obss_detection_cfg {
 struct pe_session {
 	/* To check session table is in use or free */
 	uint8_t available;
+#ifdef FEATURE_CM_ENABLE
+	wlan_cm_id cm_id;
+#endif
 	uint16_t peSessionId;
 	union {
 		uint8_t smeSessionId;

+ 199 - 1
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -1339,10 +1339,209 @@ lim_get_vdev_rmf_capable(struct mac_context *mac, struct pe_session *session)
 #endif
 
 #ifdef FEATURE_CM_ENABLE
+static QDF_STATUS
+lim_cm_prepare_join_rsp_from_pe_session(struct pe_session *pe_session,
+				        struct cm_vdev_join_rsp *rsp,
+				        enum wlan_cm_connect_fail_reason reason,
+				        QDF_STATUS connect_status,
+				        enum wlan_status_code status_code)
+{
+	struct wlan_cm_connect_rsp *connect_rsp = &rsp->connect_rsp;
+	struct wlan_connect_rsp_ies *connect_ie = &rsp->connect_rsp.connect_ies;
+
+	connect_rsp->cm_id = pe_session->cm_id;
+	connect_rsp->vdev_id = pe_session->vdev_id;
+	qdf_mem_copy(connect_rsp->bssid.bytes, pe_session->bssId,
+		     QDF_MAC_ADDR_SIZE);
+
+	connect_rsp->freq = pe_session->curr_op_freq;
+	connect_rsp->connect_status = connect_status;
+	connect_rsp->reason = reason;
+	connect_rsp->reason_code = status_code;
+	connect_rsp->ssid.length =
+			QDF_MIN(WLAN_SSID_MAX_LEN, pe_session->ssId.length);
+	qdf_mem_copy(connect_rsp->ssid.ssid, pe_session->ssId.ssId,
+		     connect_rsp->ssid.length);
+	connect_rsp->aid = pe_session->limAID;
+
+	if (pe_session->assoc_req) {
+		connect_ie->assoc_req.len = pe_session->assocReqLen;
+		connect_ie->assoc_req.ptr =
+			qdf_mem_malloc(sizeof(connect_ie->assoc_req.len));
+		if (!connect_ie->assoc_req.ptr)
+			return QDF_STATUS_E_NOMEM;
+
+		qdf_mem_copy(connect_ie->assoc_req.ptr, pe_session->assoc_req,
+			     connect_ie->assoc_req.len);
+	}
+
+	if (pe_session->assocRsp) {
+		connect_ie->assoc_rsp.len = pe_session->assocRspLen;
+		connect_ie->assoc_rsp.ptr =
+			qdf_mem_malloc(sizeof(connect_ie->assoc_rsp.len));
+		if (!connect_ie->assoc_rsp.ptr)
+			return QDF_STATUS_E_NOMEM;
+
+		qdf_mem_copy(connect_ie->assoc_rsp.ptr, pe_session->assocRsp,
+			     connect_ie->assoc_rsp.len);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void
+lim_cm_fill_join_rsp_from_connect_req(struct cm_vdev_join_req *req,
+				      struct cm_vdev_join_rsp *rsp,
+				      enum wlan_cm_connect_fail_reason reason)
+{
+	struct wlan_cm_connect_rsp *connect_rsp = &rsp->connect_rsp;
+
+	connect_rsp->cm_id = req->cm_id;
+	connect_rsp->vdev_id = req->vdev_id;
+	qdf_copy_macaddr(&connect_rsp->bssid, &req->entry->bssid);
+	connect_rsp->freq = req->entry->channel.chan_freq;
+	connect_rsp->connect_status = QDF_STATUS_E_FAILURE;
+	connect_rsp->reason = reason;
+	connect_rsp->ssid = req->entry->ssid;
+}
+
+static QDF_STATUS lim_cm_flush_connect_rsp(struct scheduler_msg *msg)
+{
+	struct cm_vdev_join_rsp *rsp;
+
+	if (!msg || !msg->bodyptr)
+		return QDF_STATUS_E_INVAL;
+
+	rsp = msg->bodyptr;
+	wlan_cm_free_connect_rsp(rsp);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void
+lim_cm_send_connect_rsp(struct mac_context *mac_ctx,
+		        struct pe_session *pe_session,
+		        struct cm_vdev_join_req *req,
+		        enum wlan_cm_connect_fail_reason reason,
+		        QDF_STATUS connect_status,
+		        enum wlan_status_code status_code)
+{
+	struct cm_vdev_join_rsp *rsp;
+	QDF_STATUS status;
+	struct scheduler_msg msg;
+
+	if (!pe_session && !req)
+		return;
+
+	rsp = qdf_mem_malloc(sizeof(*rsp));
+	if (!rsp)
+		return;
+
+	rsp->psoc = mac_ctx->psoc;
+
+	if (!pe_session) {
+		lim_cm_fill_join_rsp_from_connect_req(req, rsp, reason);
+	} else {
+		status =
+			lim_cm_prepare_join_rsp_from_pe_session(pe_session,
+								rsp,
+								reason,
+								connect_status,
+								status_code);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			wlan_cm_free_connect_rsp(rsp);
+			return;
+		}
+	}
+
+	qdf_mem_zero(&msg, sizeof(msg));
+
+	msg.bodyptr = rsp;
+	msg.callback = wlan_cm_send_connect_rsp;
+	msg.flush_callback = lim_cm_flush_connect_rsp;
+
+	status = scheduler_post_message(QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_SME,
+					QDF_MODULE_ID_SME, &msg);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		pe_err("vdev_id: %d cm_id 0x%x : msg post fails",
+			rsp->connect_rsp.vdev_id, rsp->connect_rsp.cm_id);
+		wlan_cm_free_connect_rsp(rsp);
+	}
+}
+
+static struct pe_session *
+lim_cm_create_session(struct mac_context *mac_ctx, struct cm_vdev_join_req *req)
+{
+	struct pe_session *pe_session;
+	uint8_t session_id;
+	struct wlan_objmgr_vdev *vdev;
+
+	pe_session = pe_find_session_by_bssid(mac_ctx, req->entry->bssid.bytes,
+					      &session_id);
+
+	if (pe_session) {
+		pe_err("vdev_id: %d cm_id 0x%x :pe-session(%d (vdev %d)) already exists for BSSID: "
+		       QDF_MAC_ADDR_FMT " in lim_sme_state = %X",
+		       req->vdev_id, req->cm_id, session_id,
+		       pe_session->vdev_id,
+		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes),
+		       pe_session->limSmeState);
+		return NULL;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
+						    req->vdev_id,
+						    WLAN_MLME_CM_ID);
+	if (!vdev) {
+		pe_err("vdev_id: %d cm_id 0x%x : vdev not found", req->vdev_id,
+		       req->cm_id);
+		return NULL;
+	}
+
+	pe_session = pe_create_session(mac_ctx, req->entry->bssid.bytes,
+			&session_id,
+			mac_ctx->lim.max_sta_of_pe_session,
+			eSIR_INFRASTRUCTURE_MODE,
+			req->vdev_id,
+			wlan_vdev_mlme_get_opmode(vdev));
+	if (!pe_session)
+		pe_err("vdev_id: %d cm_id 0x%x : pe_session create failed BSSID"
+		       QDF_MAC_ADDR_FMT, req->vdev_id, req->cm_id,
+		       QDF_MAC_ADDR_REF(req->entry->bssid.bytes));
+
+	pe_session->cm_id = req->cm_id;
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
+
+	return pe_session;
+}
+
 static QDF_STATUS
 lim_cm_handle_join_req(struct cm_vdev_join_req *req)
 {
+	struct mac_context *mac_ctx;
+	struct pe_session *pe_session;
+
+	if (!req)
+		return QDF_STATUS_E_INVAL;
+
+	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
+
+	if (!mac_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	pe_session = lim_cm_create_session(mac_ctx, req);
+
+	if (!pe_session)
+		goto fail;
+
 	return QDF_STATUS_SUCCESS;
+
+fail:
+	lim_cm_send_connect_rsp(mac_ctx, pe_session, req, CM_GENERIC_FAILURE,
+			        QDF_STATUS_E_FAILURE, 0);
+	return QDF_STATUS_E_FAILURE;
 }
 
 QDF_STATUS cm_process_join_req(struct scheduler_msg *msg)
@@ -1679,7 +1878,6 @@ __lim_process_sme_join_req(struct mac_context *mac_ctx, void *msg_buf)
 				ret_code = eSIR_SME_INVALID_PARAMETERS;
 				goto end;
 			}
-
 		}
 		if (sme_join_req->addIEScan.length)
 			qdf_mem_copy(&session->lim_join_req->addIEScan,