1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/kernel.h> 3 #include <linux/proc_fs.h> 4 #include <net/netfilter/nf_flow_table.h> 5 6 static void *nf_flow_table_cpu_seq_start(struct seq_file *seq, loff_t *pos) 7 { 8 struct net *net = seq_file_net(seq); 9 int cpu; 10 11 if (*pos == 0) 12 return SEQ_START_TOKEN; 13 14 for (cpu = *pos - 1; cpu < nr_cpu_ids; ++cpu) { 15 if (!cpu_possible(cpu)) 16 continue; 17 *pos = cpu + 1; 18 return per_cpu_ptr(net->ft.stat, cpu); 19 } 20 21 return NULL; 22 } 23 24 static void *nf_flow_table_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) 25 { 26 struct net *net = seq_file_net(seq); 27 int cpu; 28 29 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { 30 if (!cpu_possible(cpu)) 31 continue; 32 *pos = cpu + 1; 33 return per_cpu_ptr(net->ft.stat, cpu); 34 } 35 (*pos)++; 36 return NULL; 37 } 38 39 static void nf_flow_table_cpu_seq_stop(struct seq_file *seq, void *v) 40 { 41 } 42 43 static int nf_flow_table_cpu_seq_show(struct seq_file *seq, void *v) 44 { 45 const struct nf_flow_table_stat *st = v; 46 47 if (v == SEQ_START_TOKEN) { 48 seq_puts(seq, "wq_add wq_del wq_stats\n"); 49 return 0; 50 } 51 52 seq_printf(seq, "%8d %8d %8d\n", 53 st->count_wq_add, 54 st->count_wq_del, 55 st->count_wq_stats 56 ); 57 return 0; 58 } 59 60 static const struct seq_operations nf_flow_table_cpu_seq_ops = { 61 .start = nf_flow_table_cpu_seq_start, 62 .next = nf_flow_table_cpu_seq_next, 63 .stop = nf_flow_table_cpu_seq_stop, 64 .show = nf_flow_table_cpu_seq_show, 65 }; 66 67 int nf_flow_table_init_proc(struct net *net) 68 { 69 struct proc_dir_entry *pde; 70 71 pde = proc_create_net("nf_flowtable", 0444, net->proc_net_stat, 72 &nf_flow_table_cpu_seq_ops, 73 sizeof(struct seq_net_private)); 74 return pde ? 0 : -ENOMEM; 75 } 76 77 void nf_flow_table_fini_proc(struct net *net) 78 { 79 remove_proc_entry("nf_flowtable", net->proc_net_stat); 80 } 81