linux/net/kcm/kcmproc.c
<<
>>
Prefs
   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
  92        return seq_open_net(inode, file, &muxinfo->seq_ops,
  93                           sizeof(struct kcm_proc_mux_state));
  94}
  95
  96static void kcm_format_mux_header(struct seq_file *seq)
  97{
  98        struct net *net = seq_file_net(seq);
  99        struct kcm_net *knet = net_generic(net, kcm_net_id);
 100
 101        seq_printf(seq,
 102                   "*** KCM statistics (%d MUX) ****\n",
 103                   knet->count);
 104
 105        seq_printf(seq,
 106                   "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
 107                   "Object",
 108                   "RX-Msgs",
 109                   "RX-Bytes",
 110                   "TX-Msgs",
 111                   "TX-Bytes",
 112                   "Recv-Q",
 113                   "Rmem",
 114                   "Send-Q",
 115                   "Smem",
 116                   "Status");
 117
 118        /* XXX: pdsts header stuff here */
 119        seq_puts(seq, "\n");
 120}
 121
 122static void kcm_format_sock(struct kcm_sock *kcm, struct seq_file *seq,
 123                            int i, int *len)
 124{
 125        seq_printf(seq,
 126                   "   kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
 127                   kcm->index,
 128                   kcm->stats.rx_msgs,
 129                   kcm->stats.rx_bytes,
 130                   kcm->stats.tx_msgs,
 131                   kcm->stats.tx_bytes,
 132                   kcm->sk.sk_receive_queue.qlen,
 133                   sk_rmem_alloc_get(&kcm->sk),
 134                   kcm->sk.sk_write_queue.qlen,
 135                   "-");
 136
 137        if (kcm->tx_psock)
 138                seq_printf(seq, "Psck-%u ", kcm->tx_psock->index);
 139
 140        if (kcm->tx_wait)
 141                seq_puts(seq, "TxWait ");
 142
 143        if (kcm->tx_wait_more)
 144                seq_puts(seq, "WMore ");
 145
 146        if (kcm->rx_wait)
 147                seq_puts(seq, "RxWait ");
 148
 149        seq_puts(seq, "\n");
 150}
 151
 152static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
 153                             int i, int *len)
 154{
 155        seq_printf(seq,
 156                   "   psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
 157                   psock->index,
 158                   psock->stats.rx_msgs,
 159                   psock->stats.rx_bytes,
 160                   psock->stats.tx_msgs,
 161                   psock->stats.tx_bytes,
 162                   psock->sk->sk_receive_queue.qlen,
 163                   atomic_read(&psock->sk->sk_rmem_alloc),
 164                   psock->sk->sk_write_queue.qlen,
 165                   atomic_read(&psock->sk->sk_wmem_alloc));
 166
 167        if (psock->done)
 168                seq_puts(seq, "Done ");
 169
 170        if (psock->tx_stopped)
 171                seq_puts(seq, "TxStop ");
 172
 173        if (psock->rx_stopped)
 174                seq_puts(seq, "RxStop ");
 175
 176        if (psock->tx_kcm)
 177                seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
 178
 179        if (psock->ready_rx_msg)
 180                seq_puts(seq, "RdyRx ");
 181
 182        seq_puts(seq, "\n");
 183}
 184
 185static void
 186kcm_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
 220static 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
 235static const struct file_operations kcm_seq_fops = {
 236        .owner          = THIS_MODULE,
 237        .open           = kcm_seq_open,
 238        .read           = seq_read,
 239        .llseek         = seq_lseek,
 240        .release        = seq_release_net,
 241};
 242
 243static struct kcm_seq_muxinfo kcm_seq_muxinfo = {
 244        .name           = "kcm",
 245        .seq_fops       = &kcm_seq_fops,
 246        .seq_ops        = {
 247                .show   = kcm_seq_show,
 248                .start  = kcm_seq_start,
 249                .next   = kcm_seq_next,
 250                .stop   = kcm_seq_stop,
 251        }
 252};
 253
 254static int kcm_proc_register(struct net *net, struct kcm_seq_muxinfo *muxinfo)
 255{
 256        struct proc_dir_entry *p;
 257        int rc = 0;
 258
 259        p = proc_create_data(muxinfo->name, S_IRUGO, net->proc_net,
 260                             muxinfo->seq_fops, muxinfo);
 261        if (!p)
 262                rc = -ENOMEM;
 263        return rc;
 264}
 265EXPORT_SYMBOL(kcm_proc_register);
 266
 267static void kcm_proc_unregister(struct net *net,
 268                                struct kcm_seq_muxinfo *muxinfo)
 269{
 270        remove_proc_entry(muxinfo->name, net->proc_net);
 271}
 272EXPORT_SYMBOL(kcm_proc_unregister);
 273
 274static int kcm_stats_seq_show(struct seq_file *seq, void *v)
 275{
 276        struct kcm_psock_stats psock_stats;
 277        struct kcm_mux_stats mux_stats;
 278        struct kcm_mux *mux;
 279        struct kcm_psock *psock;
 280        struct net *net = seq->private;
 281        struct kcm_net *knet = net_generic(net, kcm_net_id);
 282
 283        memset(&mux_stats, 0, sizeof(mux_stats));
 284        memset(&psock_stats, 0, sizeof(psock_stats));
 285
 286        mutex_lock(&knet->mutex);
 287
 288        aggregate_mux_stats(&knet->aggregate_mux_stats, &mux_stats);
 289        aggregate_psock_stats(&knet->aggregate_psock_stats,
 290                              &psock_stats);
 291
 292        list_for_each_entry_rcu(mux, &knet->mux_list, kcm_mux_list) {
 293                spin_lock_bh(&mux->lock);
 294                aggregate_mux_stats(&mux->stats, &mux_stats);
 295                aggregate_psock_stats(&mux->aggregate_psock_stats,
 296                                      &psock_stats);
 297                list_for_each_entry(psock, &mux->psocks, psock_list)
 298                        aggregate_psock_stats(&psock->stats, &psock_stats);
 299                spin_unlock_bh(&mux->lock);
 300        }
 301
 302        mutex_unlock(&knet->mutex);
 303
 304        seq_printf(seq,
 305                   "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
 306                   "MUX",
 307                   "RX-Msgs",
 308                   "RX-Bytes",
 309                   "TX-Msgs",
 310                   "TX-Bytes",
 311                   "TX-Retries",
 312                   "Attach",
 313                   "Unattach",
 314                   "UnattchRsvd",
 315                   "RX-RdyDrops");
 316
 317        seq_printf(seq,
 318                   "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
 319                   "",
 320                   mux_stats.rx_msgs,
 321                   mux_stats.rx_bytes,
 322                   mux_stats.tx_msgs,
 323                   mux_stats.tx_bytes,
 324                   mux_stats.tx_retries,
 325                   mux_stats.psock_attach,
 326                   mux_stats.psock_unattach_rsvd,
 327                   mux_stats.psock_unattach,
 328                   mux_stats.rx_ready_drops);
 329
 330        seq_printf(seq,
 331                   "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
 332                   "Psock",
 333                   "RX-Msgs",
 334                   "RX-Bytes",
 335                   "TX-Msgs",
 336                   "TX-Bytes",
 337                   "Reserved",
 338                   "Unreserved",
 339                   "RX-Aborts",
 340                   "RX-MemFail",
 341                   "RX-NeedMor",
 342                   "RX-BadLen",
 343                   "RX-TooBig",
 344                   "RX-Timeout",
 345                   "TX-Aborts");
 346
 347        seq_printf(seq,
 348                   "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
 349                   "",
 350                   psock_stats.rx_msgs,
 351                   psock_stats.rx_bytes,
 352                   psock_stats.tx_msgs,
 353                   psock_stats.tx_bytes,
 354                   psock_stats.reserved,
 355                   psock_stats.unreserved,
 356                   psock_stats.rx_aborts,
 357                   psock_stats.rx_mem_fail,
 358                   psock_stats.rx_need_more_hdr,
 359                   psock_stats.rx_bad_hdr_len,
 360                   psock_stats.rx_msg_too_big,
 361                   psock_stats.rx_msg_timeouts,
 362                   psock_stats.tx_aborts);
 363
 364        return 0;
 365}
 366
 367static int kcm_stats_seq_open(struct inode *inode, struct file *file)
 368{
 369        return single_open_net(inode, file, kcm_stats_seq_show);
 370}
 371
 372static const struct file_operations kcm_stats_seq_fops = {
 373        .owner   = THIS_MODULE,
 374        .open    = kcm_stats_seq_open,
 375        .read    = seq_read,
 376        .llseek  = seq_lseek,
 377        .release = single_release_net,
 378};
 379
 380static int kcm_proc_init_net(struct net *net)
 381{
 382        int err;
 383
 384        if (!proc_create("kcm_stats", S_IRUGO, net->proc_net,
 385                         &kcm_stats_seq_fops)) {
 386                err = -ENOMEM;
 387                goto out_kcm_stats;
 388        }
 389
 390        err = kcm_proc_register(net, &kcm_seq_muxinfo);
 391        if (err)
 392                goto out_kcm;
 393
 394        return 0;
 395
 396out_kcm:
 397        remove_proc_entry("kcm_stats", net->proc_net);
 398out_kcm_stats:
 399        return err;
 400}
 401
 402static void kcm_proc_exit_net(struct net *net)
 403{
 404        kcm_proc_unregister(net, &kcm_seq_muxinfo);
 405        remove_proc_entry("kcm_stats", net->proc_net);
 406}
 407
 408static struct pernet_operations kcm_net_ops = {
 409        .init = kcm_proc_init_net,
 410        .exit = kcm_proc_exit_net,
 411};
 412
 413int __init kcm_proc_init(void)
 414{
 415        return register_pernet_subsys(&kcm_net_ops);
 416}
 417
 418void __exit kcm_proc_exit(void)
 419{
 420        unregister_pernet_subsys(&kcm_net_ops);
 421}
 422
 423#endif /* CONFIG_PROC_FS */
 424