// SPDX-License-Identifier: GPL-2.0-only #include #include #include static void *nf_flow_table_cpu_seq_start(struct seq_file *seq, loff_t *pos) { struct net *net = seq_file_net(seq); int cpu; if (*pos == 0) return SEQ_START_TOKEN; for (cpu = *pos - 1; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu + 1; return per_cpu_ptr(net->ft.stat, cpu); } return NULL; } static void *nf_flow_table_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct net *net = seq_file_net(seq); int cpu; for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { if (!cpu_possible(cpu)) continue; *pos = cpu + 1; return per_cpu_ptr(net->ft.stat, cpu); } (*pos)++; return NULL; } static void nf_flow_table_cpu_seq_stop(struct seq_file *seq, void *v) { } static int nf_flow_table_cpu_seq_show(struct seq_file *seq, void *v) { const struct nf_flow_table_stat *st = v; if (v == SEQ_START_TOKEN) { seq_puts(seq, "wq_add wq_del wq_stats\n"); return 0; } seq_printf(seq, "%8d %8d %8d\n", st->count_wq_add, st->count_wq_del, st->count_wq_stats ); return 0; } static const struct seq_operations nf_flow_table_cpu_seq_ops = { .start = nf_flow_table_cpu_seq_start, .next = nf_flow_table_cpu_seq_next, .stop = nf_flow_table_cpu_seq_stop, .show = nf_flow_table_cpu_seq_show, }; int nf_flow_table_init_proc(struct net *net) { struct proc_dir_entry *pde; pde = proc_create_net("nf_flowtable", 0444, net->proc_net_stat, &nf_flow_table_cpu_seq_ops, sizeof(struct seq_net_private)); return pde ? 0 : -ENOMEM; } void nf_flow_table_fini_proc(struct net *net) { remove_proc_entry("nf_flowtable", net->proc_net_stat); }