From 0bd967d0215cd51a282294ac57e1cdf47aa96ef9 Mon Sep 17 00:00:00 2001 From: Neil Zhao Date: Fri, 2 Mar 2018 16:00:00 -0800 Subject: [PATCH] qcacmn: fix mon vap RX skb size issues 1) for raw mode, drop frames with invalid size 2) for non-raw mode, fixed issue that frag list data_len's not properly calculated The length issues will introduce kernel issues during skb_linearize() at upper OS network stack layer. Symptoms: 1) WARNING: at net/core/skbuff.c:1782 PC is at skb_copy_bits+0x1b8/0x230 2) kernel BU at net/core/skbuff.c:1615! PC is at __pskb_pull_tail+0x70/0x2e4 CRs-fixed: 2188754 Change-Id: I848ec976cd922708ffd02d8272ea5a6f3bce2a00 --- dp/inc/cdp_txrx_stats_struct.h | 2 ++ dp/wifi3.0/dp_main.c | 2 ++ dp/wifi3.0/dp_rx_mon_dest.c | 12 ++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index b7dc239264..aacdedd06e 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -742,6 +742,8 @@ struct cdp_pdev_stats { uint32_t mec; /* Mesh Filtered packets */ uint32_t mesh_filter; + /* packets dropped on monitor vap */ + uint32_t mon_rx_drop; } dropped; struct { diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 506ec73847..c813f53f36 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4800,6 +4800,8 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev) DP_PRINT_STATS("Dropped:"); DP_PRINT_STATS(" msdu_not_done = %d", pdev->stats.dropped.msdu_not_done); + DP_PRINT_STATS(" mon_rx_drop = %d", + pdev->stats.dropped.mon_rx_drop); DP_PRINT_STATS("Sent To Stack:"); DP_PRINT_STATS(" Packets = %d", pdev->stats.rx.to_stack.num); diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index 3b9a07dfa5..4cff55ca76 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -26,6 +26,7 @@ #include "hal_api_mon.h" #include "dp_rx_mon.h" #include "wlan_cfg.h" +#include "dp_internal.h" /** * dp_rx_mon_link_desc_return() - Return a MPDU link descriptor to HW @@ -374,7 +375,8 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, if (HAL_RX_DESC_GET_MPDU_LENGTH_ERR(rx_desc)) { /* It looks like there is some issue on MPDU len err */ /* Need further investigate if drop the packet */ - /* return NULL; */ + DP_STATS_INC(dp_pdev, dropped.mon_rx_drop, 1); + return NULL; } rx_desc = qdf_nbuf_data(last_msdu); @@ -439,6 +441,11 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, /* If there were more fragments to this RAW frame */ if (head_frag_list) { + if (frag_list_sum_len < + sizeof(struct ieee80211_frame_min_one)) { + DP_STATS_INC(dp_pdev, dropped.mon_rx_drop, 1); + return NULL; + } frag_list_sum_len -= HAL_RX_FCS_LEN; qdf_nbuf_append_ext_list(mpdu_buf, head_frag_list, frag_list_sum_len); @@ -535,7 +542,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, /* The first LLC len is copied into the MPDU buffer */ frag_list_sum_len = 0; - frag_list_sum_len -= msdu_llc_len; msdu_orig = head_msdu; is_first_frag = 1; @@ -599,6 +605,8 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, frag_list_sum_len += HAL_RX_FCS_LEN; #endif + frag_list_sum_len -= msdu_llc_len; + /* TODO: Convert this to suitable adf routines */ qdf_nbuf_append_ext_list(mpdu_buf, head_frag_list, frag_list_sum_len);