Merge tag 'for-linus-2022120801' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / net / kcm / kcmproc.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/in.h>
3 #include <linux/inet.h>
4 #include <linux/list.h>
5 #include <linux/module.h>
6 #include <linux/net.h>
7 #include <linux/proc_fs.h>
8 #include <linux/rculist.h>
9 #include <linux/seq_file.h>
10 #include <linux/socket.h>
11 #include <net/inet_sock.h>
12 #include <net/kcm.h>
13 #include <net/net_namespace.h>
14 #include <net/netns/generic.h>
15 #include <net/tcp.h>
16
17 #ifdef CONFIG_PROC_FS
18 static struct kcm_mux *kcm_get_first(struct seq_file *seq)
19 {
20         struct net *net = seq_file_net(seq);
21         struct kcm_net *knet = net_generic(net, kcm_net_id);
22
23         return list_first_or_null_rcu(&knet->mux_list,
24                                       struct kcm_mux, kcm_mux_list);
25 }
26
27 static struct kcm_mux *kcm_get_next(struct kcm_mux *mux)
28 {
29         struct kcm_net *knet = mux->knet;
30
31         return list_next_or_null_rcu(&knet->mux_list, &mux->kcm_mux_list,
32                                      struct kcm_mux, kcm_mux_list);
33 }
34
35 static struct kcm_mux *kcm_get_idx(struct seq_file *seq, loff_t pos)
36 {
37         struct net *net = seq_file_net(seq);
38         struct kcm_net *knet = net_generic(net, kcm_net_id);
39         struct kcm_mux *m;
40
41         list_for_each_entry_rcu(m, &knet->mux_list, kcm_mux_list) {
42                 if (!pos)
43                         return m;
44                 --pos;
45         }
46         return NULL;
47 }
48
49 static void *kcm_seq_next(struct seq_file *seq, void *v, loff_t *pos)
50 {
51         void *p;
52
53         if (v == SEQ_START_TOKEN)
54                 p = kcm_get_first(seq);
55         else
56                 p = kcm_get_next(v);
57         ++*pos;
58         return p;
59 }
60
61 static void *kcm_seq_start(struct seq_file *seq, loff_t *pos)
62         __acquires(rcu)
63 {
64         rcu_read_lock();
65
66         if (!*pos)
67                 return SEQ_START_TOKEN;
68         else
69                 return kcm_get_idx(seq, *pos - 1);
70 }
71
72 static void kcm_seq_stop(struct seq_file *seq, void *v)
73         __releases(rcu)
74 {
75         rcu_read_unlock();
76 }
77
78 struct kcm_proc_mux_state {
79         struct seq_net_private p;
80         int idx;
81 };
82
83 static void kcm_format_mux_header(struct seq_file *seq)
84 {
85         struct net *net = seq_file_net(seq);
86         struct kcm_net *knet = net_generic(net, kcm_net_id);
87
88         seq_printf(seq,
89                    "*** KCM statistics (%d MUX) ****\n",
90                    knet->count);
91
92         seq_printf(seq,
93                    "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
94                    "Object",
95                    "RX-Msgs",
96                    "RX-Bytes",
97                    "TX-Msgs",
98                    "TX-Bytes",
99                    "Recv-Q",
100                    "Rmem",
101                    "Send-Q",
102                    "Smem",
103                    "Status");
104
105         /* XXX: pdsts header stuff here */
106         seq_puts(seq, "\n");
107 }
108
109 static void kcm_format_sock(struct kcm_sock *kcm, struct seq_file *seq,
110                             int i, int *len)
111 {
112         seq_printf(seq,
113                    "   kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
114                    kcm->index,
115                    kcm->stats.rx_msgs,
116                    kcm->stats.rx_bytes,
117                    kcm->stats.tx_msgs,
118                    kcm->stats.tx_bytes,
119                    kcm->sk.sk_receive_queue.qlen,
120                    sk_rmem_alloc_get(&kcm->sk),
121                    kcm->sk.sk_write_queue.qlen,
122                    "-");
123
124         if (kcm->tx_psock)
125                 seq_printf(seq, "Psck-%u ", kcm->tx_psock->index);
126
127         if (kcm->tx_wait)
128                 seq_puts(seq, "TxWait ");
129
130         if (kcm->tx_wait_more)
131                 seq_puts(seq, "WMore ");
132
133         if (kcm->rx_wait)
134                 seq_puts(seq, "RxWait ");
135
136         seq_puts(seq, "\n");
137 }
138
139 static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
140                              int i, int *len)
141 {
142         seq_printf(seq,
143                    "   psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
144                    psock->index,
145                    psock->strp.stats.msgs,
146                    psock->strp.stats.bytes,
147                    psock->stats.tx_msgs,
148                    psock->stats.tx_bytes,
149                    psock->sk->sk_receive_queue.qlen,
150                    atomic_read(&psock->sk->sk_rmem_alloc),
151                    psock->sk->sk_write_queue.qlen,
152                    refcount_read(&psock->sk->sk_wmem_alloc));
153
154         if (psock->done)
155                 seq_puts(seq, "Done ");
156
157         if (psock->tx_stopped)
158                 seq_puts(seq, "TxStop ");
159
160         if (psock->strp.stopped)
161                 seq_puts(seq, "RxStop ");
162
163         if (psock->tx_kcm)
164                 seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
165
166         if (!psock->strp.paused && !psock->ready_rx_msg) {
167                 if (psock->sk->sk_receive_queue.qlen) {
168                         if (psock->strp.need_bytes)
169                                 seq_printf(seq, "RxWait=%u ",
170                                            psock->strp.need_bytes);
171                         else
172                                 seq_printf(seq, "RxWait ");
173                 }
174         } else  {
175                 if (psock->strp.paused)
176                         seq_puts(seq, "RxPause ");
177
178                 if (psock->ready_rx_msg)
179                         seq_puts(seq, "RdyRx ");
180         }
181
182         seq_puts(seq, "\n");
183 }
184
185 static void
186 kcm_format_mux(struct kcm_mux *mux, loff_t idx, struct seq_file *seq)
187 {
188         int i, len;
189         struct kcm_sock *kcm;
190         struct kcm_psock *psock;
191
192         /* mux information */
193         seq_printf(seq,
194                    "%-6s%-8s %-10llu %-16llu %-10llu %-16llu %-8s %-8s %-8s %-8s ",
195                    "mux", "",
196                    mux->stats.rx_msgs,
197                    mux->stats.rx_bytes,
198                    mux->stats.tx_msgs,
199                    mux->stats.tx_bytes,
200                    "-", "-", "-", "-");
201
202         seq_printf(seq, "KCMs: %d, Psocks %d\n",
203                    mux->kcm_socks_cnt, mux->psocks_cnt);
204
205         /* kcm sock information */
206         i = 0;
207         spin_lock_bh(&mux->lock);
208         list_for_each_entry(kcm, &mux->kcm_socks, kcm_sock_list) {
209                 kcm_format_sock(kcm, seq, i, &len);
210                 i++;
211         }
212         i = 0;
213         list_for_each_entry(psock, &mux->psocks, psock_list) {
214                 kcm_format_psock(psock, seq, i, &len);
215                 i++;
216         }
217         spin_unlock_bh(&mux->lock);
218 }
219
220 static int kcm_seq_show(struct seq_file *seq, void *v)
221 {
222         struct kcm_proc_mux_state *mux_state;
223
224         mux_state = seq->private;
225         if (v == SEQ_START_TOKEN) {
226                 mux_state->idx = 0;
227                 kcm_format_mux_header(seq);
228         } else {
229                 kcm_format_mux(v, mux_state->idx, seq);
230                 mux_state->idx++;
231         }
232         return 0;
233 }
234
235 static const struct seq_operations kcm_seq_ops = {
236         .show   = kcm_seq_show,
237         .start  = kcm_seq_start,
238         .next   = kcm_seq_next,
239         .stop   = kcm_seq_stop,
240 };
241
242 static int kcm_stats_seq_show(struct seq_file *seq, void *v)
243 {
244         struct kcm_psock_stats psock_stats;
245         struct kcm_mux_stats mux_stats;
246         struct strp_aggr_stats strp_stats;
247         struct kcm_mux *mux;
248         struct kcm_psock *psock;
249         struct net *net = seq->private;
250         struct kcm_net *knet = net_generic(net, kcm_net_id);
251
252         memset(&mux_stats, 0, sizeof(mux_stats));
253         memset(&psock_stats, 0, sizeof(psock_stats));
254         memset(&strp_stats, 0, sizeof(strp_stats));
255
256         mutex_lock(&knet->mutex);
257
258         aggregate_mux_stats(&knet->aggregate_mux_stats, &mux_stats);
259         aggregate_psock_stats(&knet->aggregate_psock_stats,
260                               &psock_stats);
261         aggregate_strp_stats(&knet->aggregate_strp_stats,
262                              &strp_stats);
263
264         list_for_each_entry(mux, &knet->mux_list, kcm_mux_list) {
265                 spin_lock_bh(&mux->lock);
266                 aggregate_mux_stats(&mux->stats, &mux_stats);
267                 aggregate_psock_stats(&mux->aggregate_psock_stats,
268                                       &psock_stats);
269                 aggregate_strp_stats(&mux->aggregate_strp_stats,
270                                      &strp_stats);
271                 list_for_each_entry(psock, &mux->psocks, psock_list) {
272                         aggregate_psock_stats(&psock->stats, &psock_stats);
273                         save_strp_stats(&psock->strp, &strp_stats);
274                 }
275
276                 spin_unlock_bh(&mux->lock);
277         }
278
279         mutex_unlock(&knet->mutex);
280
281         seq_printf(seq,
282                    "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
283                    "MUX",
284                    "RX-Msgs",
285                    "RX-Bytes",
286                    "TX-Msgs",
287                    "TX-Bytes",
288                    "TX-Retries",
289                    "Attach",
290                    "Unattach",
291                    "UnattchRsvd",
292                    "RX-RdyDrops");
293
294         seq_printf(seq,
295                    "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
296                    "",
297                    mux_stats.rx_msgs,
298                    mux_stats.rx_bytes,
299                    mux_stats.tx_msgs,
300                    mux_stats.tx_bytes,
301                    mux_stats.tx_retries,
302                    mux_stats.psock_attach,
303                    mux_stats.psock_unattach_rsvd,
304                    mux_stats.psock_unattach,
305                    mux_stats.rx_ready_drops);
306
307         seq_printf(seq,
308                    "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
309                    "Psock",
310                    "RX-Msgs",
311                    "RX-Bytes",
312                    "TX-Msgs",
313                    "TX-Bytes",
314                    "Reserved",
315                    "Unreserved",
316                    "RX-Aborts",
317                    "RX-Intr",
318                    "RX-Unrecov",
319                    "RX-MemFail",
320                    "RX-NeedMor",
321                    "RX-BadLen",
322                    "RX-TooBig",
323                    "RX-Timeout",
324                    "TX-Aborts");
325
326         seq_printf(seq,
327                    "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
328                    "",
329                    strp_stats.msgs,
330                    strp_stats.bytes,
331                    psock_stats.tx_msgs,
332                    psock_stats.tx_bytes,
333                    psock_stats.reserved,
334                    psock_stats.unreserved,
335                    strp_stats.aborts,
336                    strp_stats.interrupted,
337                    strp_stats.unrecov_intr,
338                    strp_stats.mem_fail,
339                    strp_stats.need_more_hdr,
340                    strp_stats.bad_hdr_len,
341                    strp_stats.msg_too_big,
342                    strp_stats.msg_timeouts,
343                    psock_stats.tx_aborts);
344
345         return 0;
346 }
347
348 static int kcm_proc_init_net(struct net *net)
349 {
350         if (!proc_create_net_single("kcm_stats", 0444, net->proc_net,
351                          kcm_stats_seq_show, NULL))
352                 goto out_kcm_stats;
353
354         if (!proc_create_net("kcm", 0444, net->proc_net, &kcm_seq_ops,
355                         sizeof(struct kcm_proc_mux_state)))
356                 goto out_kcm;
357
358         return 0;
359
360 out_kcm:
361         remove_proc_entry("kcm_stats", net->proc_net);
362 out_kcm_stats:
363         return -ENOMEM;
364 }
365
366 static void kcm_proc_exit_net(struct net *net)
367 {
368         remove_proc_entry("kcm", net->proc_net);
369         remove_proc_entry("kcm_stats", net->proc_net);
370 }
371
372 static struct pernet_operations kcm_net_ops = {
373         .init = kcm_proc_init_net,
374         .exit = kcm_proc_exit_net,
375 };
376
377 int __init kcm_proc_init(void)
378 {
379         return register_pernet_subsys(&kcm_net_ops);
380 }
381
382 void __exit kcm_proc_exit(void)
383 {
384         unregister_pernet_subsys(&kcm_net_ops);
385 }
386
387 #endif /* CONFIG_PROC_FS */