diff options
author | Harout Hedeshian <harouth@codeaurora.org> | 2013-12-07 11:37:52 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:05:05 -0700 |
commit | 330c4cad0c49ca2daaaf69e285e185a1bbf0aa0a (patch) | |
tree | 50a3e520d46d1e619435eaae47ef5a0c5197d633 /net/rmnet_data | |
parent | 8ae46d64429483eb399a9abfacd6517366c861e6 (diff) |
net: rmnet_data: Enhanced counters
Added performance counters to various key places in RmNet Data
data path.
CRs-Fixed: 600629
Change-Id: Iba50c86665e181e09525e9538a540e09e526e16f
Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
Diffstat (limited to 'net/rmnet_data')
-rw-r--r-- | net/rmnet_data/Makefile | 1 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_data_handlers.c | 31 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_data_stats.c | 100 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_data_stats.h | 56 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_data_vnd.c | 3 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_map_command.c | 5 | ||||
-rw-r--r-- | net/rmnet_data/rmnet_map_data.c | 29 |
7 files changed, 201 insertions, 24 deletions
diff --git a/net/rmnet_data/Makefile b/net/rmnet_data/Makefile index 5841495a1711..6422e33fda03 100644 --- a/net/rmnet_data/Makefile +++ b/net/rmnet_data/Makefile @@ -8,4 +8,5 @@ rmnet_data-y += rmnet_data_vnd.o rmnet_data-y += rmnet_data_handlers.o rmnet_data-y += rmnet_map_data.o rmnet_data-y += rmnet_map_command.o +rmnet_data-y += rmnet_data_stats.o obj-$(CONFIG_RMNET_DATA) += rmnet_data.o diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c index e5912d6da3ca..505e615ba524 100644 --- a/net/rmnet_data/rmnet_data_handlers.c +++ b/net/rmnet_data/rmnet_data_handlers.c @@ -22,6 +22,7 @@ #include "rmnet_data_config.h" #include "rmnet_data_vnd.h" #include "rmnet_map.h" +#include "rmnet_data_stats.h" RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_HANDLER); @@ -149,7 +150,7 @@ static rx_handler_result_t rmnet_bridge_handler(struct sk_buff *skb, if (!ep->egress_dev) { LOGD("Missing egress device for packet arriving on %s", skb->dev->name); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_BRDG_NO_EGRESS); } else { rmnet_egress_handler(skb, ep); } @@ -193,7 +194,7 @@ static rx_handler_result_t __rmnet_deliver_skb(struct sk_buff *skb, default: LOGD("Unkown ep mode %d", ep->rmnet_mode); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_DELIVER_NO_EP); return RX_HANDLER_CONSUMED; } } @@ -220,7 +221,7 @@ static rx_handler_result_t rmnet_ingress_deliver_packet(struct sk_buff *skb, if (!(config->local_ep.refcount)) { LOGD("Packet on %s has no local endpoint configuration", skb->dev->name); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_IPINGRESS_NO_EP); return RX_HANDLER_CONSUMED; } @@ -258,7 +259,7 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, if (mux_id >= RMNET_DATA_MAX_LOGICAL_EP) { LOGD("Got packet on %s with bad mux id %d", skb->dev->name, mux_id); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPINGRESS_BAD_MUX); return RX_HANDLER_CONSUMED; } @@ -268,8 +269,8 @@ static rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, LOGD("Packet on %s:%d; has no logical endpoint config", skb->dev->name, mux_id); - kfree_skb(skb); - return RX_HANDLER_CONSUMED; + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP); + return RX_HANDLER_CONSUMED; } if (config->ingress_data_format & RMNET_INGRESS_FORMAT_DEMUXING) @@ -305,11 +306,12 @@ static rx_handler_result_t rmnet_map_ingress_handler(struct sk_buff *skb, if (config->ingress_data_format & RMNET_INGRESS_FORMAT_DEAGGREGATION) { while ((skbn = rmnet_map_deaggregate(skb, config)) != 0) { - LOGD("co=%d", co); _rmnet_map_ingress_handler(skbn, config); co++; } - kfree_skb(skb); + LOGD("De-aggregated %d packets", co); + rmnet_stats_deagg_pkts(co); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPINGRESS_AGGBUF); rc = RX_HANDLER_CONSUMED; } else { rc = _rmnet_map_ingress_handler(skb, config); @@ -431,7 +433,8 @@ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb) } else { LOGM("MAP command packet on %s; %s", dev->name, "Not configured for MAP commands"); - kfree_skb(skb); + rmnet_kfree_skb(skb, + RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPC); return RX_HANDLER_CONSUMED; } } else { @@ -446,7 +449,8 @@ rx_handler_result_t rmnet_ingress_handler(struct sk_buff *skb) } else { LOGD("MAP packet on %s; MAP not set", dev->name); - kfree_skb(skb); + rmnet_kfree_skb(skb, + RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPD); rc = RX_HANDLER_CONSUMED; } break; @@ -497,6 +501,7 @@ void rmnet_egress_handler(struct sk_buff *skb, { struct rmnet_phys_ep_conf_s *config; struct net_device *orig_dev; + int rc; orig_dev = skb->dev; skb->dev = ep->egress_dev; @@ -524,7 +529,7 @@ void rmnet_egress_handler(struct sk_buff *skb, default: LOGD("MAP egress failed on packet on %s", skb->dev->name); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_EGR_MAPFAIL); return; } } @@ -533,8 +538,10 @@ void rmnet_egress_handler(struct sk_buff *skb, rmnet_vnd_tx_fixup(skb, orig_dev); rmnet_print_packet(skb, skb->dev->name, 't'); - if (dev_queue_xmit(skb) != 0) { + rc = dev_queue_xmit(skb); + if (rc != 0) { LOGD("Failed to queue packet for transmission on [%s]", skb->dev->name); } + rmnet_stats_queue_xmit(rc, RMNET_STATS_QUEUE_XMIT_EGRESS); } diff --git a/net/rmnet_data/rmnet_data_stats.c b/net/rmnet_data/rmnet_data_stats.c new file mode 100644 index 000000000000..7643cb6aea0e --- /dev/null +++ b/net/rmnet_data/rmnet_data_stats.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * RMNET Data statistics + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include "rmnet_data_private.h" +#include "rmnet_data_stats.h" + +enum rmnet_deagg_e { + RMNET_STATS_AGG_BUFF, + RMNET_STATS_AGG_PKT, + RMNET_STATS_AGG_MAX +}; + +static DEFINE_SPINLOCK(rmnet_skb_free_lock); +unsigned long int skb_free[RMNET_STATS_SKBFREE_MAX]; +module_param_array(skb_free, ulong, 0, S_IRUGO); +MODULE_PARM_DESC(skb_free, "SKBs dropped or freed"); + +static DEFINE_SPINLOCK(rmnet_queue_xmit_lock); +unsigned long int queue_xmit[RMNET_STATS_QUEUE_XMIT_MAX*2]; +module_param_array(queue_xmit, ulong, 0, S_IRUGO); +MODULE_PARM_DESC(queue_xmit, "SKBs queued"); + +static DEFINE_SPINLOCK(rmnet_deagg_count); +unsigned long int deagg_count[RMNET_STATS_AGG_MAX]; +module_param_array(deagg_count, ulong, 0, S_IRUGO); +MODULE_PARM_DESC(deagg_count, "SKBs queued"); + +static DEFINE_SPINLOCK(rmnet_agg_count); +unsigned long int agg_count[RMNET_STATS_AGG_MAX]; +module_param_array(agg_count, ulong, 0, S_IRUGO); +MODULE_PARM_DESC(agg_count, "SKBs queued"); + +void rmnet_kfree_skb(struct sk_buff *skb, unsigned int reason) +{ + unsigned long flags; + + if (reason >= RMNET_STATS_SKBFREE_MAX) + reason = RMNET_STATS_SKBFREE_UNKNOWN; + + spin_lock_irqsave(&rmnet_skb_free_lock, flags); + skb_free[reason]++; + spin_unlock_irqrestore(&rmnet_skb_free_lock, flags); + + if (skb) + kfree_skb(skb); +} + +void rmnet_stats_queue_xmit(int rc, unsigned int reason) +{ + unsigned long flags; + + if (rc != 0) + reason += RMNET_STATS_QUEUE_XMIT_MAX; + if (reason >= RMNET_STATS_QUEUE_XMIT_MAX*2) + reason = RMNET_STATS_SKBFREE_UNKNOWN; + + spin_lock_irqsave(&rmnet_queue_xmit_lock, flags); + queue_xmit[reason]++; + spin_unlock_irqrestore(&rmnet_queue_xmit_lock, flags); +} + +void rmnet_stats_agg_pkts(int aggcount) +{ + unsigned long flags; + + spin_lock_irqsave(&rmnet_agg_count, flags); + agg_count[RMNET_STATS_AGG_BUFF]++; + agg_count[RMNET_STATS_AGG_PKT] += aggcount; + spin_unlock_irqrestore(&rmnet_agg_count, flags); +} + +void rmnet_stats_deagg_pkts(int aggcount) +{ + unsigned long flags; + + spin_lock_irqsave(&rmnet_deagg_count, flags); + deagg_count[RMNET_STATS_AGG_BUFF]++; + deagg_count[RMNET_STATS_AGG_PKT] += aggcount; + spin_unlock_irqrestore(&rmnet_deagg_count, flags); +} + diff --git a/net/rmnet_data/rmnet_data_stats.h b/net/rmnet_data/rmnet_data_stats.h new file mode 100644 index 000000000000..6b5ec1f84c35 --- /dev/null +++ b/net/rmnet_data/rmnet_data_stats.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * RMNET Data statistics + * + */ + +#ifndef _RMNET_DATA_STATS_H_ +#define _RMNET_DATA_STATS_H_ + +enum rmnet_skb_free_e { + RMNET_STATS_SKBFREE_UNKNOWN, + RMNET_STATS_SKBFREE_BRDG_NO_EGRESS, + RMNET_STATS_SKBFREE_DELIVER_NO_EP, + RMNET_STATS_SKBFREE_IPINGRESS_NO_EP, + RMNET_STATS_SKBFREE_MAPINGRESS_BAD_MUX, + RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP, + RMNET_STATS_SKBFREE_MAPINGRESS_AGGBUF, + RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPD, + RMNET_STATS_SKBFREE_INGRESS_NOT_EXPECT_MAPC, + RMNET_STATS_SKBFREE_EGR_MAPFAIL, + RMNET_STATS_SKBFREE_VND_NO_EGRESS, + RMNET_STATS_SKBFREE_MAPC_BAD_MUX, + RMNET_STATS_SKBFREE_MAPC_MUX_NO_EP, + RMNET_STATS_SKBFREE_AGG_CPY_EXPAND, + RMNET_STATS_SKBFREE_AGG_INTO_BUFF, + RMNET_STATS_SKBFREE_DEAGG_MALFORMED, + RMNET_STATS_SKBFREE_DEAGG_CLONE_FAIL, + RMNET_STATS_SKBFREE_DEAGG_UNKOWN_IP_TYP, + RMNET_STATS_SKBFREE_MAX +}; + +enum rmnet_queue_xmit_e { + RMNET_STATS_QUEUE_XMIT_UNKNOWN, + RMNET_STATS_QUEUE_XMIT_EGRESS, + RMNET_STATS_QUEUE_XMIT_AGG_FILL_BUFFER, + RMNET_STATS_QUEUE_XMIT_AGG_TIMEOUT, + RMNET_STATS_QUEUE_XMIT_AGG_CPY_EXP_FAIL, + RMNET_STATS_QUEUE_XMIT_MAX +}; + +void rmnet_kfree_skb(struct sk_buff *skb, unsigned int reason); +void rmnet_stats_queue_xmit(int rc, unsigned int reason); +void rmnet_stats_deagg_pkts(int aggcount); +void rmnet_stats_agg_pkts(int aggcount); +#endif /* _RMNET_DATA_STATS_H_ */ diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 76e111c17919..4bb97d72b4c8 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -28,6 +28,7 @@ #include "rmnet_data_private.h" #include "rmnet_map.h" #include "rmnet_data_vnd.h" +#include "rmnet_data_stats.h" RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_VND); @@ -177,7 +178,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, rmnet_egress_handler(skb, &dev_conf->local_ep); } else { dev->stats.tx_dropped++; - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_VND_NO_EGRESS); } return NETDEV_TX_OK; } diff --git a/net/rmnet_data/rmnet_map_command.c b/net/rmnet_data/rmnet_map_command.c index 56ac41312525..32326ea88a1b 100644 --- a/net/rmnet_data/rmnet_map_command.c +++ b/net/rmnet_data/rmnet_map_command.c @@ -21,6 +21,7 @@ #include "rmnet_map.h" #include "rmnet_data_private.h" #include "rmnet_data_vnd.h" +#include "rmnet_data_stats.h" RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_MAPC); @@ -63,7 +64,7 @@ static uint8_t rmnet_map_do_flow_control(struct sk_buff *skb, if (mux_id >= RMNET_DATA_MAX_LOGICAL_EP) { LOGD("Got packet on %s with bad mux id %d", skb->dev->name, mux_id); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPC_BAD_MUX); return RX_HANDLER_CONSUMED; } @@ -73,7 +74,7 @@ static uint8_t rmnet_map_do_flow_control(struct sk_buff *skb, LOGD("Packet on %s:%d; has no logical endpoint config", skb->dev->name, mux_id); - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPC_MUX_NO_EP); return RX_HANDLER_CONSUMED; } diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c index b39f906dcaac..0e588398409a 100644 --- a/net/rmnet_data/rmnet_map_data.c +++ b/net/rmnet_data/rmnet_map_data.c @@ -24,6 +24,7 @@ #include "rmnet_data_config.h" #include "rmnet_map.h" #include "rmnet_data_private.h" +#include "rmnet_data_stats.h" RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_MAPD); @@ -128,7 +129,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, ip_byte = (skbn->data[4]) & 0xF0; if (ip_byte != 0x40 && ip_byte != 0x60) { LOGM("Unknown IP type: 0x%02X", ip_byte); - kfree_skb(skbn); + rmnet_kfree_skb(skbn, RMNET_STATS_SKBFREE_DEAGG_UNKOWN_IP_TYP); return 0; } @@ -150,6 +151,7 @@ static void rmnet_map_flush_packet_queue(struct work_struct *work) struct rmnet_phys_ep_conf_s *config; unsigned long flags; struct sk_buff *skb; + int rc; skb = 0; real_work = (struct agg_work *)work; @@ -157,8 +159,9 @@ static void rmnet_map_flush_packet_queue(struct work_struct *work) LOGD("%s", "Entering flush thread"); spin_lock_irqsave(&config->agg_lock, flags); if (likely(config->agg_state == RMNET_MAP_TXFER_SCHEDULED)) { + /* Buffer may have already been shipped out */ if (likely(config->agg_skb)) { - /* Buffer may have already been shipped out */ + rmnet_stats_agg_pkts(config->agg_count); if (config->agg_count > 1) LOGL("Agg count: %d", config->agg_count); skb = config->agg_skb; @@ -172,8 +175,10 @@ static void rmnet_map_flush_packet_queue(struct work_struct *work) } spin_unlock_irqrestore(&config->agg_lock, flags); - if (skb) - dev_queue_xmit(skb); + if (skb) { + rc = dev_queue_xmit(skb); + rmnet_stats_queue_xmit(rc, RMNET_STATS_QUEUE_XMIT_AGG_TIMEOUT); + } kfree(work); } @@ -192,7 +197,7 @@ void rmnet_map_aggregate(struct sk_buff *skb, struct agg_work *work; unsigned long flags; struct sk_buff *agg_skb; - int size; + int size, rc; if (!skb || !config) @@ -212,29 +217,35 @@ new_packet: config->agg_skb = 0; config->agg_count = 0; spin_unlock_irqrestore(&config->agg_lock, flags); - dev_queue_xmit(skb); + rmnet_stats_agg_pkts(1); + rc = dev_queue_xmit(skb); + rmnet_stats_queue_xmit(rc, + RMNET_STATS_QUEUE_XMIT_AGG_CPY_EXP_FAIL); return; } config->agg_count = 1; - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_CPY_EXPAND); goto schedule; } if (skb->len > (config->egress_agg_size - config->agg_skb->len)) { + rmnet_stats_agg_pkts(config->agg_count); if (config->agg_count > 1) LOGL("Agg count: %d", config->agg_count); agg_skb = config->agg_skb; config->agg_skb = 0; config->agg_count = 0; spin_unlock_irqrestore(&config->agg_lock, flags); - dev_queue_xmit(agg_skb); + rc = dev_queue_xmit(agg_skb); + rmnet_stats_queue_xmit(rc, + RMNET_STATS_QUEUE_XMIT_AGG_FILL_BUFFER); goto new_packet; } dest_buff = skb_put(config->agg_skb, skb->len); memcpy(dest_buff, skb->data, skb->len); config->agg_count++; - kfree_skb(skb); + rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_INTO_BUFF); schedule: if (config->agg_state != RMNET_MAP_TXFER_SCHEDULED) { |