qcacld-3.0: Add LRO Statistics

Add the following statistics for LRO
- packet count based on the number of packets aggregated
- total number of LRO eligible and ineligible TCP packets
- total number of packets aggregated
- total number of flows flushed
- number of times an LRO descriptor was not found

Change-Id: Icea6b7745df9bda5b517c1a7f27c8395ede2cec6
CRs-Fixed: 1042116
This commit is contained in:
Dhanashri Atre
2016-07-14 18:20:29 -07:00
committed by qcabuildsw
parent 3de9e373c9
commit e7d442a315
4 changed files with 172 additions and 2 deletions

View File

@@ -69,6 +69,7 @@
#define WLAN_DUMP_TX_FLOW_POOL_INFO 5 #define WLAN_DUMP_TX_FLOW_POOL_INFO 5
#define WLAN_TXRX_DESC_STATS 6 #define WLAN_TXRX_DESC_STATS 6
#define WLAN_HIF_STATS 7 #define WLAN_HIF_STATS 7
#define WLAN_LRO_STATS 8
#define WLAN_SCHEDULER_STATS 21 #define WLAN_SCHEDULER_STATS 21
#define WLAN_TX_QUEUE_STATS 22 #define WLAN_TX_QUEUE_STATS 22
#define WLAN_BUNDLE_STATS 23 #define WLAN_BUNDLE_STATS 23

View File

@@ -97,16 +97,62 @@ struct hdd_lro_desc_info {
struct hdd_lro_desc_pool lro_desc_pool; struct hdd_lro_desc_pool lro_desc_pool;
}; };
/**
* enum hdd_lro_pkt_aggr_bucket - idenitifies the bucket holding
* the count of the aggregated packets
* @HDD_LRO_BUCKET_0_7: identifies the packet count when the
* aggregate size is between 0 to 7 packets
* @HDD_LRO_BUCKET_8_15: identifies the packet count when the
* aggregate size is between 8 to 15 packets
* @HDD_LRO_BUCKET_16_23: identifies the packet count when the
* aggregate size is between 16 to 23 packets
* @HDD_LRO_BUCKET_24_31: identifies the packet count when the
* aggregate size is between 24 to 31 packets
* @HDD_LRO_BUCKET_32_39: identifies the packet count when the
* aggregate size is between 32 to 39 packets
* @HDD_LRO_BUCKET_40_47: identifies the packet count when the
* aggregate size is between 40 to 47 packets
* @HDD_LRO_BUCKET_48_OR_MORE: identifies the packet count when
* the aggregate size is 48 or more packets
* @HDD_LRO_BUCKET_MAX: identifies the packet count when the
* aggregate size is 48 or more packets
*/
enum hdd_lro_pkt_aggr_bucket {
HDD_LRO_BUCKET_0_7 = 0,
HDD_LRO_BUCKET_8_15 = 1,
HDD_LRO_BUCKET_16_23 = 2,
HDD_LRO_BUCKET_24_31 = 3,
HDD_LRO_BUCKET_32_39 = 4,
HDD_LRO_BUCKET_40_47 = 5,
HDD_LRO_BUCKET_48_OR_MORE = 6,
HDD_LRO_BUCKET_MAX = HDD_LRO_BUCKET_48_OR_MORE,
};
/**
* hdd_lro_stats - structure containing the LRO statistics
* information
* @pkt_aggr_hist: histogram of the number of aggregated packets
* @lro_eligible_tcp: number of LRO elgible TCP packets
* @lro_ineligible_tcp: number of LRO inelgible TCP packets
*/
struct hdd_lro_stats {
uint16_t pkt_aggr_hist[HDD_LRO_BUCKET_MAX + 1];
uint32_t lro_eligible_tcp;
uint32_t lro_ineligible_tcp;
};
/** /**
* hdd_lro_s - LRO information per HDD adapter * hdd_lro_s - LRO information per HDD adapter
* @lro_mgr: LRO manager * @lro_mgr: LRO manager
* @lro_desc_info: LRO descriptor information * @lro_desc_info: LRO descriptor information
* @lro_mgr_arr_access_lock: Lock to access LRO manager array. * @lro_mgr_arr_access_lock: Lock to access LRO manager array.
* @lro_stats: LRO statistics
*/ */
struct hdd_lro_s { struct hdd_lro_s {
struct net_lro_mgr *lro_mgr; struct net_lro_mgr *lro_mgr;
struct hdd_lro_desc_info lro_desc_info; struct hdd_lro_desc_info lro_desc_info;
qdf_spinlock_t lro_mgr_arr_access_lock; qdf_spinlock_t lro_mgr_arr_access_lock;
struct hdd_lro_stats lro_stats;
}; };
int hdd_lro_init(hdd_context_t *hdd_ctx); int hdd_lro_init(hdd_context_t *hdd_ctx);
@@ -121,6 +167,8 @@ enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx,
void hdd_lro_flush_all(hdd_context_t *hdd_ctx, void hdd_lro_flush_all(hdd_context_t *hdd_ctx,
hdd_adapter_t *adapter); hdd_adapter_t *adapter);
void hdd_lro_display_stats(hdd_context_t *hdd_ctx);
#else #else
struct hdd_lro_s {}; struct hdd_lro_s {};
@@ -142,6 +190,14 @@ static inline int hdd_lro_init(hdd_context_t *hdd_ctx)
} }
static inline void hdd_lro_disable(hdd_context_t *hdd_ctx, static inline void hdd_lro_disable(hdd_context_t *hdd_ctx,
hdd_adapter_t *adapter){} hdd_adapter_t *adapter)
{
return;
}
static inline void hdd_lro_display_stats(hdd_context_t *hdd_ctx)
{
return;
}
#endif /* FEATURE_LRO */ #endif /* FEATURE_LRO */
#endif /* __WLAN_HDD_LRO_H__ */ #endif /* __WLAN_HDD_LRO_H__ */

