diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 35367cf855..a58422f50d 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -90,6 +90,7 @@ #define wma_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_WMA, params) #define wma_info(params...) QDF_TRACE_INFO(QDF_MODULE_ID_WMA, params) #define wma_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_WMA, params) +#define wma_debug_rl(params...) QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_WMA, params) #define wma_err_rl(params...) QDF_TRACE_ERROR_RL(QDF_MODULE_ID_WMA, params) #define wma_nofl_alert(params...) \ @@ -672,6 +673,16 @@ struct roam_synch_frame_ind { uint8_t *reassoc_rsp; }; +/* Max number of invalid peer entries */ +#define INVALID_PEER_MAX_NUM 5 + +/** + * struct wma_invalid_peer_params - stores invalid peer entries + * @rx_macaddr: store mac addr of invalid peer + */ +struct wma_invalid_peer_params { + uint8_t rx_macaddr[QDF_MAC_ADDR_SIZE]; +}; /** * struct wma_txrx_node - txrx node @@ -725,7 +736,8 @@ struct roam_synch_frame_ind { * @vdev_set_key_runtime_wakelock: runtime pm wakelock for set key * @ch_freq: channel frequency * @roam_scan_stats_req: cached roam scan stats request - * + * @wma_invalid_peer_params: structure storing invalid peer params + * @invalid_peer_idx: invalid peer index * It stores parameters per vdev in wma. */ struct wma_txrx_node { @@ -785,6 +797,8 @@ struct wma_txrx_node { bool is_waiting_for_key; uint32_t ch_freq; struct sir_roam_scan_stats *roam_scan_stats_req; + struct wma_invalid_peer_params invalid_peers[INVALID_PEER_MAX_NUM]; + uint8_t invalid_peer_idx; }; /** @@ -2434,7 +2448,16 @@ void wma_check_and_set_wake_timer(uint32_t time); #endif /** - * wma_rx_invalid_peer_ind(): the callback for DP to notify WMA layer + * wma_delete_invalid_peer_entries() - Delete invalid peer entries stored + * @vdev_id: virtual interface id + * @peer_mac_addr: Peer MAC address + * + * Removes the invalid peer mac entry from wma node + */ +void wma_delete_invalid_peer_entries(uint8_t vdev_id, uint8_t *peer_mac_addr); + +/** + * wma_rx_invalid_peer_ind() - the callback for DP to notify WMA layer * invalid peer data is received, this function will send message to * lim module. * @vdev_id: virtual device ID diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 2f6aa846ed..d2ae6d5db3 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -3091,27 +3091,97 @@ QDF_STATUS wma_lro_config_cmd(void *handle, &wmi_lro_cmd); } +void wma_delete_invalid_peer_entries(uint8_t vdev_id, uint8_t *peer_mac_addr) +{ + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + uint8_t i; + struct wma_txrx_node *iface; + + if (!wma) { + wma_err("wma handle is NULL"); + return; + } + + iface = &wma->interfaces[vdev_id]; + + if (peer_mac_addr) { + for (i = 0; i < INVALID_PEER_MAX_NUM; i++) { + if (qdf_mem_cmp + (iface->invalid_peers[i].rx_macaddr, + peer_mac_addr, + QDF_MAC_ADDR_SIZE) == 0) { + qdf_mem_zero(iface->invalid_peers[i].rx_macaddr, + sizeof(QDF_MAC_ADDR_SIZE)); + break; + } + } + if (i == INVALID_PEER_MAX_NUM) + wma_debug("peer_mac_addr %pM is not found", peer_mac_addr); + } else { + qdf_mem_zero(iface->invalid_peers, + sizeof(iface->invalid_peers)); + } +} + uint8_t wma_rx_invalid_peer_ind(uint8_t vdev_id, void *wh) { struct ol_rx_inv_peer_params *rx_inv_msg; struct ieee80211_frame *wh_l = (struct ieee80211_frame *)wh; tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + uint8_t i, index; + bool invalid_peer_found = false; + struct wma_txrx_node *iface; + if (!wma) { + wma_err("wma handle is NULL"); + return -EINVAL; + } + + iface = &wma->interfaces[vdev_id]; rx_inv_msg = qdf_mem_malloc(sizeof(struct ol_rx_inv_peer_params)); if (!rx_inv_msg) return -ENOMEM; + index = iface->invalid_peer_idx; rx_inv_msg->vdev_id = vdev_id; qdf_mem_copy(rx_inv_msg->ra, wh_l->i_addr1, QDF_MAC_ADDR_SIZE); qdf_mem_copy(rx_inv_msg->ta, wh_l->i_addr2, QDF_MAC_ADDR_SIZE); - WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); - wma_debug("RA:"QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(rx_inv_msg->ra)); - wma_debug("TA:"QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(rx_inv_msg->ta)); - wma_send_msg(wma, SIR_LIM_RX_INVALID_PEER, (void *)rx_inv_msg, 0); + for (i = 0; i < INVALID_PEER_MAX_NUM; i++) { + if (qdf_mem_cmp + (iface->invalid_peers[i].rx_macaddr, + rx_inv_msg->ra, + QDF_MAC_ADDR_SIZE) == 0) { + invalid_peer_found = true; + break; + } + } + + if (!invalid_peer_found) { + qdf_mem_copy(iface->invalid_peers[index].rx_macaddr, + rx_inv_msg->ra, + QDF_MAC_ADDR_SIZE); + + /* reset count if reached max */ + iface->invalid_peer_idx = + (index + 1) % INVALID_PEER_MAX_NUM; + + /* send deauth */ + WMA_LOGD("%s: vdev_id %d", __func__, vdev_id); + wma_debug(" RA: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(rx_inv_msg->ra)); + wma_debug(" TA: " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(rx_inv_msg->ta)); + + wma_send_msg(wma, + SIR_LIM_RX_INVALID_PEER, + (void *)rx_inv_msg, 0); + } else { + wma_debug_rl("Ignore invalid peer indication as received more than once " + QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(rx_inv_msg->ra)); + } return 0; } diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 56732ab999..d6c6c18440 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -3966,6 +3966,8 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta) goto send_rsp; } + wma_delete_invalid_peer_entries(add_sta->smesessionId, add_sta->staMac); + status = wma_create_peer(wma, pdev, vdev, add_sta->staMac, WMI_PEER_TYPE_DEFAULT, add_sta->smesessionId, false); @@ -5113,6 +5115,8 @@ void wma_delete_bss(tp_wma_handle wma, uint8_t vdev_id) goto out; } + wma_delete_invalid_peer_entries(vdev_id, NULL); + if (iface->psnr_req) { qdf_mem_free(iface->psnr_req); iface->psnr_req = NULL;