Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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     /* XXX: pdsts header stuff here */
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     /* mux information */
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     /* kcm sock information */
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 /* CONFIG_PROC_FS */