View File

@@ -53,6 +53,14 @@
(LRO_DESC | LRO_ELIGIBILITY_CHECKED | LRO_TCP_ACK_NUM | \ (LRO_DESC | LRO_ELIGIBILITY_CHECKED | LRO_TCP_ACK_NUM | \
LRO_TCP_DATA_CSUM | LRO_TCP_SEQ_NUM | LRO_TCP_WIN) LRO_TCP_DATA_CSUM | LRO_TCP_SEQ_NUM | LRO_TCP_WIN)
#define LRO_HIST_UPDATE(lro_desc, adapter) \
do { \
uint8_t bucket = lro_desc->pkt_aggr_cnt >> 3; \
if (unlikely(bucket > HDD_LRO_BUCKET_MAX)) \
bucket = HDD_LRO_BUCKET_MAX; \
adapter->lro_info.lro_stats.pkt_aggr_hist[bucket]++; \
} while (0);
/** /**
* hdd_lro_get_skb_header() - LRO callback function * hdd_lro_get_skb_header() - LRO callback function
* @skb: network buffer * @skb: network buffer
@@ -260,7 +268,7 @@ static int hdd_lro_desc_find(hdd_adapter_t *adapter,
qdf_spin_unlock_bh(&free_pool->lro_pool_lock); qdf_spin_unlock_bh(&free_pool->lro_pool_lock);
if (NULL == entry->lro_desc) { if (NULL == entry->lro_desc) {
hdd_err("entry->lro_desc is NULL!\n"); hdd_err("entry->lro_desc is NULL!");
return -EINVAL; return -EINVAL;
} }
@@ -421,6 +429,9 @@ static void hdd_lro_flush_pkt(struct net_lro_mgr *lro_mgr,
lro_desc = hdd_lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph); lro_desc = hdd_lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
if (lro_desc) { if (lro_desc) {
/* statistics */
LRO_HIST_UPDATE(lro_desc, adapter);
hdd_lro_desc_free(lro_desc, adapter); hdd_lro_desc_free(lro_desc, adapter);
lro_flush_desc(lro_mgr, lro_desc); lro_flush_desc(lro_mgr, lro_desc);
} }
@@ -474,6 +485,8 @@ static void hdd_lro_flush(void *data)
lro_flush_desc( lro_flush_desc(
hdd_lro->lro_mgr, hdd_lro->lro_mgr,
&hdd_lro->lro_mgr->lro_arr[i]); &hdd_lro->lro_mgr->lro_arr[i]);
LRO_HIST_UPDATE((&hdd_lro->lro_mgr->lro_arr[i]),
adapter);
} }
} }
qdf_spin_unlock_bh(&hdd_lro->lro_mgr_arr_access_lock); qdf_spin_unlock_bh(&hdd_lro->lro_mgr_arr_access_lock);
@@ -556,6 +569,7 @@ int hdd_lro_enable(hdd_context_t *hdd_ctx,
hdd_lro = &adapter->lro_info; hdd_lro = &adapter->lro_info;
qdf_mem_zero((void *)hdd_lro, sizeof(struct hdd_lro_s)); qdf_mem_zero((void *)hdd_lro, sizeof(struct hdd_lro_s));
/* /*
* Allocate all the LRO data structures at once and then carve * Allocate all the LRO data structures at once and then carve
* them up as needed * them up as needed
@@ -693,12 +707,107 @@ enum hdd_lro_rx_status hdd_lro_rx(hdd_context_t *hdd_ctx,
} }
status = HDD_LRO_RX; status = HDD_LRO_RX;
adapter->lro_info.lro_stats.lro_eligible_tcp++;
} else { } else {
hdd_lro_flush_pkt(adapter->lro_info.lro_mgr, hdd_lro_flush_pkt(adapter->lro_info.lro_mgr,
iph, tcph, adapter); iph, tcph, adapter);
adapter->lro_info.lro_stats.lro_ineligible_tcp++;
} }
qdf_spin_unlock_bh( qdf_spin_unlock_bh(
&hdd_lro->lro_mgr_arr_access_lock); &hdd_lro->lro_mgr_arr_access_lock);
} }
return status; return status;
} }
/**
* hdd_lro_bucket_to_string() - return string conversion of
* bucket
* @bucket: bucket
*
* This utility function helps log string conversion of bucket
* enum
*
* Return: string conversion of the LRO bucket, if match found;
* "Invalid" otherwise.
*/
static const char *hdd_lro_bucket_to_string(enum hdd_lro_pkt_aggr_bucket bucket)
{
switch (bucket) {
CASE_RETURN_STRING(HDD_LRO_BUCKET_0_7);
CASE_RETURN_STRING(HDD_LRO_BUCKET_8_15);
CASE_RETURN_STRING(HDD_LRO_BUCKET_16_23);
CASE_RETURN_STRING(HDD_LRO_BUCKET_24_31);
CASE_RETURN_STRING(HDD_LRO_BUCKET_32_39);
CASE_RETURN_STRING(HDD_LRO_BUCKET_40_47);
CASE_RETURN_STRING(HDD_LRO_BUCKET_48_OR_MORE);
default:
return "Invalid";
}
}
/**
* wlan_hdd_display_lro_stats() - display LRO statistics
* @hdd_ctx: hdd context
*
* Return: none
*/
void hdd_lro_display_stats(hdd_context_t *hdd_ctx)
{
hdd_adapter_t *adapter = NULL;
hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
QDF_STATUS status;
int i;
if (!hdd_ctx->config->lro_enable) {
hdd_err("LRO Disabled");
return;
}
status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
struct hdd_lro_stats *stats;
hdd_err("\nLRO statistics:");
adapter = adapter_node->pAdapter;
if (!adapter) {
status = hdd_get_next_adapter(hdd_ctx,
adapter_node, &next);
adapter_node = next;
continue;
}
stats = &adapter->lro_info.lro_stats;
hdd_err("Session_id %d device mode %d",
adapter->sessionId, adapter->device_mode);
if (NL80211_IFTYPE_STATION != adapter->wdev.iftype) {
hdd_err("No LRO on interface type %d",
adapter->wdev.iftype);
status = hdd_get_next_adapter(hdd_ctx,
adapter_node, &next);
adapter_node = next;
continue;
}
for (i = 0; i <= HDD_LRO_BUCKET_MAX; i++) {
if (stats && stats->pkt_aggr_hist)
hdd_err("bucket %s: %d packets",
hdd_lro_bucket_to_string(i),
stats->pkt_aggr_hist[i]);
}
hdd_err("LRO eligible TCP packets %d\n"
"LRO ineligible TCP packets %d",
stats->lro_eligible_tcp, stats->lro_ineligible_tcp);
if (adapter->lro_info.lro_mgr)
hdd_err("LRO manager aggr %lu flushed %lu no desc %lu",
adapter->lro_info.lro_mgr->stats.aggregated,
adapter->lro_info.lro_mgr->stats.flushed,
adapter->lro_info.lro_mgr->stats.no_desc);
status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
adapter_node = next;
}
}

View File

@@ -94,6 +94,7 @@
#include "hif.h" #include "hif.h"
#include "pld_common.h" #include "pld_common.h"
#endif #endif
#include "wlan_hdd_lro.h"
#define HDD_FINISH_ULA_TIME_OUT 800 #define HDD_FINISH_ULA_TIME_OUT 800
#define HDD_SET_MCBC_FILTERS_TO_FW 1 #define HDD_SET_MCBC_FILTERS_TO_FW 1
@@ -720,6 +721,9 @@ void hdd_wlan_dump_stats(hdd_adapter_t *adapter, int value)
case WLAN_HIF_STATS: case WLAN_HIF_STATS:
hdd_display_hif_stats(); hdd_display_hif_stats();
break; break;
case WLAN_LRO_STATS:
hdd_lro_display_stats(hdd_ctx);
break;
default: default:
ol_txrx_display_stats(value); ol_txrx_display_stats(value);
break; break;