1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/inet.h>
4 #include <linux/list.h>
5 #include <linux/module.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>
13 #include <net/net_namespace.h>
14 #include <net/netns/generic.h>
18 struct kcm_seq_muxinfo
{
20 const struct file_operations
*seq_fops
;
21 const struct seq_operations seq_ops
;
24 static struct kcm_mux
*kcm_get_first(struct seq_file
*seq
)
26 struct net
*net
= seq_file_net(seq
);
27 struct kcm_net
*knet
= net_generic(net
, kcm_net_id
);
29 return list_first_or_null_rcu(&knet
->mux_list
,
30 struct kcm_mux
, kcm_mux_list
);
33 static struct kcm_mux
*kcm_get_next(struct kcm_mux
*mux
)
35 struct kcm_net
*knet
= mux
->knet
;
37 return list_next_or_null_rcu(&knet
->mux_list
, &mux
->kcm_mux_list
,
38 struct kcm_mux
, kcm_mux_list
);
41 static struct kcm_mux
*kcm_get_idx(struct seq_file
*seq
, loff_t pos
)
43 struct net
*net
= seq_file_net(seq
);
44 struct kcm_net
*knet
= net_generic(net
, kcm_net_id
);
47 list_for_each_entry_rcu(m
, &knet
->mux_list
, kcm_mux_list
) {
55 static void *kcm_seq_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
59 if (v
== SEQ_START_TOKEN
)
60 p
= kcm_get_first(seq
);
67 static void *kcm_seq_start(struct seq_file
*seq
, loff_t
*pos
)
73 return SEQ_START_TOKEN
;
75 return kcm_get_idx(seq
, *pos
- 1);
78 static void kcm_seq_stop(struct seq_file
*seq
, void *v
)
84 struct kcm_proc_mux_state
{
85 struct seq_net_private p
;
89 static int kcm_seq_open(struct inode
*inode
, struct file
*file
)
91 struct kcm_seq_muxinfo
*muxinfo
= PDE_DATA(inode
);
93 return seq_open_net(inode
, file
, &muxinfo
->seq_ops
,
94 sizeof(struct kcm_proc_mux_state
));
97 static void kcm_format_mux_header(struct seq_file
*seq
)
99 struct net
*net
= seq_file_net(seq
);
100 struct kcm_net
*knet
= net_generic(net
, kcm_net_id
);
103 "*** KCM statistics (%d MUX) ****\n",
107 "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
119 /* XXX: pdsts header stuff here */
123 static void kcm_format_sock(struct kcm_sock
*kcm
, struct seq_file
*seq
,
127 " kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
133 kcm
->sk
.sk_receive_queue
.qlen
,
134 sk_rmem_alloc_get(&kcm
->sk
),
135 kcm
->sk
.sk_write_queue
.qlen
,
139 seq_printf(seq
, "Psck-%u ", kcm
->tx_psock
->index
);
142 seq_puts(seq
, "TxWait ");
144 if (kcm
->tx_wait_more
)
145 seq_puts(seq
, "WMore ");
148 seq_puts(seq
, "RxWait ");
153 static void kcm_format_psock(struct kcm_psock
*psock
, struct seq_file
*seq
,
157 " psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
159 psock
->strp
.stats
.msgs
,
160 psock
->strp
.stats
.bytes
,
161 psock
->stats
.tx_msgs
,
162 psock
->stats
.tx_bytes
,
163 psock
->sk
->sk_receive_queue
.qlen
,
164 atomic_read(&psock
->sk
->sk_rmem_alloc
),
165 psock
->sk
->sk_write_queue
.qlen
,
166 refcount_read(&psock
->sk
->sk_wmem_alloc
));
169 seq_puts(seq
, "Done ");
171 if (psock
->tx_stopped
)
172 seq_puts(seq
, "TxStop ");
174 if (psock
->strp
.stopped
)
175 seq_puts(seq
, "RxStop ");
178 seq_printf(seq
, "Rsvd-%d ", psock
->tx_kcm
->index
);
180 if (!psock
->strp
.paused
&& !psock
->ready_rx_msg
) {
181 if (psock
->sk
->sk_receive_queue
.qlen
) {
182 if (psock
->strp
.need_bytes
)
183 seq_printf(seq
, "RxWait=%u ",
184 psock
->strp
.need_bytes
);
186 seq_printf(seq
, "RxWait ");
189 if (psock
->strp
.paused
)
190 seq_puts(seq
, "RxPause ");
192 if (psock
->ready_rx_msg
)
193 seq_puts(seq
, "RdyRx ");
200 kcm_format_mux(struct kcm_mux
*mux
, loff_t idx
, struct seq_file
*seq
)
203 struct kcm_sock
*kcm
;
204 struct kcm_psock
*psock
;
206 /* mux information */
208 "%-6s%-8s %-10llu %-16llu %-10llu %-16llu %-8s %-8s %-8s %-8s ",
216 seq_printf(seq
, "KCMs: %d, Psocks %d\n",
217 mux
->kcm_socks_cnt
, mux
->psocks_cnt
);
219 /* kcm sock information */
221 spin_lock_bh(&mux
->lock
);
222 list_for_each_entry(kcm
, &mux
->kcm_socks
, kcm_sock_list
) {
223 kcm_format_sock(kcm
, seq
, i
, &len
);
227 list_for_each_entry(psock
, &mux
->psocks
, psock_list
) {
228 kcm_format_psock(psock
, seq
, i
, &len
);
231 spin_unlock_bh(&mux
->lock
);
234 static int kcm_seq_show(struct seq_file
*seq
, void *v
)
236 struct kcm_proc_mux_state
*mux_state
;
238 mux_state
= seq
->private;
239 if (v
== SEQ_START_TOKEN
) {
241 kcm_format_mux_header(seq
);
243 kcm_format_mux(v
, mux_state
->idx
, seq
);
249 static const struct file_operations kcm_seq_fops
= {
250 .open
= kcm_seq_open
,
253 .release
= seq_release_net
,
256 static struct kcm_seq_muxinfo kcm_seq_muxinfo
= {
258 .seq_fops
= &kcm_seq_fops
,
260 .show
= kcm_seq_show
,
261 .start
= kcm_seq_start
,
262 .next
= kcm_seq_next
,
263 .stop
= kcm_seq_stop
,
267 static int kcm_proc_register(struct net
*net
, struct kcm_seq_muxinfo
*muxinfo
)
269 struct proc_dir_entry
*p
;
272 p
= proc_create_data(muxinfo
->name
, S_IRUGO
, net
->proc_net
,
273 muxinfo
->seq_fops
, muxinfo
);
278 EXPORT_SYMBOL(kcm_proc_register
);
280 static void kcm_proc_unregister(struct net
*net
,
281 struct kcm_seq_muxinfo
*muxinfo
)
283 remove_proc_entry(muxinfo
->name
, net
->proc_net
);
285 EXPORT_SYMBOL(kcm_proc_unregister
);
287 static int kcm_stats_seq_show(struct seq_file
*seq
, void *v
)
289 struct kcm_psock_stats psock_stats
;
290 struct kcm_mux_stats mux_stats
;
291 struct strp_aggr_stats strp_stats
;
293 struct kcm_psock
*psock
;
294 struct net
*net
= seq
->private;
295 struct kcm_net
*knet
= net_generic(net
, kcm_net_id
);
297 memset(&mux_stats
, 0, sizeof(mux_stats
));
298 memset(&psock_stats
, 0, sizeof(psock_stats
));
299 memset(&strp_stats
, 0, sizeof(strp_stats
));
301 mutex_lock(&knet
->mutex
);
303 aggregate_mux_stats(&knet
->aggregate_mux_stats
, &mux_stats
);
304 aggregate_psock_stats(&knet
->aggregate_psock_stats
,
306 aggregate_strp_stats(&knet
->aggregate_strp_stats
,
309 list_for_each_entry_rcu(mux
, &knet
->mux_list
, kcm_mux_list
) {
310 spin_lock_bh(&mux
->lock
);
311 aggregate_mux_stats(&mux
->stats
, &mux_stats
);
312 aggregate_psock_stats(&mux
->aggregate_psock_stats
,
314 aggregate_strp_stats(&mux
->aggregate_strp_stats
,
316 list_for_each_entry(psock
, &mux
->psocks
, psock_list
) {
317 aggregate_psock_stats(&psock
->stats
, &psock_stats
);
318 save_strp_stats(&psock
->strp
, &strp_stats
);
321 spin_unlock_bh(&mux
->lock
);
324 mutex_unlock(&knet
->mutex
);
327 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
340 "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
346 mux_stats
.tx_retries
,
347 mux_stats
.psock_attach
,
348 mux_stats
.psock_unattach_rsvd
,
349 mux_stats
.psock_unattach
,
350 mux_stats
.rx_ready_drops
);
353 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
372 "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
377 psock_stats
.tx_bytes
,
378 psock_stats
.reserved
,
379 psock_stats
.unreserved
,
381 strp_stats
.interrupted
,
382 strp_stats
.unrecov_intr
,
384 strp_stats
.need_more_hdr
,
385 strp_stats
.bad_hdr_len
,
386 strp_stats
.msg_too_big
,
387 strp_stats
.msg_timeouts
,
388 psock_stats
.tx_aborts
);
393 static int kcm_stats_seq_open(struct inode
*inode
, struct file
*file
)
395 return single_open_net(inode
, file
, kcm_stats_seq_show
);
398 static const struct file_operations kcm_stats_seq_fops
= {
399 .open
= kcm_stats_seq_open
,
402 .release
= single_release_net
,
405 static int kcm_proc_init_net(struct net
*net
)
409 if (!proc_create("kcm_stats", S_IRUGO
, net
->proc_net
,
410 &kcm_stats_seq_fops
)) {
415 err
= kcm_proc_register(net
, &kcm_seq_muxinfo
);
422 remove_proc_entry("kcm_stats", net
->proc_net
);
427 static void kcm_proc_exit_net(struct net
*net
)
429 kcm_proc_unregister(net
, &kcm_seq_muxinfo
);
430 remove_proc_entry("kcm_stats", net
->proc_net
);
433 static struct pernet_operations kcm_net_ops
= {
434 .init
= kcm_proc_init_net
,
435 .exit
= kcm_proc_exit_net
,
438 int __init
kcm_proc_init(void)
440 return register_pernet_subsys(&kcm_net_ops
);
443 void __exit
kcm_proc_exit(void)
445 unregister_pernet_subsys(&kcm_net_ops
);
448 #endif /* CONFIG_PROC_FS */