0001
0002 #include <linux/in.h>
0003 #include <linux/inet.h>
0004 #include <linux/list.h>
0005 #include <linux/module.h>
0006 #include <linux/net.h>
0007 #include <linux/proc_fs.h>
0008 #include <linux/rculist.h>
0009 #include <linux/seq_file.h>
0010 #include <linux/socket.h>
0011 #include <net/inet_sock.h>
0012 #include <net/kcm.h>
0013 #include <net/net_namespace.h>
0014 #include <net/netns/generic.h>
0015 #include <net/tcp.h>
0016
0017 #ifdef CONFIG_PROC_FS
0018 static struct kcm_mux *kcm_get_first(struct seq_file *seq)
0019 {
0020 struct net *net = seq_file_net(seq);
0021 struct kcm_net *knet = net_generic(net, kcm_net_id);
0022
0023 return list_first_or_null_rcu(&knet->mux_list,
0024 struct kcm_mux, kcm_mux_list);
0025 }
0026
0027 static struct kcm_mux *kcm_get_next(struct kcm_mux *mux)
0028 {
0029 struct kcm_net *knet = mux->knet;
0030
0031 return list_next_or_null_rcu(&knet->mux_list, &mux->kcm_mux_list,
0032 struct kcm_mux, kcm_mux_list);
0033 }
0034
0035 static struct kcm_mux *kcm_get_idx(struct seq_file *seq, loff_t pos)
0036 {
0037 struct net *net = seq_file_net(seq);
0038 struct kcm_net *knet = net_generic(net, kcm_net_id);
0039 struct kcm_mux *m;
0040
0041 list_for_each_entry_rcu(m, &knet->mux_list, kcm_mux_list) {
0042 if (!pos)
0043 return m;
0044 --pos;
0045 }
0046 return NULL;
0047 }
0048
0049 static void *kcm_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0050 {
0051 void *p;
0052
0053 if (v == SEQ_START_TOKEN)
0054 p = kcm_get_first(seq);
0055 else
0056 p = kcm_get_next(v);
0057 ++*pos;
0058 return p;
0059 }
0060
0061 static void *kcm_seq_start(struct seq_file *seq, loff_t *pos)
0062 __acquires(rcu)
0063 {
0064 rcu_read_lock();
0065
0066 if (!*pos)
0067 return SEQ_START_TOKEN;
0068 else
0069 return kcm_get_idx(seq, *pos - 1);
0070 }
0071
0072 static void kcm_seq_stop(struct seq_file *seq, void *v)
0073 __releases(rcu)
0074 {
0075 rcu_read_unlock();
0076 }
0077
0078 struct kcm_proc_mux_state {
0079 struct seq_net_private p;
0080 int idx;
0081 };
0082
0083 static void kcm_format_mux_header(struct seq_file *seq)
0084 {
0085 struct net *net = seq_file_net(seq);
0086 struct kcm_net *knet = net_generic(net, kcm_net_id);
0087
0088 seq_printf(seq,
0089 "*** KCM statistics (%d MUX) ****\n",
0090 knet->count);
0091
0092 seq_printf(seq,
0093 "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
0094 "Object",
0095 "RX-Msgs",
0096 "RX-Bytes",
0097 "TX-Msgs",
0098 "TX-Bytes",
0099 "Recv-Q",
0100 "Rmem",
0101 "Send-Q",
0102 "Smem",
0103 "Status");
0104
0105
0106 seq_puts(seq, "\n");
0107 }
0108
0109 static void kcm_format_sock(struct kcm_sock *kcm, struct seq_file *seq,
0110 int i, int *len)
0111 {
0112 seq_printf(seq,
0113 " kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
0114 kcm->index,
0115 kcm->stats.rx_msgs,
0116 kcm->stats.rx_bytes,
0117 kcm->stats.tx_msgs,
0118 kcm->stats.tx_bytes,
0119 kcm->sk.sk_receive_queue.qlen,
0120 sk_rmem_alloc_get(&kcm->sk),
0121 kcm->sk.sk_write_queue.qlen,
0122 "-");
0123
0124 if (kcm->tx_psock)
0125 seq_printf(seq, "Psck-%u ", kcm->tx_psock->index);
0126
0127 if (kcm->tx_wait)
0128 seq_puts(seq, "TxWait ");
0129
0130 if (kcm->tx_wait_more)
0131 seq_puts(seq, "WMore ");
0132
0133 if (kcm->rx_wait)
0134 seq_puts(seq, "RxWait ");
0135
0136 seq_puts(seq, "\n");
0137 }
0138
0139 static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
0140 int i, int *len)
0141 {
0142 seq_printf(seq,
0143 " psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
0144 psock->index,
0145 psock->strp.stats.msgs,
0146 psock->strp.stats.bytes,
0147 psock->stats.tx_msgs,
0148 psock->stats.tx_bytes,
0149 psock->sk->sk_receive_queue.qlen,
0150 atomic_read(&psock->sk->sk_rmem_alloc),
0151 psock->sk->sk_write_queue.qlen,
0152 refcount_read(&psock->sk->sk_wmem_alloc));
0153
0154 if (psock->done)
0155 seq_puts(seq, "Done ");
0156
0157 if (psock->tx_stopped)
0158 seq_puts(seq, "TxStop ");
0159
0160 if (psock->strp.stopped)
0161 seq_puts(seq, "RxStop ");
0162
0163 if (psock->tx_kcm)
0164 seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
0165
0166 if (!psock->strp.paused && !psock->ready_rx_msg) {
0167 if (psock->sk->sk_receive_queue.qlen) {
0168 if (psock->strp.need_bytes)
0169 seq_printf(seq, "RxWait=%u ",
0170 psock->strp.need_bytes);
0171 else
0172 seq_printf(seq, "RxWait ");
0173 }
0174 } else {
0175 if (psock->strp.paused)
0176 seq_puts(seq, "RxPause ");
0177
0178 if (psock->ready_rx_msg)
0179 seq_puts(seq, "RdyRx ");
0180 }
0181
0182 seq_puts(seq, "\n");
0183 }
0184
0185 static void
0186 kcm_format_mux(struct kcm_mux *mux, loff_t idx, struct seq_file *seq)
0187 {
0188 int i, len;
0189 struct kcm_sock *kcm;
0190 struct kcm_psock *psock;
0191
0192
0193 seq_printf(seq,
0194 "%-6s%-8s %-10llu %-16llu %-10llu %-16llu %-8s %-8s %-8s %-8s ",
0195 "mux", "",
0196 mux->stats.rx_msgs,
0197 mux->stats.rx_bytes,
0198 mux->stats.tx_msgs,
0199 mux->stats.tx_bytes,
0200 "-", "-", "-", "-");
0201
0202 seq_printf(seq, "KCMs: %d, Psocks %d\n",
0203 mux->kcm_socks_cnt, mux->psocks_cnt);
0204
0205
0206 i = 0;
0207 spin_lock_bh(&mux->lock);
0208 list_for_each_entry(kcm, &mux->kcm_socks, kcm_sock_list) {
0209 kcm_format_sock(kcm, seq, i, &len);
0210 i++;
0211 }
0212 i = 0;
0213 list_for_each_entry(psock, &mux->psocks, psock_list) {
0214 kcm_format_psock(psock, seq, i, &len);
0215 i++;
0216 }
0217 spin_unlock_bh(&mux->lock);
0218 }
0219
0220 static int kcm_seq_show(struct seq_file *seq, void *v)
0221 {
0222 struct kcm_proc_mux_state *mux_state;
0223
0224 mux_state = seq->private;
0225 if (v == SEQ_START_TOKEN) {
0226 mux_state->idx = 0;
0227 kcm_format_mux_header(seq);
0228 } else {
0229 kcm_format_mux(v, mux_state->idx, seq);
0230 mux_state->idx++;
0231 }
0232 return 0;
0233 }
0234
0235 static const struct seq_operations kcm_seq_ops = {
0236 .show = kcm_seq_show,
0237 .start = kcm_seq_start,
0238 .next = kcm_seq_next,
0239 .stop = kcm_seq_stop,
0240 };
0241
0242 static int kcm_stats_seq_show(struct seq_file *seq, void *v)
0243 {
0244 struct kcm_psock_stats psock_stats;
0245 struct kcm_mux_stats mux_stats;
0246 struct strp_aggr_stats strp_stats;
0247 struct kcm_mux *mux;
0248 struct kcm_psock *psock;
0249 struct net *net = seq->private;
0250 struct kcm_net *knet = net_generic(net, kcm_net_id);
0251
0252 memset(&mux_stats, 0, sizeof(mux_stats));
0253 memset(&psock_stats, 0, sizeof(psock_stats));
0254 memset(&strp_stats, 0, sizeof(strp_stats));
0255
0256 mutex_lock(&knet->mutex);
0257
0258 aggregate_mux_stats(&knet->aggregate_mux_stats, &mux_stats);
0259 aggregate_psock_stats(&knet->aggregate_psock_stats,
0260 &psock_stats);
0261 aggregate_strp_stats(&knet->aggregate_strp_stats,
0262 &strp_stats);
0263
0264 list_for_each_entry(mux, &knet->mux_list, kcm_mux_list) {
0265 spin_lock_bh(&mux->lock);
0266 aggregate_mux_stats(&mux->stats, &mux_stats);
0267 aggregate_psock_stats(&mux->aggregate_psock_stats,
0268 &psock_stats);
0269 aggregate_strp_stats(&mux->aggregate_strp_stats,
0270 &strp_stats);
0271 list_for_each_entry(psock, &mux->psocks, psock_list) {
0272 aggregate_psock_stats(&psock->stats, &psock_stats);
0273 save_strp_stats(&psock->strp, &strp_stats);
0274 }
0275
0276 spin_unlock_bh(&mux->lock);
0277 }
0278
0279 mutex_unlock(&knet->mutex);
0280
0281 seq_printf(seq,
0282 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
0283 "MUX",
0284 "RX-Msgs",
0285 "RX-Bytes",
0286 "TX-Msgs",
0287 "TX-Bytes",
0288 "TX-Retries",
0289 "Attach",
0290 "Unattach",
0291 "UnattchRsvd",
0292 "RX-RdyDrops");
0293
0294 seq_printf(seq,
0295 "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
0296 "",
0297 mux_stats.rx_msgs,
0298 mux_stats.rx_bytes,
0299 mux_stats.tx_msgs,
0300 mux_stats.tx_bytes,
0301 mux_stats.tx_retries,
0302 mux_stats.psock_attach,
0303 mux_stats.psock_unattach_rsvd,
0304 mux_stats.psock_unattach,
0305 mux_stats.rx_ready_drops);
0306
0307 seq_printf(seq,
0308 "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
0309 "Psock",
0310 "RX-Msgs",
0311 "RX-Bytes",
0312 "TX-Msgs",
0313 "TX-Bytes",
0314 "Reserved",
0315 "Unreserved",
0316 "RX-Aborts",
0317 "RX-Intr",
0318 "RX-Unrecov",
0319 "RX-MemFail",
0320 "RX-NeedMor",
0321 "RX-BadLen",
0322 "RX-TooBig",
0323 "RX-Timeout",
0324 "TX-Aborts");
0325
0326 seq_printf(seq,
0327 "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
0328 "",
0329 strp_stats.msgs,
0330 strp_stats.bytes,
0331 psock_stats.tx_msgs,
0332 psock_stats.tx_bytes,
0333 psock_stats.reserved,
0334 psock_stats.unreserved,
0335 strp_stats.aborts,
0336 strp_stats.interrupted,
0337 strp_stats.unrecov_intr,
0338 strp_stats.mem_fail,
0339 strp_stats.need_more_hdr,
0340 strp_stats.bad_hdr_len,
0341 strp_stats.msg_too_big,
0342 strp_stats.msg_timeouts,
0343 psock_stats.tx_aborts);
0344
0345 return 0;
0346 }
0347
0348 static int kcm_proc_init_net(struct net *net)
0349 {
0350 if (!proc_create_net_single("kcm_stats", 0444, net->proc_net,
0351 kcm_stats_seq_show, NULL))
0352 goto out_kcm_stats;
0353
0354 if (!proc_create_net("kcm", 0444, net->proc_net, &kcm_seq_ops,
0355 sizeof(struct kcm_proc_mux_state)))
0356 goto out_kcm;
0357
0358 return 0;
0359
0360 out_kcm:
0361 remove_proc_entry("kcm_stats", net->proc_net);
0362 out_kcm_stats:
0363 return -ENOMEM;
0364 }
0365
0366 static void kcm_proc_exit_net(struct net *net)
0367 {
0368 remove_proc_entry("kcm", net->proc_net);
0369 remove_proc_entry("kcm_stats", net->proc_net);
0370 }
0371
0372 static struct pernet_operations kcm_net_ops = {
0373 .init = kcm_proc_init_net,
0374 .exit = kcm_proc_exit_net,
0375 };
0376
0377 int __init kcm_proc_init(void)
0378 {
0379 return register_pernet_subsys(&kcm_net_ops);
0380 }
0381
0382 void __exit kcm_proc_exit(void)
0383 {
0384 unregister_pernet_subsys(&kcm_net_ops);
0385 }
0386
0387 #endif