]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * Data gathering module for Linux-VM Monitor Stream, Stage 1. |
3 | * Collects accumulated network statistics (Packets received/transmitted, | |
4 | * dropped, errors, ...). | |
5 | * | |
a53c8fab | 6 | * Copyright IBM Corp. 2003, 2006 |
1da177e4 | 7 | * |
5b5dd21a | 8 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
1da177e4 LT |
9 | */ |
10 | ||
1da177e4 LT |
11 | #include <linux/module.h> |
12 | #include <linux/init.h> | |
1da177e4 LT |
13 | #include <linux/errno.h> |
14 | #include <linux/kernel_stat.h> | |
15 | #include <linux/netdevice.h> | |
881d966b | 16 | #include <net/net_namespace.h> |
1da177e4 LT |
17 | |
18 | #include "appldata.h" | |
19 | ||
20 | ||
1da177e4 LT |
21 | /* |
22 | * Network data | |
23 | * | |
24 | * This is accessed as binary data by z/VM. If changes to it can't be avoided, | |
25 | * the structure version (product ID, see appldata_base.c) needs to be changed | |
26 | * as well and all documentation and z/VM applications using it must be updated. | |
27 | * | |
28 | * The record layout is documented in the Linux for zSeries Device Drivers | |
29 | * book: | |
30 | * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml | |
31 | */ | |
2ab14619 | 32 | struct appldata_net_sum_data { |
1da177e4 LT |
33 | u64 timestamp; |
34 | u32 sync_count_1; /* after VM collected the record data, */ | |
35 | u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the | |
36 | same. If not, the record has been updated on | |
37 | the Linux side while VM was collecting the | |
38 | (possibly corrupt) data */ | |
39 | ||
40 | u32 nr_interfaces; /* nr. of network interfaces being monitored */ | |
41 | ||
42 | u32 padding; /* next value is 64-bit aligned, so these */ | |
43 | /* 4 byte would be padded out by compiler */ | |
44 | ||
45 | u64 rx_packets; /* total packets received */ | |
46 | u64 tx_packets; /* total packets transmitted */ | |
47 | u64 rx_bytes; /* total bytes received */ | |
48 | u64 tx_bytes; /* total bytes transmitted */ | |
49 | u64 rx_errors; /* bad packets received */ | |
50 | u64 tx_errors; /* packet transmit problems */ | |
51 | u64 rx_dropped; /* no space in linux buffers */ | |
52 | u64 tx_dropped; /* no space available in linux */ | |
53 | u64 collisions; /* collisions while transmitting */ | |
2ab14619 | 54 | } __packed; |
1da177e4 LT |
55 | |
56 | ||
1da177e4 LT |
57 | /* |
58 | * appldata_get_net_sum_data() | |
59 | * | |
60 | * gather accumulated network statistics | |
61 | */ | |
62 | static void appldata_get_net_sum_data(void *data) | |
63 | { | |
64 | int i; | |
65 | struct appldata_net_sum_data *net_data; | |
66 | struct net_device *dev; | |
1da177e4 LT |
67 | unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes, rx_errors, |
68 | tx_errors, rx_dropped, tx_dropped, collisions; | |
69 | ||
70 | net_data = data; | |
71 | net_data->sync_count_1++; | |
72 | ||
73 | i = 0; | |
74 | rx_packets = 0; | |
75 | tx_packets = 0; | |
76 | rx_bytes = 0; | |
77 | tx_bytes = 0; | |
78 | rx_errors = 0; | |
79 | tx_errors = 0; | |
80 | rx_dropped = 0; | |
81 | tx_dropped = 0; | |
82 | collisions = 0; | |
e576b9ef | 83 | |
84 | rcu_read_lock(); | |
85 | for_each_netdev_rcu(&init_net, dev) { | |
e402e38c | 86 | const struct rtnl_link_stats64 *stats; |
28172739 | 87 | struct rtnl_link_stats64 temp; |
eeda3fd6 | 88 | |
e402e38c | 89 | stats = dev_get_stats(dev, &temp); |
1da177e4 LT |
90 | rx_packets += stats->rx_packets; |
91 | tx_packets += stats->tx_packets; | |
92 | rx_bytes += stats->rx_bytes; | |
93 | tx_bytes += stats->tx_bytes; | |
94 | rx_errors += stats->rx_errors; | |
95 | tx_errors += stats->tx_errors; | |
96 | rx_dropped += stats->rx_dropped; | |
97 | tx_dropped += stats->tx_dropped; | |
98 | collisions += stats->collisions; | |
99 | i++; | |
100 | } | |
e576b9ef | 101 | rcu_read_unlock(); |
102 | ||
1da177e4 LT |
103 | net_data->nr_interfaces = i; |
104 | net_data->rx_packets = rx_packets; | |
105 | net_data->tx_packets = tx_packets; | |
106 | net_data->rx_bytes = rx_bytes; | |
107 | net_data->tx_bytes = tx_bytes; | |
108 | net_data->rx_errors = rx_errors; | |
109 | net_data->tx_errors = tx_errors; | |
110 | net_data->rx_dropped = rx_dropped; | |
111 | net_data->tx_dropped = tx_dropped; | |
112 | net_data->collisions = collisions; | |
113 | ||
1aae0560 | 114 | net_data->timestamp = get_tod_clock(); |
1da177e4 | 115 | net_data->sync_count_2++; |
1da177e4 LT |
116 | } |
117 | ||
118 | ||
119 | static struct appldata_ops ops = { | |
1da177e4 LT |
120 | .name = "net_sum", |
121 | .record_nr = APPLDATA_RECORD_NET_SUM_ID, | |
122 | .size = sizeof(struct appldata_net_sum_data), | |
123 | .callback = &appldata_get_net_sum_data, | |
1da177e4 | 124 | .owner = THIS_MODULE, |
5b5dd21a | 125 | .mod_lvl = {0xF0, 0xF0}, /* EBCDIC "00" */ |
1da177e4 LT |
126 | }; |
127 | ||
128 | ||
129 | /* | |
130 | * appldata_net_init() | |
131 | * | |
132 | * init data, register ops | |
133 | */ | |
134 | static int __init appldata_net_init(void) | |
135 | { | |
2ab14619 SO |
136 | int ret; |
137 | ||
138 | ops.data = kzalloc(sizeof(struct appldata_net_sum_data), GFP_KERNEL); | |
139 | if (!ops.data) | |
140 | return -ENOMEM; | |
141 | ||
142 | ret = appldata_register_ops(&ops); | |
143 | if (ret) | |
144 | kfree(ops.data); | |
145 | ||
146 | return ret; | |
1da177e4 LT |
147 | } |
148 | ||
149 | /* | |
150 | * appldata_net_exit() | |
151 | * | |
152 | * unregister ops | |
153 | */ | |
154 | static void __exit appldata_net_exit(void) | |
155 | { | |
156 | appldata_unregister_ops(&ops); | |
2ab14619 | 157 | kfree(ops.data); |
1da177e4 LT |
158 | } |
159 | ||
160 | ||
161 | module_init(appldata_net_init); | |
162 | module_exit(appldata_net_exit); | |
163 | ||
164 | MODULE_LICENSE("GPL"); | |
165 | MODULE_AUTHOR("Gerald Schaefer"); | |
166 | MODULE_DESCRIPTION("Linux-VM Monitor Stream, accumulated network statistics"); |