qcacmn: Drop mpdus received on non-monitor PMAC

Currently the monitor mode filter settings are set
for both the PMAC. Hence it is possible that the
non-monitor PMAC (the PMAC on which monitor vdev
is not running), can receive packets and forward them
to the monitor destination ring.

The above scenario will lead to a ppdu_id mismatch
when reaping the monitor status ring and comparing
the ppdu_id in status ring with the one in monitor
destination ring, since monitor status ring will
have ppdu_id from the PMAC on which monitor vdev is
running, whereas monitor destination ring will have
packets from both the PMAC.

In order to mitigate the above issue, detect the
packets in the monitor destination ring, which are
not from the PMAC where monitor vdev is running, and
drop them.

Change-Id: I32392ceeadffd9cb7a4dd76336004a9dcbb99404
CRs-Fixed: 3318036
Šī revīzija ir iekļauta:
Rakesh Pillai
2022-10-21 07:34:46 -07:00
revīziju iesūtīja Madan Koyyalamudi
vecāks 2158048410
revīzija f533809136
4 mainīti faili ar 208 papildinājumiem un 0 dzēšanām

Parādīt failu

@@ -463,6 +463,153 @@ next_msdu:
return rx_bufs_used;
}
#if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_NON_MON_PMAC)
static int dp_rx_mon_drop_one_mpdu(struct dp_pdev *pdev,
uint32_t mac_id,
hal_rxdma_desc_t rxdma_dst_ring_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail)
{
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
struct dp_soc *soc = pdev->soc;
hal_soc_handle_t hal_soc = soc->hal_soc;
struct hal_buf_info buf_info;
uint32_t msdu_count = 0;
uint32_t rx_bufs_used = 0;
void *rx_msdu_link_desc;
struct hal_rx_msdu_list msdu_list;
uint16_t num_msdus;
qdf_nbuf_t nbuf;
uint32_t i;
uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST;
uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS];
struct rx_desc_pool *rx_desc_pool;
rx_desc_pool = dp_rx_get_mon_desc_pool(soc, mac_id, pdev->pdev_id);
hal_rx_reo_ent_buf_paddr_get(hal_soc, rxdma_dst_ring_desc,
&buf_info, &msdu_count);
do {
rx_msdu_link_desc = dp_rx_cookie_2_mon_link_desc(pdev,
buf_info,
mac_id);
if (qdf_unlikely(!rx_msdu_link_desc)) {
mon_pdev->rx_mon_stats.mon_link_desc_invalid++;
return rx_bufs_used;
}
hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc,
&msdu_list, &num_msdus);
for (i = 0; i < num_msdus; i++) {
struct dp_rx_desc *rx_desc;
qdf_dma_addr_t buf_paddr;
rx_desc = dp_rx_get_mon_desc(soc,
msdu_list.sw_cookie[i]);
if (qdf_unlikely(!rx_desc)) {
mon_pdev->rx_mon_stats.
mon_rx_desc_invalid++;
continue;
}
nbuf = DP_RX_MON_GET_NBUF_FROM_DESC(rx_desc);
buf_paddr =
dp_rx_mon_get_paddr_from_desc(rx_desc);
if (qdf_unlikely(!rx_desc->in_use || !nbuf ||
msdu_list.paddr[i] !=
buf_paddr)) {
mon_pdev->rx_mon_stats.
mon_nbuf_sanity_err++;
continue;
}
rx_bufs_used++;
if (!rx_desc->unmapped) {
dp_rx_mon_buffer_unmap(soc, rx_desc,
rx_desc_pool->buf_size);
rx_desc->unmapped = 1;
}
qdf_nbuf_free(nbuf);
dp_rx_add_to_free_desc_list(head, tail, rx_desc);
if (!(msdu_list.msdu_info[i].msdu_flags &
HAL_MSDU_F_MSDU_CONTINUATION))
msdu_count--;
}
/*
* Store the current link buffer into to the local
* structure to be used for release purpose.
*/
hal_rxdma_buff_addr_info_set(soc->hal_soc,
rx_link_buf_info,
buf_info.paddr,
buf_info.sw_cookie,
buf_info.rbm);
hal_rx_mon_next_link_desc_get(soc->hal_soc,
rx_msdu_link_desc,
&buf_info);
if (dp_rx_monitor_link_desc_return(pdev,
(hal_buff_addrinfo_t)
rx_link_buf_info,
mac_id, bm_action) !=
QDF_STATUS_SUCCESS)
dp_info_rl("monitor link desc return failed");
} while (buf_info.paddr && msdu_count);
return rx_bufs_used;
}
static QDF_STATUS
dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
hal_rxdma_desc_t rxdma_dst_ring_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail,
uint32_t *rx_bufs_dropped)
{
struct dp_soc *soc = pdev->soc;
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
uint32_t lmac_id = DP_MON_INVALID_LMAC_ID;
uint8_t src_link_id;
QDF_STATUS status;
if (mon_pdev->mon_chan_band == REG_BAND_UNKNOWN)
return QDF_STATUS_E_INVAL;
lmac_id = pdev->ch_band_lmac_id_mapping[mon_pdev->mon_chan_band];
status = hal_rx_reo_ent_get_src_link_id(soc->hal_soc,
rxdma_dst_ring_desc,
&src_link_id);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_INVAL;
if (src_link_id == lmac_id)
return QDF_STATUS_E_INVAL;
*rx_bufs_dropped = dp_rx_mon_drop_one_mpdu(pdev, mac_id,
rxdma_dst_ring_desc,
head, tail);
return QDF_STATUS_SUCCESS;
}
#else
static inline QDF_STATUS
dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
hal_rxdma_desc_t rxdma_dst_ring_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail,
uint32_t *rx_bufs_dropped)
{
return QDF_STATUS_E_FAILURE;
}
#endif
void dp_rx_mon_dest_process(struct dp_soc *soc, struct dp_intr *int_ctx,
uint32_t mac_id, uint32_t quota)
{
@@ -517,10 +664,23 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, struct dp_intr *int_ctx,
hal_srng_dst_peek(hal_soc, mon_dst_srng))) {
qdf_nbuf_t head_msdu, tail_msdu;
uint32_t npackets;
uint32_t rx_bufs_dropped;
rx_bufs_dropped = 0;
head_msdu = (qdf_nbuf_t)NULL;
tail_msdu = (qdf_nbuf_t)NULL;
if (QDF_STATUS_SUCCESS ==
dp_rx_mon_check_n_drop_mpdu(pdev, mac_id,
rxdma_dst_ring_desc,
&head, &tail,
&rx_bufs_dropped)) {
/* Increment stats */
rx_bufs_used += rx_bufs_dropped;
hal_srng_dst_get_next(hal_soc, mon_dst_srng);
continue;
}
mpdu_rx_bufs_used =
dp_rx_mon_mpdu_pop(soc, mac_id,
rxdma_dst_ring_desc,
@@ -1037,6 +1197,18 @@ dp_mon_dest_srng_drop_for_mac(struct dp_pdev *pdev, uint32_t mac_id)
return 0;
}
#endif
#if !defined(DISABLE_MON_CONFIG) && defined(MON_ENABLE_DROP_FOR_NON_MON_PMAC)
static QDF_STATUS
dp_rx_mon_check_n_drop_mpdu(struct dp_pdev *pdev, uint32_t mac_id,
hal_rxdma_desc_t rxdma_dst_ring_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail,
uint32_t *rx_bufs_dropped)
{
return QDF_STATUS_E_FAILURE;
}
#endif
#endif
static void