1 /**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
10 #include "gator.h"
11 #include <linux/netdevice.h>
12 #include <linux/hardirq.h>
14 #define NETRX 0
15 #define NETTX 1
16 #define TOTALNET 2
18 static ulong netrx_enabled;
19 static ulong nettx_enabled;
20 static ulong netrx_key;
21 static ulong nettx_key;
22 static int rx_total, tx_total;
23 static ulong netPrev[TOTALNET];
24 static int netGet[TOTALNET * 4];
26 static void get_network_stats(struct work_struct *wsptr) {
27 int rx = 0, tx = 0;
28 struct net_device *dev;
30 for_each_netdev(&init_net, dev) {
31 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
32 const struct net_device_stats *stats = dev_get_stats(dev);
33 #else
34 struct rtnl_link_stats64 temp;
35 const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
36 #endif
37 rx += stats->rx_bytes;
38 tx += stats->tx_bytes;
39 }
40 rx_total = rx;
41 tx_total = tx;
42 }
43 DECLARE_WORK(wq_get_stats, get_network_stats);
45 static void calculate_delta(int *rx, int *tx)
46 {
47 int rx_calc, tx_calc;
49 rx_calc = (int)(rx_total - netPrev[NETRX]);
50 if (rx_calc < 0)
51 rx_calc = 0;
52 netPrev[NETRX] += rx_calc;
54 tx_calc = (int)(tx_total - netPrev[NETTX]);
55 if (tx_calc < 0)
56 tx_calc = 0;
57 netPrev[NETTX] += tx_calc;
59 *rx = rx_calc;
60 *tx = tx_calc;
61 }
63 static int gator_events_net_create_files(struct super_block *sb, struct dentry *root)
64 {
65 struct dentry *dir;
67 dir = gatorfs_mkdir(sb, root, "Linux_net_rx");
68 if (!dir) {
69 return -1;
70 }
71 gatorfs_create_ulong(sb, dir, "enabled", &netrx_enabled);
72 gatorfs_create_ro_ulong(sb, dir, "key", &netrx_key);
74 dir = gatorfs_mkdir(sb, root, "Linux_net_tx");
75 if (!dir) {
76 return -1;
77 }
78 gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled);
79 gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key);
81 return 0;
82 }
84 static int gator_events_net_start(void)
85 {
86 get_network_stats(NULL);
87 netPrev[NETRX] = rx_total;
88 netPrev[NETTX] = tx_total;
89 return 0;
90 }
92 static void gator_events_net_stop(void)
93 {
94 netrx_enabled = 0;
95 nettx_enabled = 0;
96 }
98 static int gator_events_net_read(int **buffer)
99 {
100 int len, rx_delta, tx_delta;
101 static int last_rx_delta = 0, last_tx_delta = 0;
103 if (smp_processor_id() != 0)
104 return 0;
106 if (!netrx_enabled && !nettx_enabled)
107 return 0;
109 if (in_interrupt()){
110 schedule_work(&wq_get_stats);
111 } else {
112 get_network_stats(NULL);
113 }
115 calculate_delta(&rx_delta, &tx_delta);
117 len = 0;
118 if (netrx_enabled && last_rx_delta != rx_delta) {
119 last_rx_delta = rx_delta;
120 netGet[len++] = netrx_key;
121 netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message
122 netGet[len++] = netrx_key;
123 netGet[len++] = rx_delta;
124 }
126 if (nettx_enabled && last_tx_delta != tx_delta) {
127 last_tx_delta = tx_delta;
128 netGet[len++] = nettx_key;
129 netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message
130 netGet[len++] = nettx_key;
131 netGet[len++] = tx_delta;
132 }
134 if (buffer)
135 *buffer = netGet;
137 return len;
138 }
140 static struct gator_interface gator_events_net_interface = {
141 .create_files = gator_events_net_create_files,
142 .start = gator_events_net_start,
143 .stop = gator_events_net_stop,
144 .read = gator_events_net_read,
145 };
147 int gator_events_net_init(void)
148 {
149 netrx_key = gator_events_get_key();
150 nettx_key = gator_events_get_key();
152 netrx_enabled = 0;
153 nettx_enabled = 0;
155 return gator_events_install(&gator_events_net_interface);
156 }
157 gator_events_init(gator_events_net_init);