aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2016-03-07 17:11:07 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-09 16:36:14 -0500
commitcd6e111bf5be5c70aef96a86d791ee7be0c0e137 (patch)
tree6fcfcb85e5838ef670558ad548e27458b0df42f0
parentab7ac4eb9832e32a09f4e8042705484d2fb0aad3 (diff)
kcm: Add statistics and proc interfaces
This patch adds various counters for KCM. These include counters for messages and bytes received or sent, as well as counters for number of attached/unattached TCP sockets and other error or edge events. The statistics are exposed via a proc interface. /proc/net/kcm provides statistics per KCM socket and per psock (attached TCP sockets). /proc/net/kcm_stats provides aggregate statistics. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/kcm.h94
-rw-r--r--net/kcm/Makefile2
-rw-r--r--net/kcm/kcmproc.c422
-rw-r--r--net/kcm/kcmsock.c80
4 files changed, 597 insertions, 1 deletions
diff --git a/include/net/kcm.h b/include/net/kcm.h
index 1bcae39070ec..39c7abe98552 100644
--- a/include/net/kcm.h
+++ b/include/net/kcm.h
@@ -17,6 +17,42 @@
17 17
18extern unsigned int kcm_net_id; 18extern unsigned int kcm_net_id;
19 19
20#define KCM_STATS_ADD(stat, count) ((stat) += (count))
21#define KCM_STATS_INCR(stat) ((stat)++)
22
23struct kcm_psock_stats {
24 unsigned long long rx_msgs;
25 unsigned long long rx_bytes;
26 unsigned long long tx_msgs;
27 unsigned long long tx_bytes;
28 unsigned int rx_aborts;
29 unsigned int rx_mem_fail;
30 unsigned int rx_need_more_hdr;
31 unsigned int rx_bad_hdr_len;
32 unsigned long long reserved;
33 unsigned long long unreserved;
34 unsigned int tx_aborts;
35};
36
37struct kcm_mux_stats {
38 unsigned long long rx_msgs;
39 unsigned long long rx_bytes;
40 unsigned long long tx_msgs;
41 unsigned long long tx_bytes;
42 unsigned int rx_ready_drops;
43 unsigned int tx_retries;
44 unsigned int psock_attach;
45 unsigned int psock_unattach_rsvd;
46 unsigned int psock_unattach;
47};
48
49struct kcm_stats {
50 unsigned long long rx_msgs;
51 unsigned long long rx_bytes;
52 unsigned long long tx_msgs;
53 unsigned long long tx_bytes;
54};
55
20struct kcm_tx_msg { 56struct kcm_tx_msg {
21 unsigned int sent; 57 unsigned int sent;
22 unsigned int fragidx; 58 unsigned int fragidx;
@@ -41,6 +77,8 @@ struct kcm_sock {
41 u32 done : 1; 77 u32 done : 1;
42 struct work_struct done_work; 78 struct work_struct done_work;
43 79
80 struct kcm_stats stats;
81
44 /* Transmit */ 82 /* Transmit */
45 struct kcm_psock *tx_psock; 83 struct kcm_psock *tx_psock;
46 struct work_struct tx_work; 84 struct work_struct tx_work;
@@ -77,6 +115,8 @@ struct kcm_psock {
77 115
78 struct list_head psock_list; 116 struct list_head psock_list;
79 117
118 struct kcm_psock_stats stats;
119
80 /* Receive */ 120 /* Receive */
81 struct sk_buff *rx_skb_head; 121 struct sk_buff *rx_skb_head;
82 struct sk_buff **rx_skb_nextp; 122 struct sk_buff **rx_skb_nextp;
@@ -86,15 +126,21 @@ struct kcm_psock {
86 struct delayed_work rx_delayed_work; 126 struct delayed_work rx_delayed_work;
87 struct bpf_prog *bpf_prog; 127 struct bpf_prog *bpf_prog;
88 struct kcm_sock *rx_kcm; 128 struct kcm_sock *rx_kcm;
129 unsigned long long saved_rx_bytes;
130 unsigned long long saved_rx_msgs;
89 131
90 /* Transmit */ 132 /* Transmit */
91 struct kcm_sock *tx_kcm; 133 struct kcm_sock *tx_kcm;
92 struct list_head psock_avail_list; 134 struct list_head psock_avail_list;
135 unsigned long long saved_tx_bytes;
136 unsigned long long saved_tx_msgs;
93}; 137};
94 138
95/* Per net MUX list */ 139/* Per net MUX list */
96struct kcm_net { 140struct kcm_net {
97 struct mutex mutex; 141 struct mutex mutex;
142 struct kcm_psock_stats aggregate_psock_stats;
143 struct kcm_mux_stats aggregate_mux_stats;
98 struct list_head mux_list; 144 struct list_head mux_list;
99 int count; 145 int count;
100}; 146};
@@ -110,6 +156,9 @@ struct kcm_mux {
110 struct list_head psocks; /* List of all psocks on MUX */ 156 struct list_head psocks; /* List of all psocks on MUX */
111 int psocks_cnt; /* Total attached sockets */ 157 int psocks_cnt; /* Total attached sockets */
112 158
159 struct kcm_mux_stats stats;
160 struct kcm_psock_stats aggregate_psock_stats;
161
113 /* Receive */ 162 /* Receive */
114 spinlock_t rx_lock ____cacheline_aligned_in_smp; 163 spinlock_t rx_lock ____cacheline_aligned_in_smp;
115 struct list_head kcm_rx_waiters; /* KCMs waiting for receiving */ 164 struct list_head kcm_rx_waiters; /* KCMs waiting for receiving */
@@ -122,4 +171,49 @@ struct kcm_mux {
122 struct list_head kcm_tx_waiters; /* KCMs waiting for a TX psock */ 171 struct list_head kcm_tx_waiters; /* KCMs waiting for a TX psock */
123}; 172};
124 173
174#ifdef CONFIG_PROC_FS
175int kcm_proc_init(void);
176void kcm_proc_exit(void);
177#else
178static int kcm_proc_init(void) { return 0; }
179static void kcm_proc_exit(void) { }
180#endif
181
182static inline void aggregate_psock_stats(struct kcm_psock_stats *stats,
183 struct kcm_psock_stats *agg_stats)
184{
185 /* Save psock statistics in the mux when psock is being unattached. */
186
187#define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat)
188 SAVE_PSOCK_STATS(rx_msgs);
189 SAVE_PSOCK_STATS(rx_bytes);
190 SAVE_PSOCK_STATS(rx_aborts);
191 SAVE_PSOCK_STATS(rx_mem_fail);
192 SAVE_PSOCK_STATS(rx_need_more_hdr);
193 SAVE_PSOCK_STATS(rx_bad_hdr_len);
194 SAVE_PSOCK_STATS(tx_msgs);
195 SAVE_PSOCK_STATS(tx_bytes);
196 SAVE_PSOCK_STATS(reserved);
197 SAVE_PSOCK_STATS(unreserved);
198 SAVE_PSOCK_STATS(tx_aborts);
199#undef SAVE_PSOCK_STATS
200}
201
202static inline void aggregate_mux_stats(struct kcm_mux_stats *stats,
203 struct kcm_mux_stats *agg_stats)
204{
205 /* Save psock statistics in the mux when psock is being unattached. */
206
207#define SAVE_MUX_STATS(_stat) (agg_stats->_stat += stats->_stat)
208 SAVE_MUX_STATS(rx_msgs);
209 SAVE_MUX_STATS(rx_bytes);
210 SAVE_MUX_STATS(tx_msgs);
211 SAVE_MUX_STATS(tx_bytes);
212 SAVE_MUX_STATS(rx_ready_drops);
213 SAVE_MUX_STATS(psock_attach);
214 SAVE_MUX_STATS(psock_unattach_rsvd);
215 SAVE_MUX_STATS(psock_unattach);
216#undef SAVE_MUX_STATS
217}
218
125#endif /* __NET_KCM_H_ */ 219#endif /* __NET_KCM_H_ */
diff --git a/net/kcm/Makefile b/net/kcm/Makefile
index cb525f7c5a13..71256133e677 100644
--- a/net/kcm/Makefile
+++ b/net/kcm/Makefile
@@ -1,3 +1,3 @@
1obj-$(CONFIG_AF_KCM) += kcm.o 1obj-$(CONFIG_AF_KCM) += kcm.o
2 2
3kcm-y := kcmsock.o 3kcm-y := kcmsock.o kcmproc.o
diff --git a/net/kcm/kcmproc.c b/net/kcm/kcmproc.c
new file mode 100644
index 000000000000..5eb9809c0f59
--- /dev/null
+++ b/net/kcm/kcmproc.c
@@ -0,0 +1,422 @@
1#include <linux/in.h>
2#include <linux/inet.h>
3#include <linux/list.h>
4#include <linux/module.h>
5#include <linux/net.h>
6#include <linux/proc_fs.h>
7#include <linux/rculist.h>
8#include <linux/seq_file.h>
9#include <linux/socket.h>
10#include <net/inet_sock.h>
11#include <net/kcm.h>
12#include <net/net_namespace.h>
13#include <net/netns/generic.h>
14#include <net/tcp.h>
15
16#ifdef CONFIG_PROC_FS
17struct kcm_seq_muxinfo {
18 char *name;
19 const struct file_operations *seq_fops;
20 const struct seq_operations seq_ops;
21};
22
23static struct kcm_mux *kcm_get_first(struct seq_file *seq)
24{
25 struct net *net = seq_file_net(seq);
26 struct kcm_net *knet = net_generic(net, kcm_net_id);
27
28 return list_first_or_null_rcu(&knet->mux_list,
29 struct kcm_mux, kcm_mux_list);
30}
31
32static struct kcm_mux *kcm_get_next(struct kcm_mux *mux)
33{
34 struct kcm_net *knet = mux->knet;
35
36 return list_next_or_null_rcu(&knet->mux_list, &mux->kcm_mux_list,
37 struct kcm_mux, kcm_mux_list);
38}
39
40static struct kcm_mux *kcm_get_idx(struct seq_file *seq, loff_t pos)
41{
42 struct net *net = seq_file_net(seq);
43 struct kcm_net *knet = net_generic(net, kcm_net_id);
44 struct kcm_mux *m;
45
46 list_for_each_entry_rcu(m, &knet->mux_list, kcm_mux_list) {
47 if (!pos)
48 return m;
49 --pos;
50 }
51 return NULL;
52}
53
54static void *kcm_seq_next(struct seq_file *seq, void *v, loff_t *pos)
55{
56 void *p;
57
58 if (v == SEQ_START_TOKEN)
59 p = kcm_get_first(seq);
60 else
61 p = kcm_get_next(v);
62 ++*pos;
63 return p;
64}
65
66static void *kcm_seq_start(struct seq_file *seq, loff_t *pos)
67 __acquires(rcu)
68{
69 rcu_read_lock();
70
71 if (!*pos)
72 return SEQ_START_TOKEN;
73 else
74 return kcm_get_idx(seq, *pos - 1);
75}
76
77static void kcm_seq_stop(struct seq_file *seq, void *v)
78 __releases(rcu)
79{
80 rcu_read_unlock();
81}
82
83struct kcm_proc_mux_state {
84 struct seq_net_private p;
85 int idx;
86};
87
88static int kcm_seq_open(struct inode *inode, struct file *file)
89{
90 struct kcm_seq_muxinfo *muxinfo = PDE_DATA(inode);
91 int err;
92
93 err = seq_open_net(inode, file, &muxinfo->seq_ops,
94 sizeof(struct kcm_proc_mux_state));
95 if (err < 0)
96 return err;
97 return err;
98}
99
100static void kcm_format_mux_header(struct seq_file *seq)
101{
102 struct net *net = seq_file_net(seq);
103 struct kcm_net *knet = net_generic(net, kcm_net_id);
104
105 seq_printf(seq,
106 "*** KCM statistics (%d MUX) ****\n",
107 knet->count);
108
109 seq_printf(seq,
110 "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
111 "Object",
112 "RX-Msgs",
113 "RX-Bytes",
114 "TX-Msgs",
115 "TX-Bytes",
116 "Recv-Q",
117 "Rmem",
118 "Send-Q",
119 "Smem",
120 "Status");
121
122 /* XXX: pdsts header stuff here */
123 seq_puts(seq, "\n");
124}
125
126static void kcm_format_sock(struct kcm_sock *kcm, struct seq_file *seq,
127 int i, int *len)
128{
129 seq_printf(seq,
130 " kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
131 kcm->index,
132 kcm->stats.rx_msgs,
133 kcm->stats.rx_bytes,
134 kcm->stats.tx_msgs,
135 kcm->stats.tx_bytes,
136 kcm->sk.sk_receive_queue.qlen,
137 sk_rmem_alloc_get(&kcm->sk),
138 kcm->sk.sk_write_queue.qlen,
139 "-");
140
141 if (kcm->tx_psock)
142 seq_printf(seq, "Psck-%u ", kcm->tx_psock->index);
143
144 if (kcm->tx_wait)
145 seq_puts(seq, "TxWait ");
146
147 if (kcm->tx_wait_more)
148 seq_puts(seq, "WMore ");
149
150 if (kcm->rx_wait)
151 seq_puts(seq, "RxWait ");
152
153 seq_puts(seq, "\n");
154}
155
156static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
157 int i, int *len)
158{
159 seq_printf(seq,
160 " psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
161 psock->index,
162 psock->stats.rx_msgs,
163 psock->stats.rx_bytes,
164 psock->stats.tx_msgs,
165 psock->stats.tx_bytes,
166 psock->sk->sk_receive_queue.qlen,
167 atomic_read(&psock->sk->sk_rmem_alloc),
168 psock->sk->sk_write_queue.qlen,
169 atomic_read(&psock->sk->sk_wmem_alloc));
170
171 if (psock->done)
172 seq_puts(seq, "Done ");
173
174 if (psock->tx_stopped)
175 seq_puts(seq, "TxStop ");
176
177 if (psock->rx_stopped)
178 seq_puts(seq, "RxStop ");
179
180 if (psock->tx_kcm)
181 seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
182
183 if (psock->ready_rx_msg)
184 seq_puts(seq, "RdyRx ");
185
186 seq_puts(seq, "\n");
187}
188
189static void
190kcm_format_mux(struct kcm_mux *mux, loff_t idx, struct seq_file *seq)
191{
192 int i, len;
193 struct kcm_sock *kcm;
194 struct kcm_psock *psock;
195
196 /* mux information */
197 seq_printf(seq,
198 "%-6s%-8s %-10llu %-16llu %-10llu %-16llu %-8s %-8s %-8s %-8s ",
199 "mux", "",
200 mux->stats.rx_msgs,
201 mux->stats.rx_bytes,
202 mux->stats.tx_msgs,
203 mux->stats.tx_bytes,
204 "-", "-", "-", "-");
205
206 seq_printf(seq, "KCMs: %d, Psocks %d\n",
207 mux->kcm_socks_cnt, mux->psocks_cnt);
208
209 /* kcm sock information */
210 i = 0;
211 spin_lock_bh(&mux->lock);
212 list_for_each_entry(kcm, &mux->kcm_socks, kcm_sock_list) {
213 kcm_format_sock(kcm, seq, i, &len);
214 i++;
215 }
216 i = 0;
217 list_for_each_entry(psock, &mux->psocks, psock_list) {
218 kcm_format_psock(psock, seq, i, &len);
219 i++;
220 }
221 spin_unlock_bh(&mux->lock);
222}
223
224static int kcm_seq_show(struct seq_file *seq, void *v)
225{
226 struct kcm_proc_mux_state *mux_state;
227
228 mux_state = seq->private;
229 if (v == SEQ_START_TOKEN) {
230 mux_state->idx = 0;
231 kcm_format_mux_header(seq);
232 } else {
233 kcm_format_mux(v, mux_state->idx, seq);
234 mux_state->idx++;
235 }
236 return 0;
237}
238
239static const struct file_operations kcm_seq_fops = {
240 .owner = THIS_MODULE,
241 .open = kcm_seq_open,
242 .read = seq_read,
243 .llseek = seq_lseek,
244};
245
246static struct kcm_seq_muxinfo kcm_seq_muxinfo = {
247 .name = "kcm",
248 .seq_fops = &kcm_seq_fops,
249 .seq_ops = {
250 .show = kcm_seq_show,
251 .start = kcm_seq_start,
252 .next = kcm_seq_next,
253 .stop = kcm_seq_stop,
254 }
255};
256
257static int kcm_proc_register(struct net *net, struct kcm_seq_muxinfo *muxinfo)
258{
259 struct proc_dir_entry *p;
260 int rc = 0;
261
262 p = proc_create_data(muxinfo->name, S_IRUGO, net->proc_net,
263 muxinfo->seq_fops, muxinfo);
264 if (!p)
265 rc = -ENOMEM;
266 return rc;
267}
268EXPORT_SYMBOL(kcm_proc_register);
269
270static void kcm_proc_unregister(struct net *net,
271 struct kcm_seq_muxinfo *muxinfo)
272{
273 remove_proc_entry(muxinfo->name, net->proc_net);
274}
275EXPORT_SYMBOL(kcm_proc_unregister);
276
277static int kcm_stats_seq_show(struct seq_file *seq, void *v)
278{
279 struct kcm_psock_stats psock_stats;
280 struct kcm_mux_stats mux_stats;
281 struct kcm_mux *mux;
282 struct kcm_psock *psock;
283 struct net *net = seq->private;
284 struct kcm_net *knet = net_generic(net, kcm_net_id);
285
286 memset(&mux_stats, 0, sizeof(mux_stats));
287 memset(&psock_stats, 0, sizeof(psock_stats));
288
289 mutex_lock(&knet->mutex);
290
291 aggregate_mux_stats(&knet->aggregate_mux_stats, &mux_stats);
292 aggregate_psock_stats(&knet->aggregate_psock_stats,
293 &psock_stats);
294
295 list_for_each_entry_rcu(mux, &knet->mux_list, kcm_mux_list) {
296 spin_lock_bh(&mux->lock);
297 aggregate_mux_stats(&mux->stats, &mux_stats);
298 aggregate_psock_stats(&mux->aggregate_psock_stats,
299 &psock_stats);
300 list_for_each_entry(psock, &mux->psocks, psock_list)
301 aggregate_psock_stats(&psock->stats, &psock_stats);
302 spin_unlock_bh(&mux->lock);
303 }
304
305 mutex_unlock(&knet->mutex);
306
307 seq_printf(seq,
308 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
309 "MUX",
310 "RX-Msgs",
311 "RX-Bytes",
312 "TX-Msgs",
313 "TX-Bytes",
314 "TX-Retries",
315 "Attach",
316 "Unattach",
317 "UnattchRsvd",
318 "RX-RdyDrops");
319
320 seq_printf(seq,
321 "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
322 "",
323 mux_stats.rx_msgs,
324 mux_stats.rx_bytes,
325 mux_stats.tx_msgs,
326 mux_stats.tx_bytes,
327 mux_stats.tx_retries,
328 mux_stats.psock_attach,
329 mux_stats.psock_unattach_rsvd,
330 mux_stats.psock_unattach,
331 mux_stats.rx_ready_drops);
332
333 seq_printf(seq,
334 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
335 "Psock",
336 "RX-Msgs",
337 "RX-Bytes",
338 "TX-Msgs",
339 "TX-Bytes",
340 "Reserved",
341 "Unreserved",
342 "RX-Aborts",
343 "RX-MemFail",
344 "RX-NeedMor",
345 "RX-BadLen",
346 "TX-Aborts");
347
348 seq_printf(seq,
349 "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u\n",
350 "",
351 psock_stats.rx_msgs,
352 psock_stats.rx_bytes,
353 psock_stats.tx_msgs,
354 psock_stats.tx_bytes,
355 psock_stats.reserved,
356 psock_stats.unreserved,
357 psock_stats.rx_aborts,
358 psock_stats.rx_mem_fail,
359 psock_stats.rx_need_more_hdr,
360 psock_stats.rx_bad_hdr_len,
361 psock_stats.tx_aborts);
362
363 return 0;
364}
365
366static int kcm_stats_seq_open(struct inode *inode, struct file *file)
367{
368 return single_open_net(inode, file, kcm_stats_seq_show);
369}
370
371static const struct file_operations kcm_stats_seq_fops = {
372 .owner = THIS_MODULE,
373 .open = kcm_stats_seq_open,
374 .read = seq_read,
375 .llseek = seq_lseek,
376 .release = single_release_net,
377};
378
379static int kcm_proc_init_net(struct net *net)
380{
381 int err;
382
383 if (!proc_create("kcm_stats", S_IRUGO, net->proc_net,
384 &kcm_stats_seq_fops)) {
385 err = -ENOMEM;
386 goto out_kcm_stats;
387 }
388
389 err = kcm_proc_register(net, &kcm_seq_muxinfo);
390 if (err)
391 goto out_kcm;
392
393 return 0;
394
395out_kcm:
396 remove_proc_entry("kcm_stats", net->proc_net);
397out_kcm_stats:
398 return err;
399}
400
401static void kcm_proc_exit_net(struct net *net)
402{
403 kcm_proc_unregister(net, &kcm_seq_muxinfo);
404 remove_proc_entry("kcm_stats", net->proc_net);
405}
406
407static struct pernet_operations kcm_net_ops = {
408 .init = kcm_proc_init_net,
409 .exit = kcm_proc_exit_net,
410};
411
412int __init kcm_proc_init(void)
413{
414 return register_pernet_subsys(&kcm_net_ops);
415}
416
417void __exit kcm_proc_exit(void)
418{
419 unregister_pernet_subsys(&kcm_net_ops);
420}
421
422#endif /* CONFIG_PROC_FS */
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 30ef69ac6b81..f938d7d3e6e2 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -59,6 +59,7 @@ static void kcm_abort_rx_psock(struct kcm_psock *psock, int err,
59 return; 59 return;
60 60
61 psock->rx_stopped = 1; 61 psock->rx_stopped = 1;
62 KCM_STATS_INCR(psock->stats.rx_aborts);
62 63
63 /* Report an error on the lower socket */ 64 /* Report an error on the lower socket */
64 report_csk_error(csk, err); 65 report_csk_error(csk, err);
@@ -80,6 +81,7 @@ static void kcm_abort_tx_psock(struct kcm_psock *psock, int err,
80 } 81 }
81 82
82 psock->tx_stopped = 1; 83 psock->tx_stopped = 1;
84 KCM_STATS_INCR(psock->stats.tx_aborts);
83 85
84 if (!psock->tx_kcm) { 86 if (!psock->tx_kcm) {
85 /* Take off psocks_avail list */ 87 /* Take off psocks_avail list */
@@ -101,6 +103,29 @@ static void kcm_abort_tx_psock(struct kcm_psock *psock, int err,
101 report_csk_error(csk, err); 103 report_csk_error(csk, err);
102} 104}
103 105
106/* RX mux lock held. */
107static void kcm_update_rx_mux_stats(struct kcm_mux *mux,
108 struct kcm_psock *psock)
109{
110 KCM_STATS_ADD(mux->stats.rx_bytes,
111 psock->stats.rx_bytes - psock->saved_rx_bytes);
112 mux->stats.rx_msgs +=
113 psock->stats.rx_msgs - psock->saved_rx_msgs;
114 psock->saved_rx_msgs = psock->stats.rx_msgs;
115 psock->saved_rx_bytes = psock->stats.rx_bytes;
116}
117
118static void kcm_update_tx_mux_stats(struct kcm_mux *mux,
119 struct kcm_psock *psock)
120{
121 KCM_STATS_ADD(mux->stats.tx_bytes,
122 psock->stats.tx_bytes - psock->saved_tx_bytes);
123 mux->stats.tx_msgs +=
124 psock->stats.tx_msgs - psock->saved_tx_msgs;
125 psock->saved_tx_msgs = psock->stats.tx_msgs;
126 psock->saved_tx_bytes = psock->stats.tx_bytes;
127}
128
104static int kcm_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); 129static int kcm_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
105 130
106/* KCM is ready to receive messages on its queue-- either the KCM is new or 131/* KCM is ready to receive messages on its queue-- either the KCM is new or
@@ -254,6 +279,8 @@ static struct kcm_sock *reserve_rx_kcm(struct kcm_psock *psock,
254 return psock->rx_kcm; 279 return psock->rx_kcm;
255 } 280 }
256 281
282 kcm_update_rx_mux_stats(mux, psock);
283
257 if (list_empty(&mux->kcm_rx_waiters)) { 284 if (list_empty(&mux->kcm_rx_waiters)) {
258 psock->ready_rx_msg = head; 285 psock->ready_rx_msg = head;
259 list_add_tail(&psock->psock_ready_list, 286 list_add_tail(&psock->psock_ready_list,
@@ -356,10 +383,12 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
356 */ 383 */
357 orig_skb = skb_clone(orig_skb, GFP_ATOMIC); 384 orig_skb = skb_clone(orig_skb, GFP_ATOMIC);
358 if (!orig_skb) { 385 if (!orig_skb) {
386 KCM_STATS_INCR(psock->stats.rx_mem_fail);
359 desc->error = -ENOMEM; 387 desc->error = -ENOMEM;
360 return 0; 388 return 0;
361 } 389 }
362 if (!pskb_pull(orig_skb, orig_offset)) { 390 if (!pskb_pull(orig_skb, orig_offset)) {
391 KCM_STATS_INCR(psock->stats.rx_mem_fail);
363 kfree_skb(orig_skb); 392 kfree_skb(orig_skb);
364 desc->error = -ENOMEM; 393 desc->error = -ENOMEM;
365 return 0; 394 return 0;
@@ -374,6 +403,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
374 */ 403 */
375 err = skb_unclone(head, GFP_ATOMIC); 404 err = skb_unclone(head, GFP_ATOMIC);
376 if (err) { 405 if (err) {
406 KCM_STATS_INCR(psock->stats.rx_mem_fail);
377 desc->error = err; 407 desc->error = err;
378 return 0; 408 return 0;
379 } 409 }
@@ -392,6 +422,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
392 422
393 skb = alloc_skb(0, GFP_ATOMIC); 423 skb = alloc_skb(0, GFP_ATOMIC);
394 if (!skb) { 424 if (!skb) {
425 KCM_STATS_INCR(psock->stats.rx_mem_fail);
395 desc->error = -ENOMEM; 426 desc->error = -ENOMEM;
396 return 0; 427 return 0;
397 } 428 }
@@ -414,6 +445,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
414 /* Always clone since we will consume something */ 445 /* Always clone since we will consume something */
415 skb = skb_clone(orig_skb, GFP_ATOMIC); 446 skb = skb_clone(orig_skb, GFP_ATOMIC);
416 if (!skb) { 447 if (!skb) {
448 KCM_STATS_INCR(psock->stats.rx_mem_fail);
417 desc->error = -ENOMEM; 449 desc->error = -ENOMEM;
418 break; 450 break;
419 } 451 }
@@ -435,6 +467,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
435 */ 467 */
436 err = skb_unclone(skb, GFP_ATOMIC); 468 err = skb_unclone(skb, GFP_ATOMIC);
437 if (err) { 469 if (err) {
470 KCM_STATS_INCR(psock->stats.rx_mem_fail);
438 desc->error = err; 471 desc->error = err;
439 break; 472 break;
440 } 473 }
@@ -456,6 +489,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
456 /* Need more header to determine length */ 489 /* Need more header to determine length */
457 rxm->accum_len += cand_len; 490 rxm->accum_len += cand_len;
458 eaten += cand_len; 491 eaten += cand_len;
492 KCM_STATS_INCR(psock->stats.rx_need_more_hdr);
459 WARN_ON(eaten != orig_len); 493 WARN_ON(eaten != orig_len);
460 break; 494 break;
461 } else if (len <= (ssize_t)head->len - 495 } else if (len <= (ssize_t)head->len -
@@ -463,6 +497,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
463 /* Length must be into new skb (and also 497 /* Length must be into new skb (and also
464 * greater than zero) 498 * greater than zero)
465 */ 499 */
500 KCM_STATS_INCR(psock->stats.rx_bad_hdr_len);
466 desc->error = -EPROTO; 501 desc->error = -EPROTO;
467 psock->rx_skb_head = NULL; 502 psock->rx_skb_head = NULL;
468 kcm_abort_rx_psock(psock, EPROTO, head); 503 kcm_abort_rx_psock(psock, EPROTO, head);
@@ -492,6 +527,7 @@ static int kcm_tcp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
492 527
493 /* Hurray, we have a new message! */ 528 /* Hurray, we have a new message! */
494 psock->rx_skb_head = NULL; 529 psock->rx_skb_head = NULL;
530 KCM_STATS_INCR(psock->stats.rx_msgs);
495 531
496try_queue: 532try_queue:
497 kcm = reserve_rx_kcm(psock, head); 533 kcm = reserve_rx_kcm(psock, head);
@@ -510,6 +546,8 @@ try_queue:
510 if (cloned_orig) 546 if (cloned_orig)
511 kfree_skb(orig_skb); 547 kfree_skb(orig_skb);
512 548
549 KCM_STATS_ADD(psock->stats.rx_bytes, eaten);
550
513 return eaten; 551 return eaten;
514} 552}
515 553
@@ -671,6 +709,7 @@ static struct kcm_psock *reserve_psock(struct kcm_sock *kcm)
671 } 709 }
672 kcm->tx_psock = psock; 710 kcm->tx_psock = psock;
673 psock->tx_kcm = kcm; 711 psock->tx_kcm = kcm;
712 KCM_STATS_INCR(psock->stats.reserved);
674 } else if (!kcm->tx_wait) { 713 } else if (!kcm->tx_wait) {
675 list_add_tail(&kcm->wait_psock_list, 714 list_add_tail(&kcm->wait_psock_list,
676 &mux->kcm_tx_waiters); 715 &mux->kcm_tx_waiters);
@@ -705,6 +744,7 @@ static void psock_now_avail(struct kcm_psock *psock)
705 smp_mb(); 744 smp_mb();
706 745
707 kcm->tx_psock = psock; 746 kcm->tx_psock = psock;
747 KCM_STATS_INCR(psock->stats.reserved);
708 queue_work(kcm_wq, &kcm->tx_work); 748 queue_work(kcm_wq, &kcm->tx_work);
709 } 749 }
710} 750}
@@ -726,10 +766,13 @@ static void unreserve_psock(struct kcm_sock *kcm)
726 766
727 smp_rmb(); /* Read tx_psock before tx_wait */ 767 smp_rmb(); /* Read tx_psock before tx_wait */
728 768
769 kcm_update_tx_mux_stats(mux, psock);
770
729 WARN_ON(kcm->tx_wait); 771 WARN_ON(kcm->tx_wait);
730 772
731 kcm->tx_psock = NULL; 773 kcm->tx_psock = NULL;
732 psock->tx_kcm = NULL; 774 psock->tx_kcm = NULL;
775 KCM_STATS_INCR(psock->stats.unreserved);
733 776
734 if (unlikely(psock->tx_stopped)) { 777 if (unlikely(psock->tx_stopped)) {
735 if (psock->done) { 778 if (psock->done) {
@@ -753,6 +796,15 @@ static void unreserve_psock(struct kcm_sock *kcm)
753 spin_unlock_bh(&mux->lock); 796 spin_unlock_bh(&mux->lock);
754} 797}
755 798
799static void kcm_report_tx_retry(struct kcm_sock *kcm)
800{
801 struct kcm_mux *mux = kcm->mux;
802
803 spin_lock_bh(&mux->lock);
804 KCM_STATS_INCR(mux->stats.tx_retries);
805 spin_unlock_bh(&mux->lock);
806}
807
756/* Write any messages ready on the kcm socket. Called with kcm sock lock 808/* Write any messages ready on the kcm socket. Called with kcm sock lock
757 * held. Return bytes actually sent or error. 809 * held. Return bytes actually sent or error.
758 */ 810 */
@@ -773,6 +825,7 @@ static int kcm_write_msgs(struct kcm_sock *kcm)
773 * it and we'll retry the message. 825 * it and we'll retry the message.
774 */ 826 */
775 unreserve_psock(kcm); 827 unreserve_psock(kcm);
828 kcm_report_tx_retry(kcm);
776 if (skb_queue_empty(&sk->sk_write_queue)) 829 if (skb_queue_empty(&sk->sk_write_queue))
777 return 0; 830 return 0;
778 831
@@ -856,6 +909,7 @@ do_frag:
856 unreserve_psock(kcm); 909 unreserve_psock(kcm);
857 910
858 txm->sent = 0; 911 txm->sent = 0;
912 kcm_report_tx_retry(kcm);
859 ret = 0; 913 ret = 0;
860 914
861 goto try_again; 915 goto try_again;
@@ -863,6 +917,7 @@ do_frag:
863 917
864 sent += ret; 918 sent += ret;
865 frag_offset += ret; 919 frag_offset += ret;
920 KCM_STATS_ADD(psock->stats.tx_bytes, ret);
866 if (frag_offset < frag->size) { 921 if (frag_offset < frag->size) {
867 /* Not finished with this frag */ 922 /* Not finished with this frag */
868 goto do_frag; 923 goto do_frag;
@@ -884,6 +939,7 @@ do_frag:
884 kfree_skb(head); 939 kfree_skb(head);
885 sk->sk_wmem_queued -= sent; 940 sk->sk_wmem_queued -= sent;
886 total_sent += sent; 941 total_sent += sent;
942 KCM_STATS_INCR(psock->stats.tx_msgs);
887 } while ((head = skb_peek(&sk->sk_write_queue))); 943 } while ((head = skb_peek(&sk->sk_write_queue)));
888out: 944out:
889 if (!head) { 945 if (!head) {
@@ -1061,6 +1117,7 @@ wait_for_memory:
1061 /* Message complete, queue it on send buffer */ 1117 /* Message complete, queue it on send buffer */
1062 __skb_queue_tail(&sk->sk_write_queue, head); 1118 __skb_queue_tail(&sk->sk_write_queue, head);
1063 kcm->seq_skb = NULL; 1119 kcm->seq_skb = NULL;
1120 KCM_STATS_INCR(kcm->stats.tx_msgs);
1064 1121
1065 if (msg->msg_flags & MSG_BATCH) { 1122 if (msg->msg_flags & MSG_BATCH) {
1066 kcm->tx_wait_more = true; 1123 kcm->tx_wait_more = true;
@@ -1083,6 +1140,8 @@ partial_message:
1083 kcm_tx_msg(head)->last_skb = skb; 1140 kcm_tx_msg(head)->last_skb = skb;
1084 } 1141 }
1085 1142
1143 KCM_STATS_ADD(kcm->stats.tx_bytes, copied);
1144
1086 release_sock(sk); 1145 release_sock(sk);
1087 return copied; 1146 return copied;
1088 1147
@@ -1144,6 +1203,7 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg,
1144 size_t len, int flags) 1203 size_t len, int flags)
1145{ 1204{
1146 struct sock *sk = sock->sk; 1205 struct sock *sk = sock->sk;
1206 struct kcm_sock *kcm = kcm_sk(sk);
1147 int err = 0; 1207 int err = 0;
1148 long timeo; 1208 long timeo;
1149 struct kcm_rx_msg *rxm; 1209 struct kcm_rx_msg *rxm;
@@ -1171,6 +1231,7 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg,
1171 1231
1172 copied = len; 1232 copied = len;
1173 if (likely(!(flags & MSG_PEEK))) { 1233 if (likely(!(flags & MSG_PEEK))) {
1234 KCM_STATS_ADD(kcm->stats.rx_bytes, copied);
1174 if (copied < rxm->full_len) { 1235 if (copied < rxm->full_len) {
1175 if (sock->type == SOCK_DGRAM) { 1236 if (sock->type == SOCK_DGRAM) {
1176 /* Truncated message */ 1237 /* Truncated message */
@@ -1183,6 +1244,7 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg,
1183msg_finished: 1244msg_finished:
1184 /* Finished with message */ 1245 /* Finished with message */
1185 msg->msg_flags |= MSG_EOR; 1246 msg->msg_flags |= MSG_EOR;
1247 KCM_STATS_INCR(kcm->stats.rx_msgs);
1186 skb_unlink(skb, &sk->sk_receive_queue); 1248 skb_unlink(skb, &sk->sk_receive_queue);
1187 kfree_skb(skb); 1249 kfree_skb(skb);
1188 } 1250 }
@@ -1394,6 +1456,7 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
1394 list_add(&psock->psock_list, head); 1456 list_add(&psock->psock_list, head);
1395 psock->index = index; 1457 psock->index = index;
1396 1458
1459 KCM_STATS_INCR(mux->stats.psock_attach);
1397 mux->psocks_cnt++; 1460 mux->psocks_cnt++;
1398 psock_now_avail(psock); 1461 psock_now_avail(psock);
1399 spin_unlock_bh(&mux->lock); 1462 spin_unlock_bh(&mux->lock);
@@ -1469,6 +1532,7 @@ static void kcm_unattach(struct kcm_psock *psock)
1469 list_del(&psock->psock_ready_list); 1532 list_del(&psock->psock_ready_list);
1470 kfree_skb(psock->ready_rx_msg); 1533 kfree_skb(psock->ready_rx_msg);
1471 psock->ready_rx_msg = NULL; 1534 psock->ready_rx_msg = NULL;
1535 KCM_STATS_INCR(mux->stats.rx_ready_drops);
1472 } 1536 }
1473 1537
1474 spin_unlock_bh(&mux->rx_lock); 1538 spin_unlock_bh(&mux->rx_lock);
@@ -1485,11 +1549,16 @@ static void kcm_unattach(struct kcm_psock *psock)
1485 1549
1486 spin_lock_bh(&mux->lock); 1550 spin_lock_bh(&mux->lock);
1487 1551
1552 aggregate_psock_stats(&psock->stats, &mux->aggregate_psock_stats);
1553
1554 KCM_STATS_INCR(mux->stats.psock_unattach);
1555
1488 if (psock->tx_kcm) { 1556 if (psock->tx_kcm) {
1489 /* psock was reserved. Just mark it finished and we will clean 1557 /* psock was reserved. Just mark it finished and we will clean
1490 * up in the kcm paths, we need kcm lock which can not be 1558 * up in the kcm paths, we need kcm lock which can not be
1491 * acquired here. 1559 * acquired here.
1492 */ 1560 */
1561 KCM_STATS_INCR(mux->stats.psock_unattach_rsvd);
1493 spin_unlock_bh(&mux->lock); 1562 spin_unlock_bh(&mux->lock);
1494 1563
1495 /* We are unattaching a socket that is reserved. Abort the 1564 /* We are unattaching a socket that is reserved. Abort the
@@ -1717,6 +1786,9 @@ static void release_mux(struct kcm_mux *mux)
1717 __skb_queue_purge(&mux->rx_hold_queue); 1786 __skb_queue_purge(&mux->rx_hold_queue);
1718 1787
1719 mutex_lock(&knet->mutex); 1788 mutex_lock(&knet->mutex);
1789 aggregate_mux_stats(&mux->stats, &knet->aggregate_mux_stats);
1790 aggregate_psock_stats(&mux->aggregate_psock_stats,
1791 &knet->aggregate_psock_stats);
1720 list_del_rcu(&mux->kcm_mux_list); 1792 list_del_rcu(&mux->kcm_mux_list);
1721 knet->count--; 1793 knet->count--;
1722 mutex_unlock(&knet->mutex); 1794 mutex_unlock(&knet->mutex);
@@ -1979,8 +2051,15 @@ static int __init kcm_init(void)
1979 if (err) 2051 if (err)
1980 goto net_ops_fail; 2052 goto net_ops_fail;
1981 2053
2054 err = kcm_proc_init();
2055 if (err)
2056 goto proc_init_fail;
2057
1982 return 0; 2058 return 0;
1983 2059
2060proc_init_fail:
2061 unregister_pernet_device(&kcm_net_ops);
2062
1984net_ops_fail: 2063net_ops_fail:
1985 sock_unregister(PF_KCM); 2064 sock_unregister(PF_KCM);
1986 2065
@@ -1999,6 +2078,7 @@ fail:
1999 2078
2000static void __exit kcm_exit(void) 2079static void __exit kcm_exit(void)
2001{ 2080{
2081 kcm_proc_exit();
2002 unregister_pernet_device(&kcm_net_ops); 2082 unregister_pernet_device(&kcm_net_ops);
2003 sock_unregister(PF_KCM); 2083 sock_unregister(PF_KCM);
2004 proto_unregister(&kcm_proto); 2084 proto_unregister(&kcm_proto);