Commit 8b90fc7e authored by Benjamin Thery's avatar Benjamin Thery Committed by David S. Miller

netns: ip6mr: declare ip6mr /proc/net entries per-namespace

Declare IPv6 multicast forwarding /proc/net entries per-namespace:
/proc/net/ip6_mr_vif
/proc/net/ip6_mr_cache

Changelog
=========
V2:
* In routine ipmr_mfc_seq_idx(), only match entries belonging to current
  netns in mfc_unres_queue list.
Signed-off-by: default avatarBenjamin Thery <benjamin.thery@bull.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 950d5704
...@@ -90,19 +90,21 @@ static struct timer_list ipmr_expire_timer; ...@@ -90,19 +90,21 @@ static struct timer_list ipmr_expire_timer;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct ipmr_mfc_iter { struct ipmr_mfc_iter {
struct seq_net_private p;
struct mfc6_cache **cache; struct mfc6_cache **cache;
int ct; int ct;
}; };
static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net,
struct ipmr_mfc_iter *it, loff_t pos)
{ {
struct mfc6_cache *mfc; struct mfc6_cache *mfc;
it->cache = init_net.ipv6.mfc6_cache_array; it->cache = net->ipv6.mfc6_cache_array;
read_lock(&mrt_lock); read_lock(&mrt_lock);
for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) for (it->ct = 0; it->ct < MFC6_LINES; it->ct++)
for (mfc = init_net.ipv6.mfc6_cache_array[it->ct]; for (mfc = net->ipv6.mfc6_cache_array[it->ct];
mfc; mfc = mfc->next) mfc; mfc = mfc->next)
if (pos-- == 0) if (pos-- == 0)
return mfc; return mfc;
...@@ -111,7 +113,8 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) ...@@ -111,7 +113,8 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
it->cache = &mfc_unres_queue; it->cache = &mfc_unres_queue;
spin_lock_bh(&mfc_unres_lock); spin_lock_bh(&mfc_unres_lock);
for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) for (mfc = mfc_unres_queue; mfc; mfc = mfc->next)
if (pos-- == 0) if (net_eq(mfc6_net(mfc), net) &&
pos-- == 0)
return mfc; return mfc;
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
...@@ -127,17 +130,19 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) ...@@ -127,17 +130,19 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
*/ */
struct ipmr_vif_iter { struct ipmr_vif_iter {
struct seq_net_private p;
int ct; int ct;
}; };
static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, static struct mif_device *ip6mr_vif_seq_idx(struct net *net,
struct ipmr_vif_iter *iter,
loff_t pos) loff_t pos)
{ {
for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) { for (iter->ct = 0; iter->ct < net->ipv6.maxvif; ++iter->ct) {
if (!MIF_EXISTS(&init_net, iter->ct)) if (!MIF_EXISTS(net, iter->ct))
continue; continue;
if (pos-- == 0) if (pos-- == 0)
return &init_net.ipv6.vif6_table[iter->ct]; return &net->ipv6.vif6_table[iter->ct];
} }
return NULL; return NULL;
} }
...@@ -145,23 +150,26 @@ static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, ...@@ -145,23 +150,26 @@ static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(mrt_lock) __acquires(mrt_lock)
{ {
struct net *net = seq_file_net(seq);
read_lock(&mrt_lock); read_lock(&mrt_lock);
return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1) return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1)
: SEQ_START_TOKEN); : SEQ_START_TOKEN;
} }
static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct ipmr_vif_iter *iter = seq->private; struct ipmr_vif_iter *iter = seq->private;
struct net *net = seq_file_net(seq);
++*pos; ++*pos;
if (v == SEQ_START_TOKEN) if (v == SEQ_START_TOKEN)
return ip6mr_vif_seq_idx(iter, 0); return ip6mr_vif_seq_idx(net, iter, 0);
while (++iter->ct < init_net.ipv6.maxvif) { while (++iter->ct < net->ipv6.maxvif) {
if (!MIF_EXISTS(&init_net, iter->ct)) if (!MIF_EXISTS(net, iter->ct))
continue; continue;
return &init_net.ipv6.vif6_table[iter->ct]; return &net->ipv6.vif6_table[iter->ct];
} }
return NULL; return NULL;
} }
...@@ -174,6 +182,8 @@ static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v) ...@@ -174,6 +182,8 @@ static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
{ {
struct net *net = seq_file_net(seq);
if (v == SEQ_START_TOKEN) { if (v == SEQ_START_TOKEN) {
seq_puts(seq, seq_puts(seq,
"Interface BytesIn PktsIn BytesOut PktsOut Flags\n"); "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
...@@ -183,7 +193,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) ...@@ -183,7 +193,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, seq_printf(seq,
"%2td %-10s %8ld %7ld %8ld %7ld %05X\n", "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
vif - init_net.ipv6.vif6_table, vif - net->ipv6.vif6_table,
name, vif->bytes_in, vif->pkt_in, name, vif->bytes_in, vif->pkt_in,
vif->bytes_out, vif->pkt_out, vif->bytes_out, vif->pkt_out,
vif->flags); vif->flags);
...@@ -200,7 +210,7 @@ static struct seq_operations ip6mr_vif_seq_ops = { ...@@ -200,7 +210,7 @@ static struct seq_operations ip6mr_vif_seq_ops = {
static int ip6mr_vif_open(struct inode *inode, struct file *file) static int ip6mr_vif_open(struct inode *inode, struct file *file)
{ {
return seq_open_private(file, &ip6mr_vif_seq_ops, return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
sizeof(struct ipmr_vif_iter)); sizeof(struct ipmr_vif_iter));
} }
...@@ -209,24 +219,27 @@ static struct file_operations ip6mr_vif_fops = { ...@@ -209,24 +219,27 @@ static struct file_operations ip6mr_vif_fops = {
.open = ip6mr_vif_open, .open = ip6mr_vif_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = seq_release_net,
}; };
static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
{ {
return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) struct net *net = seq_file_net(seq);
: SEQ_START_TOKEN);
return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
: SEQ_START_TOKEN;
} }
static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct mfc6_cache *mfc = v; struct mfc6_cache *mfc = v;
struct ipmr_mfc_iter *it = seq->private; struct ipmr_mfc_iter *it = seq->private;
struct net *net = seq_file_net(seq);
++*pos; ++*pos;
if (v == SEQ_START_TOKEN) if (v == SEQ_START_TOKEN)
return ipmr_mfc_seq_idx(seq->private, 0); return ipmr_mfc_seq_idx(net, seq->private, 0);
if (mfc->next) if (mfc->next)
return mfc->next; return mfc->next;
...@@ -234,10 +247,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -234,10 +247,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (it->cache == &mfc_unres_queue) if (it->cache == &mfc_unres_queue)
goto end_of_list; goto end_of_list;
BUG_ON(it->cache != init_net.ipv6.mfc6_cache_array); BUG_ON(it->cache != net->ipv6.mfc6_cache_array);
while (++it->ct < MFC6_LINES) { while (++it->ct < MFC6_LINES) {
mfc = init_net.ipv6.mfc6_cache_array[it->ct]; mfc = net->ipv6.mfc6_cache_array[it->ct];
if (mfc) if (mfc)
return mfc; return mfc;
} }
...@@ -262,16 +275,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -262,16 +275,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
{ {
struct ipmr_mfc_iter *it = seq->private; struct ipmr_mfc_iter *it = seq->private;
struct net *net = seq_file_net(seq);
if (it->cache == &mfc_unres_queue) if (it->cache == &mfc_unres_queue)
spin_unlock_bh(&mfc_unres_lock); spin_unlock_bh(&mfc_unres_lock);
else if (it->cache == init_net.ipv6.mfc6_cache_array) else if (it->cache == net->ipv6.mfc6_cache_array)
read_unlock(&mrt_lock); read_unlock(&mrt_lock);
} }
static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
{ {
int n; int n;
struct net *net = seq_file_net(seq);
if (v == SEQ_START_TOKEN) { if (v == SEQ_START_TOKEN) {
seq_puts(seq, seq_puts(seq,
...@@ -293,7 +308,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) ...@@ -293,7 +308,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
mfc->mfc_un.res.wrong_if); mfc->mfc_un.res.wrong_if);
for (n = mfc->mfc_un.res.minvif; for (n = mfc->mfc_un.res.minvif;
n < mfc->mfc_un.res.maxvif; n++) { n < mfc->mfc_un.res.maxvif; n++) {
if (MIF_EXISTS(&init_net, n) && if (MIF_EXISTS(net, n) &&
mfc->mfc_un.res.ttls[n] < 255) mfc->mfc_un.res.ttls[n] < 255)
seq_printf(seq, seq_printf(seq,
" %2d:%-3d", " %2d:%-3d",
...@@ -319,7 +334,7 @@ static struct seq_operations ipmr_mfc_seq_ops = { ...@@ -319,7 +334,7 @@ static struct seq_operations ipmr_mfc_seq_ops = {
static int ipmr_mfc_open(struct inode *inode, struct file *file) static int ipmr_mfc_open(struct inode *inode, struct file *file)
{ {
return seq_open_private(file, &ipmr_mfc_seq_ops, return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
sizeof(struct ipmr_mfc_iter)); sizeof(struct ipmr_mfc_iter));
} }
...@@ -328,7 +343,7 @@ static struct file_operations ip6mr_mfc_fops = { ...@@ -328,7 +343,7 @@ static struct file_operations ip6mr_mfc_fops = {
.open = ipmr_mfc_open, .open = ipmr_mfc_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = seq_release_net,
}; };
#endif #endif
...@@ -983,8 +998,22 @@ static int __net_init ip6mr_net_init(struct net *net) ...@@ -983,8 +998,22 @@ static int __net_init ip6mr_net_init(struct net *net)
#ifdef CONFIG_IPV6_PIMSM_V2 #ifdef CONFIG_IPV6_PIMSM_V2
net->ipv6.mroute_reg_vif_num = -1; net->ipv6.mroute_reg_vif_num = -1;
#endif #endif
#ifdef CONFIG_PROC_FS
err = -ENOMEM;
if (!proc_net_fops_create(net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
goto proc_vif_fail;
if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops))
goto proc_cache_fail;
#endif
return 0; return 0;
#ifdef CONFIG_PROC_FS
proc_cache_fail:
proc_net_remove(net, "ip6_mr_vif");
proc_vif_fail:
kfree(net->ipv6.mfc6_cache_array);
#endif
fail_mfc6_cache: fail_mfc6_cache:
kfree(net->ipv6.vif6_table); kfree(net->ipv6.vif6_table);
fail: fail:
...@@ -993,6 +1022,10 @@ fail: ...@@ -993,6 +1022,10 @@ fail:
static void __net_exit ip6mr_net_exit(struct net *net) static void __net_exit ip6mr_net_exit(struct net *net)
{ {
#ifdef CONFIG_PROC_FS
proc_net_remove(net, "ip6_mr_cache");
proc_net_remove(net, "ip6_mr_vif");
#endif
kfree(net->ipv6.mfc6_cache_array); kfree(net->ipv6.mfc6_cache_array);
kfree(net->ipv6.vif6_table); kfree(net->ipv6.vif6_table);
} }
...@@ -1021,21 +1054,7 @@ int __init ip6_mr_init(void) ...@@ -1021,21 +1054,7 @@ int __init ip6_mr_init(void)
err = register_netdevice_notifier(&ip6_mr_notifier); err = register_netdevice_notifier(&ip6_mr_notifier);
if (err) if (err)
goto reg_notif_fail; goto reg_notif_fail;
#ifdef CONFIG_PROC_FS
err = -ENOMEM;
if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
goto proc_vif_fail;
if (!proc_net_fops_create(&init_net, "ip6_mr_cache",
0, &ip6mr_mfc_fops))
goto proc_cache_fail;
#endif
return 0; return 0;
#ifdef CONFIG_PROC_FS
proc_cache_fail:
proc_net_remove(&init_net, "ip6_mr_vif");
proc_vif_fail:
unregister_netdevice_notifier(&ip6_mr_notifier);
#endif
reg_notif_fail: reg_notif_fail:
del_timer(&ipmr_expire_timer); del_timer(&ipmr_expire_timer);
unregister_pernet_subsys(&ip6mr_net_ops); unregister_pernet_subsys(&ip6mr_net_ops);
...@@ -1046,10 +1065,6 @@ reg_pernet_fail: ...@@ -1046,10 +1065,6 @@ reg_pernet_fail:
void ip6_mr_cleanup(void) void ip6_mr_cleanup(void)
{ {
#ifdef CONFIG_PROC_FS
proc_net_remove(&init_net, "ip6_mr_cache");
proc_net_remove(&init_net, "ip6_mr_vif");
#endif
unregister_netdevice_notifier(&ip6_mr_notifier); unregister_netdevice_notifier(&ip6_mr_notifier);
del_timer(&ipmr_expire_timer); del_timer(&ipmr_expire_timer);
unregister_pernet_subsys(&ip6mr_net_ops); unregister_pernet_subsys(&ip6mr_net_ops);
......
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