summaryrefslogtreecommitdiff
path: root/net/rmnet_data
diff options
context:
space:
mode:
authorHarout Hedeshian <harouth@codeaurora.org>2013-12-07 11:37:52 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:05:05 -0700
commit330c4cad0c49ca2daaaf69e285e185a1bbf0aa0a (patch)
tree50a3e520d46d1e619435eaae47ef5a0c5197d633 /net/rmnet_data
parent8ae46d64429483eb399a9abfacd6517366c861e6 (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/Makefile1
-rw-r--r--net/rmnet_data/rmnet_data_handlers.c31
-rw-r--r--net/rmnet_data/rmnet_data_stats.c100
-rw-r--r--net/rmnet_data/rmnet_data_stats.h56
-rw-r--r--net/rmnet_data/rmnet_data_vnd.c3
-rw-r--r--net/rmnet_data/rmnet_map_command.c5
-rw-r--r--net/rmnet_data/rmnet_map_data.c29
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) {