linux/net/kcm/kcmproc.c
<<
>>
Prefs
   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
  18static 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
  27static 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
  35static 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
  49static 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
  61static 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
  72static void kcm_seq_stop(struct seq_file *seq, void *v)
  73        __releases(rcu)
  74{
  75        rcu_read_unlock();
  76}
  77
  78struct kcm_proc_mux_state {
  79        struct seq_net_private p;
  80        int idx;
  81};
  82
  83static 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
 109static 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
 139static 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
 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 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
 242static 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
 348static 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
 360out_kcm:
 361        remove_proc_entry("kcm_stats", net->proc_net);
 362out_kcm_stats:
 363        return -ENOMEM;
 364}
 365
 366static 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
 372static struct pernet_operations kcm_net_ops = {
 373        .init = kcm_proc_init_net,
 374        .exit = kcm_proc_exit_net,
 375};
 376
 377int __init kcm_proc_init(void)
 378{
 379        return register_pernet_subsys(&kcm_net_ops);
 380}
 381
 382void __exit kcm_proc_exit(void)
 383{
 384        unregister_pernet_subsys(&kcm_net_ops);
 385}
 386
 387#endif /* CONFIG_PROC_FS */
 388