Commit 452b9318 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] Convert /proc/net/ip6_flowlabel to seq_file.

parent cc991563
......@@ -19,6 +19,7 @@
#include <linux/in6.h>
#include <linux/route.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
......@@ -554,66 +555,132 @@ int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen)
#ifdef CONFIG_PROC_FS
struct ip6fl_iter_state {
int bucket;
};
static int ip6_fl_read_proc(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
{
off_t pos=0;
off_t begin=0;
int len=0;
int i, k;
struct ip6_flowlabel *fl;
#define ip6fl_seq_private(seq) ((struct ip6fl_iter_state *)&(seq)->private)
len+= sprintf(buffer,"Label S Owner Users Linger Expires "
"Dst Opt\n");
static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
{
struct ip6_flowlabel *fl = NULL;
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
read_lock_bh(&ip6_fl_lock);
for (i=0; i<=FL_HASH_MASK; i++) {
for (fl = fl_ht[i]; fl; fl = fl->next) {
len+=sprintf(buffer+len,"%05X %-1d %-6d %-6d %-6d %-8ld ",
(unsigned)ntohl(fl->label),
fl->share,
(unsigned)fl->owner,
atomic_read(&fl->users),
fl->linger/HZ,
(long)(fl->expires - jiffies)/HZ);
for (k=0; k<16; k++)
len+=sprintf(buffer+len, "%02x", fl->dst.s6_addr[k]);
buffer[len++]=' ';
len+=sprintf(buffer+len, "%-4d", fl->opt ? fl->opt->opt_nflen : 0);
buffer[len++]='\n';
pos=begin+len;
if(pos<offset) {
len=0;
begin=pos;
}
if(pos>offset+length)
goto done;
for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) {
if (fl_ht[state->bucket]) {
fl = fl_ht[state->bucket];
break;
}
}
*eof = 1;
return fl;
}
done:
static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl)
{
struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
fl = fl->next;
while (!fl) {
if (++state->bucket <= FL_HASH_MASK)
fl = fl_ht[state->bucket];
}
return fl;
}
static struct ip6_flowlabel *ip6fl_get_idx(struct seq_file *seq, loff_t pos)
{
struct ip6_flowlabel *fl = ip6fl_get_first(seq);
if (fl)
while (pos && (fl = ip6fl_get_next(seq, fl)) != NULL)
--pos;
return pos ? NULL : fl;
}
static void *ip6fl_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock_bh(&ip6_fl_lock);
return *pos ? ip6fl_get_idx(seq, *pos) : (void *)1;
}
static void *ip6fl_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ip6_flowlabel *fl;
if (v == (void *)1)
fl = ip6fl_get_first(seq);
else
fl = ip6fl_get_next(seq, v);
++*pos;
return fl;
}
static void ip6fl_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&ip6_fl_lock);
*start=buffer+(offset-begin);
len-=(offset-begin);
if(len>length)
len=length;
if(len<0)
len=0;
return len;
}
static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
{
while(fl) {
seq_printf(seq,
"%05X %-1d %-6d %-6d %-6d %-8ld "
"%02x%02x%02x%02x%02x%02x%02x%02x "
"%-4d\n",
(unsigned)ntohl(fl->label),
fl->share,
(unsigned)fl->owner,
atomic_read(&fl->users),
fl->linger/HZ,
(long)(fl->expires - jiffies)/HZ,
NIP6(fl->dst),
fl->opt ? fl->opt->opt_nflen : 0);
fl = fl->next;
}
}
static int ip6fl_seq_show(struct seq_file *seq, void *v)
{
if (v == (void *)1)
seq_printf(seq, "Label S Owner Users Linger Expires "
"Dst Opt\n");
else
ip6fl_fl_seq_show(seq, v);
return 0;
}
static struct seq_operations ip6fl_seq_ops = {
.start = ip6fl_seq_start,
.next = ip6fl_seq_next,
.stop = ip6fl_seq_stop,
.show = ip6fl_seq_show,
};
static int ip6fl_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &ip6fl_seq_ops);
}
static struct file_operations ip6fl_seq_fops = {
.owner = THIS_MODULE,
.open = ip6fl_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif
void ip6_flowlabel_init()
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *p;
#endif
init_timer(&ip6_fl_gc_timer);
ip6_fl_gc_timer.function = ip6_fl_gc;
#ifdef CONFIG_PROC_FS
create_proc_read_entry("net/ip6_flowlabel", 0, 0, ip6_fl_read_proc, NULL);
p = create_proc_entry("ip6_flowlabel", S_IRUGO, proc_net);
if (p)
p->proc_fops = &ip6fl_seq_fops;
#endif
}
......@@ -621,6 +688,6 @@ void ip6_flowlabel_cleanup()
{
del_timer(&ip6_fl_gc_timer);
#ifdef CONFIG_PROC_FS
remove_proc_entry("net/ip6_flowlabel", 0);
proc_net_remove("ip6_flowlabel");
#endif
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment