qcacld-3.0: Send NAN action frame to userspace

After NAN PASN pairing, followup action frames are exchanged between
the paired peers and are forwarded to userspace.
Currently, when target sends the action frames on NAN VDEV, driver
drops the frame due to following reasons:
1. driver is not able to find the adapter by destination for the
NAN opmode.
2. For "ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION", WEP bit
is set, so these action frames have additional bytes for CCMP
header after mac header. Thus, when kernel tries to compare the
action category, then it drops the frame.

So, to fix this, exempt the adapter check and strip the CCMP header
while sending the frame to userspace.

Change-Id: I9a79b7a6dee6a5c3df86d28424673f8e5776e147
CRs-Fixed: 3694362
This commit is contained in:
Rahul Gusain
2023-12-22 13:28:28 +05:30
committad av Ravindra Konda
förälder a9fa007959
incheckning 7f8c018348
4 ändrade filer med 51 tillägg och 8 borttagningar

Visa fil

@@ -712,7 +712,7 @@ static const struct ieee80211_txrx_stypes
},
[NL80211_IFTYPE_NAN] = {
.tx = 0xffff,
.rx = BIT(SIR_MAC_MGMT_AUTH),
.rx = BIT(SIR_MAC_MGMT_AUTH) | BIT(SIR_MAC_MGMT_ACTION),
},
};

Visa fil

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1133,6 +1133,8 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
struct hdd_adapter *assoc_adapter;
bool eht_capab;
struct hdd_ap_ctx *ap_ctx;
struct action_frm_hdr *action_hdr;
tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
hdd_debug("Frame Type = %d Frame Length = %d freq = %d",
frame_type, frm_len, rx_freq);
@@ -1171,6 +1173,24 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
}
}
if (type == WLAN_FC0_TYPE_MGMT && sub_type == WLAN_FC0_STYPE_ACTION &&
frm_len >= (sizeof(struct wlan_frame_hdr) +
sizeof(*vendor_specific))) {
action_hdr = (struct action_frm_hdr *)(pb_frames +
sizeof(struct wlan_frame_hdr));
vendor_specific =
(tpSirMacVendorSpecificPublicActionFrameHdr)action_hdr;
if (is_nan_oui(vendor_specific->Oui)) {
adapter = hdd_get_adapter(hdd_ctx, QDF_NAN_DISC_MODE);
if (!adapter) {
hdd_err("NAN adapter is null");
return;
}
goto check_adapter;
}
}
/* Get adapter from Destination mac address of the frame */
if (type == SIR_MAC_MGMT_FRAME &&
sub_type != SIR_MAC_MGMT_PROBE_REQ && !is_pasn_auth_frame &&
@@ -1209,6 +1229,7 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
}
}
check_adapter:
if (!adapter->dev) {
hdd_err("adapter->dev is NULL");
return;

Visa fil

@@ -2294,8 +2294,10 @@ void lim_process_action_frame_no_session(struct mac_context *mac, uint8_t *pBd)
pe_debug("Received an action frame category: %d action_id: %d",
action_hdr->category, action_hdr->category ==
ACTION_CATEGORY_PUBLIC ? action_hdr->actionID : 255);
action_hdr->category, (action_hdr->category ==
ACTION_CATEGORY_PUBLIC || action_hdr->category ==
ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION) ?
action_hdr->actionID : 255);
if (frame_len < sizeof(*action_hdr)) {
pe_debug("frame_len %d less than action frame header len",
@@ -2305,6 +2307,7 @@ void lim_process_action_frame_no_session(struct mac_context *mac, uint8_t *pBd)
switch (action_hdr->category) {
case ACTION_CATEGORY_PUBLIC:
case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION:
if (action_hdr->actionID == PUB_ACTION_VENDOR_SPECIFIC) {
vendor_specific =
(tpSirMacVendorSpecificPublicActionFrameHdr)

Visa fil

@@ -90,6 +90,7 @@
#include "wlan_cm_api.h"
#include "wlan_mlo_link_force.h"
#include <target_if_spatial_reuse.h>
#include "wlan_nan_api_i.h"
/* Max debug string size for WMM in bytes */
#define WMA_WMM_DEBUG_STRING_SIZE 512
@@ -3340,7 +3341,8 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle,
return -EINVAL;
}
if (iface->type == WMI_VDEV_TYPE_NDI) {
if (iface->type == WMI_VDEV_TYPE_NDI ||
iface->type == WMI_VDEV_TYPE_NAN) {
hdr_len = IEEE80211_CCMP_HEADERLEN;
mic_len = IEEE80211_CCMP_MICLEN;
} else {
@@ -3491,14 +3493,16 @@ wma_check_and_process_rmf_frame(tp_wma_handle wma_handle,
struct ieee80211_frame *hdr = *wh;
iface = &(wma_handle->interfaces[vdev_id]);
if (iface->type != WMI_VDEV_TYPE_NDI && !iface->rmfEnabled)
if ((iface->type != WMI_VDEV_TYPE_NDI &&
iface->type != WMI_VDEV_TYPE_NAN) && !iface->rmfEnabled)
return 0;
if (qdf_is_macaddr_group((struct qdf_mac_addr *)(hdr->i_addr1)) ||
qdf_is_macaddr_broadcast((struct qdf_mac_addr *)(hdr->i_addr1)) ||
wma_get_peer_pmf_status(wma_handle, hdr->i_addr2) ||
(iface->type == WMI_VDEV_TYPE_NDI &&
(hdr->i_fc[1] & IEEE80211_FC1_WEP))) {
((iface->type == WMI_VDEV_TYPE_NDI ||
iface->type == WMI_VDEV_TYPE_NAN) &&
(hdr->i_fc[1] & IEEE80211_FC1_WEP))) {
status = wma_process_rmf_frame(wma_handle, iface, hdr,
rx_pkt, buf);
if (status)
@@ -3702,6 +3706,21 @@ int wma_form_rx_packet(qdf_nbuf_t buf,
buf);
if (status)
return status;
} else if (mgt_subtype == MGMT_SUBTYPE_ACTION) {
/* NAN Action frame */
vdev_id = wlan_nan_get_vdev_id_from_bssid(
wma_handle->pdev,
wh->i_addr3,
WLAN_ACTION_OUI_ID);
if (vdev_id != WMA_INVALID_VDEV_ID) {
status = wma_check_and_process_rmf_frame(
wma_handle,
vdev_id, &wh,
rx_pkt, buf);
if (status)
return status;
}
}
}