* [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace
@ 2008-12-08 16:01 Benjamin Thery
2008-12-08 16:01 ` [PATCH 1/8] netns: ip6mr: allocate mroute6_socket per-namespace Benjamin Thery
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:01 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
This patchset introduces the support for network namespaces in IPv6
multicast forwarding code (net/ipv6/ip6mr.c).
The first patches in the series moves global data from ip6mr.c into
struct netns_ipv6 to prepare netns support. Data are still referenced in
init_net only. One of these patches makes the related /proc entries
per-namespace.
The last patch does the main job and enables the network namespace support
by replacing all the init_net references with the proper net retrieved
from sockets or net devices.
The patchset applies on top of net-next-2.6
Regards,
Benjamin
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/8] netns: ip6mr: allocate mroute6_socket per-namespace.
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
@ 2008-12-08 16:01 ` Benjamin Thery
2008-12-08 16:01 ` [PATCH 2/8] netns: ip6mr: dynamically allocates vif6_table Benjamin Thery
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:01 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Preliminary work to make IPv6 multicast forwarding netns-aware.
Make IPv6 multicast forwarding mroute6_socket per-namespace,
moves it into struct netns_ipv6.
At the moment, mroute6_socket is only referenced in init_net.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/linux/mroute6.h | 8 ++++++--
include/net/netns/ipv6.h | 3 +++
net/ipv6/ip6_output.c | 3 ++-
net/ipv6/ip6mr.c | 22 ++++++++++------------
4 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 6f4c180..2cd9901 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -117,6 +117,7 @@ struct sioc_mif_req6
#include <linux/pim.h>
#include <linux/skbuff.h> /* for struct sk_buff_head */
+#include <net/net_namespace.h>
#ifdef CONFIG_IPV6_MROUTE
static inline int ip6_mroute_opt(int opt)
@@ -232,10 +233,13 @@ struct rtmsg;
extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
#ifdef CONFIG_IPV6_MROUTE
-extern struct sock *mroute6_socket;
+static inline struct sock *mroute6_socket(struct net *net)
+{
+ return net->ipv6.mroute6_sk;
+}
extern int ip6mr_sk_done(struct sock *sk);
#else
-#define mroute6_socket NULL
+static inline struct sock *mroute6_socket(struct net *net) { return NULL; }
static inline int ip6mr_sk_done(struct sock *sk) { return 0; }
#endif
#endif
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 2932721..8a0a67d 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -55,5 +55,8 @@ struct netns_ipv6 {
struct sock *ndisc_sk;
struct sock *tcp_sk;
struct sock *igmp_sk;
+#ifdef CONFIG_IPV6_MROUTE
+ struct sock *mroute6_sk;
+#endif
};
#endif
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7d92fd9..4b15938 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -137,7 +137,8 @@ static int ip6_output2(struct sk_buff *skb)
struct inet6_dev *idev = ip6_dst_idev(skb->dst);
if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
- ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
+ ((mroute6_socket(dev_net(dev)) &&
+ !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
&ipv6_hdr(skb)->saddr))) {
struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d1008e6..02163db 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -49,9 +49,6 @@
#include <net/addrconf.h>
#include <linux/netfilter_ipv6.h>
-struct sock *mroute6_socket;
-
-
/* Big lock, protecting vif table, mrt cache and mroute socket state.
Note that the changes are semaphored via rtnl_lock.
*/
@@ -820,7 +817,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
skb_pull(skb, sizeof(struct ipv6hdr));
}
- if (mroute6_socket == NULL) {
+ if (init_net.ipv6.mroute6_sk == NULL) {
kfree_skb(skb);
return -EINVAL;
}
@@ -828,7 +825,8 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
/*
* Deliver to user space multicast routing algorithms
*/
- if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) {
+ ret = sock_queue_rcv_skb(init_net.ipv6.mroute6_sk, skb);
+ if (ret < 0) {
if (net_ratelimit())
printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
kfree_skb(skb);
@@ -1145,8 +1143,8 @@ static int ip6mr_sk_init(struct sock *sk)
rtnl_lock();
write_lock_bh(&mrt_lock);
- if (likely(mroute6_socket == NULL))
- mroute6_socket = sk;
+ if (likely(init_net.ipv6.mroute6_sk == NULL))
+ init_net.ipv6.mroute6_sk = sk;
else
err = -EADDRINUSE;
write_unlock_bh(&mrt_lock);
@@ -1161,9 +1159,9 @@ int ip6mr_sk_done(struct sock *sk)
int err = 0;
rtnl_lock();
- if (sk == mroute6_socket) {
+ if (sk == init_net.ipv6.mroute6_sk) {
write_lock_bh(&mrt_lock);
- mroute6_socket = NULL;
+ init_net.ipv6.mroute6_sk = NULL;
write_unlock_bh(&mrt_lock);
mroute_clean_tables(sk);
@@ -1189,7 +1187,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
mifi_t mifi;
if (optname != MRT6_INIT) {
- if (sk != mroute6_socket && !capable(CAP_NET_ADMIN))
+ if (sk != init_net.ipv6.mroute6_sk && !capable(CAP_NET_ADMIN))
return -EACCES;
}
@@ -1214,7 +1212,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
if (vif.mif6c_mifi >= MAXMIFS)
return -ENFILE;
rtnl_lock();
- ret = mif6_add(&vif, sk == mroute6_socket);
+ ret = mif6_add(&vif, sk == init_net.ipv6.mroute6_sk);
rtnl_unlock();
return ret;
@@ -1242,7 +1240,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
if (optname == MRT6_DEL_MFC)
ret = ip6mr_mfc_delete(&mfc);
else
- ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket);
+ ret = ip6mr_mfc_add(&mfc, sk == init_net.ipv6.mroute6_sk);
rtnl_unlock();
return ret;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/8] netns: ip6mr: dynamically allocates vif6_table
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
2008-12-08 16:01 ` [PATCH 1/8] netns: ip6mr: allocate mroute6_socket per-namespace Benjamin Thery
@ 2008-12-08 16:01 ` Benjamin Thery
2008-12-08 16:01 ` [PATCH 3/8] netns: ip6mr: Dynamically allocates mfc6_cache_array Benjamin Thery
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:01 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Preliminary work to make IPv6 multicast forwarding netns-aware.
Dynamically allocates interface table vif6_table and moves it to
struct netns_ipv6, and updates MIF_EXISTS() macro.
At the moment, vif6_table is only referenced in init_net.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/net/netns/ipv6.h | 2 +
net/ipv6/ip6mr.c | 107 +++++++++++++++++++++++++++++-----------------
2 files changed, 70 insertions(+), 39 deletions(-)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 8a0a67d..4ab0cb0 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -57,6 +57,8 @@ struct netns_ipv6 {
struct sock *igmp_sk;
#ifdef CONFIG_IPV6_MROUTE
struct sock *mroute6_sk;
+ struct mif_device *vif6_table;
+ int maxvif;
#endif
};
#endif
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 02163db..bae3ef6 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -59,10 +59,7 @@ static DEFINE_RWLOCK(mrt_lock);
* Multicast router control variables
*/
-static struct mif_device vif6_table[MAXMIFS]; /* Devices */
-static int maxvif;
-
-#define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL)
+#define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL)
static int mroute_do_assert; /* Set in PIM assert */
#ifdef CONFIG_IPV6_PIMSM_V2
@@ -145,11 +142,11 @@ struct ipmr_vif_iter {
static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
loff_t pos)
{
- for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
- if (!MIF_EXISTS(iter->ct))
+ for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) {
+ if (!MIF_EXISTS(&init_net, iter->ct))
continue;
if (pos-- == 0)
- return &vif6_table[iter->ct];
+ return &init_net.ipv6.vif6_table[iter->ct];
}
return NULL;
}
@@ -170,10 +167,10 @@ static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (v == SEQ_START_TOKEN)
return ip6mr_vif_seq_idx(iter, 0);
- while (++iter->ct < maxvif) {
- if (!MIF_EXISTS(iter->ct))
+ while (++iter->ct < init_net.ipv6.maxvif) {
+ if (!MIF_EXISTS(&init_net, iter->ct))
continue;
- return &vif6_table[iter->ct];
+ return &init_net.ipv6.vif6_table[iter->ct];
}
return NULL;
}
@@ -195,7 +192,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
seq_printf(seq,
"%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
- vif - vif6_table,
+ vif - init_net.ipv6.vif6_table,
name, vif->bytes_in, vif->pkt_in,
vif->bytes_out, vif->pkt_out,
vif->flags);
@@ -305,7 +302,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
mfc->mfc_un.res.wrong_if);
for (n = mfc->mfc_un.res.minvif;
n < mfc->mfc_un.res.maxvif; n++) {
- if (MIF_EXISTS(n) &&
+ if (MIF_EXISTS(&init_net, n) &&
mfc->mfc_un.res.ttls[n] < 255)
seq_printf(seq,
" %2d:%-3d",
@@ -374,7 +371,7 @@ static int pim6_rcv(struct sk_buff *skb)
read_lock(&mrt_lock);
if (reg_vif_num >= 0)
- reg_dev = vif6_table[reg_vif_num].dev;
+ reg_dev = init_net.ipv6.vif6_table[reg_vif_num].dev;
if (reg_dev)
dev_hold(reg_dev);
read_unlock(&mrt_lock);
@@ -470,10 +467,10 @@ static int mif6_delete(int vifi)
{
struct mif_device *v;
struct net_device *dev;
- if (vifi < 0 || vifi >= maxvif)
+ if (vifi < 0 || vifi >= init_net.ipv6.maxvif)
return -EADDRNOTAVAIL;
- v = &vif6_table[vifi];
+ v = &init_net.ipv6.vif6_table[vifi];
write_lock_bh(&mrt_lock);
dev = v->dev;
@@ -489,13 +486,13 @@ static int mif6_delete(int vifi)
reg_vif_num = -1;
#endif
- if (vifi + 1 == maxvif) {
+ if (vifi + 1 == init_net.ipv6.maxvif) {
int tmp;
for (tmp = vifi - 1; tmp >= 0; tmp--) {
- if (MIF_EXISTS(tmp))
+ if (MIF_EXISTS(&init_net, tmp))
break;
}
- maxvif = tmp + 1;
+ init_net.ipv6.maxvif = tmp + 1;
}
write_unlock_bh(&mrt_lock);
@@ -586,8 +583,9 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
cache->mfc_un.res.maxvif = 0;
memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
- for (vifi = 0; vifi < maxvif; vifi++) {
- if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
+ for (vifi = 0; vifi < init_net.ipv6.maxvif; vifi++) {
+ if (MIF_EXISTS(&init_net, vifi) &&
+ ttls[vifi] && ttls[vifi] < 255) {
cache->mfc_un.res.ttls[vifi] = ttls[vifi];
if (cache->mfc_un.res.minvif > vifi)
cache->mfc_un.res.minvif = vifi;
@@ -600,12 +598,12 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
static int mif6_add(struct mif6ctl *vifc, int mrtsock)
{
int vifi = vifc->mif6c_mifi;
- struct mif_device *v = &vif6_table[vifi];
+ struct mif_device *v = &init_net.ipv6.vif6_table[vifi];
struct net_device *dev;
int err;
/* Is vif busy ? */
- if (MIF_EXISTS(vifi))
+ if (MIF_EXISTS(&init_net, vifi))
return -EADDRINUSE;
switch (vifc->mif6c_flags) {
@@ -665,8 +663,8 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
if (v->flags & MIFF_REGISTER)
reg_vif_num = vifi;
#endif
- if (vifi + 1 > maxvif)
- maxvif = vifi + 1;
+ if (vifi + 1 > init_net.ipv6.maxvif)
+ init_net.ipv6.maxvif = vifi + 1;
write_unlock_bh(&mrt_lock);
return 0;
}
@@ -946,8 +944,8 @@ static int ip6mr_device_event(struct notifier_block *this,
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;
- v = &vif6_table[0];
- for (ct = 0; ct < maxvif; ct++, v++) {
+ v = &init_net.ipv6.vif6_table[0];
+ for (ct = 0; ct < init_net.ipv6.maxvif; ct++, v++) {
if (v->dev == dev)
mif6_delete(ct);
}
@@ -962,6 +960,30 @@ static struct notifier_block ip6_mr_notifier = {
* Setup for IP multicast routing
*/
+static int __net_init ip6mr_net_init(struct net *net)
+{
+ int err = 0;
+
+ net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device),
+ GFP_KERNEL);
+ if (!net->ipv6.vif6_table) {
+ err = -ENOMEM;
+ goto fail;
+ }
+fail:
+ return err;
+}
+
+static void __net_exit ip6mr_net_exit(struct net *net)
+{
+ kfree(net->ipv6.vif6_table);
+}
+
+static struct pernet_operations ip6mr_net_ops = {
+ .init = ip6mr_net_init,
+ .exit = ip6mr_net_exit,
+};
+
int __init ip6_mr_init(void)
{
int err;
@@ -973,6 +995,10 @@ int __init ip6_mr_init(void)
if (!mrt_cachep)
return -ENOMEM;
+ err = register_pernet_subsys(&ip6mr_net_ops);
+ if (err)
+ goto reg_pernet_fail;
+
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
err = register_netdevice_notifier(&ip6_mr_notifier);
if (err)
@@ -994,6 +1020,8 @@ proc_vif_fail:
#endif
reg_notif_fail:
del_timer(&ipmr_expire_timer);
+ unregister_pernet_subsys(&ip6mr_net_ops);
+reg_pernet_fail:
kmem_cache_destroy(mrt_cachep);
return err;
}
@@ -1006,6 +1034,7 @@ void ip6_mr_cleanup(void)
#endif
unregister_netdevice_notifier(&ip6_mr_notifier);
del_timer(&ipmr_expire_timer);
+ unregister_pernet_subsys(&ip6mr_net_ops);
kmem_cache_destroy(mrt_cachep);
}
@@ -1095,8 +1124,8 @@ static void mroute_clean_tables(struct sock *sk)
/*
* Shut down all active vif entries
*/
- for (i = 0; i < maxvif; i++) {
- if (!(vif6_table[i].flags & VIFF_STATIC))
+ for (i = 0; i < init_net.ipv6.maxvif; i++) {
+ if (!(init_net.ipv6.vif6_table[i].flags & VIFF_STATIC))
mif6_delete(i);
}
@@ -1346,11 +1375,11 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
case SIOCGETMIFCNT_IN6:
if (copy_from_user(&vr, arg, sizeof(vr)))
return -EFAULT;
- if (vr.mifi >= maxvif)
+ if (vr.mifi >= init_net.ipv6.maxvif)
return -EINVAL;
read_lock(&mrt_lock);
- vif = &vif6_table[vr.mifi];
- if (MIF_EXISTS(vr.mifi)) {
+ vif = &init_net.ipv6.vif6_table[vr.mifi];
+ if (MIF_EXISTS(&init_net, vr.mifi)) {
vr.icount = vif->pkt_in;
vr.ocount = vif->pkt_out;
vr.ibytes = vif->bytes_in;
@@ -1401,7 +1430,7 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb)
static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
{
struct ipv6hdr *ipv6h;
- struct mif_device *vif = &vif6_table[vifi];
+ struct mif_device *vif = &init_net.ipv6.vif6_table[vifi];
struct net_device *dev;
struct dst_entry *dst;
struct flowi fl;
@@ -1474,8 +1503,8 @@ out_free:
static int ip6mr_find_vif(struct net_device *dev)
{
int ct;
- for (ct = maxvif - 1; ct >= 0; ct--) {
- if (vif6_table[ct].dev == dev)
+ for (ct = init_net.ipv6.maxvif - 1; ct >= 0; ct--) {
+ if (init_net.ipv6.vif6_table[ct].dev == dev)
break;
}
return ct;
@@ -1493,7 +1522,7 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
/*
* Wrong interface: drop packet and (maybe) send PIM assert.
*/
- if (vif6_table[vif].dev != skb->dev) {
+ if (init_net.ipv6.vif6_table[vif].dev != skb->dev) {
int true_vifi;
cache->mfc_un.res.wrong_if++;
@@ -1514,8 +1543,8 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
goto dont_forward;
}
- vif6_table[vif].pkt_in++;
- vif6_table[vif].bytes_in += skb->len;
+ init_net.ipv6.vif6_table[vif].pkt_in++;
+ init_net.ipv6.vif6_table[vif].bytes_in += skb->len;
/*
* Forward the frame
@@ -1583,7 +1612,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
{
int ct;
struct rtnexthop *nhp;
- struct net_device *dev = vif6_table[c->mf6c_parent].dev;
+ struct net_device *dev = init_net.ipv6.vif6_table[c->mf6c_parent].dev;
u8 *b = skb_tail_pointer(skb);
struct rtattr *mp_head;
@@ -1599,7 +1628,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
nhp->rtnh_flags = 0;
nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
- nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex;
+ nhp->rtnh_ifindex = init_net.ipv6.vif6_table[ct].dev->ifindex;
nhp->rtnh_len = sizeof(*nhp);
}
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/8] netns: ip6mr: Dynamically allocates mfc6_cache_array
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
2008-12-08 16:01 ` [PATCH 1/8] netns: ip6mr: allocate mroute6_socket per-namespace Benjamin Thery
2008-12-08 16:01 ` [PATCH 2/8] netns: ip6mr: dynamically allocates vif6_table Benjamin Thery
@ 2008-12-08 16:01 ` Benjamin Thery
2008-12-08 16:02 ` [PATCH 4/8] netns: ip6mr: Declare mroute_do_assert and mroute_do_pim per-namespace Benjamin Thery
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:01 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Preliminary work to make IPv6 multicast forwarding netns-aware.
Dynamically allocates IPv6 multicast forwarding cache, mfc6_cache_array,
and moves it to struct netns_ipv6.
At the moment, mfc6_cache_array is only referenced in init_net.
Replace 'ARRAY_SIZE(mfc6_cache_array)' with mfc6_cache_array size: MFC6_LINES.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/net/netns/ipv6.h | 1 +
net/ipv6/ip6mr.c | 47 ++++++++++++++++++++++++++++++---------------
2 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 4ab0cb0..14c1bbe 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -57,6 +57,7 @@ struct netns_ipv6 {
struct sock *igmp_sk;
#ifdef CONFIG_IPV6_MROUTE
struct sock *mroute6_sk;
+ struct mfc6_cache **mfc6_cache_array;
struct mif_device *vif6_table;
int maxvif;
#endif
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index bae3ef6..565e81e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -68,8 +68,6 @@ static int mroute_do_pim;
#define mroute_do_pim 0
#endif
-static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */
-
static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */
static atomic_t cache_resolve_queue_len; /* Size of unresolved */
@@ -109,10 +107,11 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
{
struct mfc6_cache *mfc;
- it->cache = mfc6_cache_array;
+ it->cache = init_net.ipv6.mfc6_cache_array;
read_lock(&mrt_lock);
- for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++)
- for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next)
+ for (it->ct = 0; it->ct < MFC6_LINES; it->ct++)
+ for (mfc = init_net.ipv6.mfc6_cache_array[it->ct];
+ mfc; mfc = mfc->next)
if (pos-- == 0)
return mfc;
read_unlock(&mrt_lock);
@@ -243,10 +242,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (it->cache == &mfc_unres_queue)
goto end_of_list;
- BUG_ON(it->cache != mfc6_cache_array);
+ BUG_ON(it->cache != init_net.ipv6.mfc6_cache_array);
- while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) {
- mfc = mfc6_cache_array[it->ct];
+ while (++it->ct < MFC6_LINES) {
+ mfc = init_net.ipv6.mfc6_cache_array[it->ct];
if (mfc)
return mfc;
}
@@ -274,7 +273,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
if (it->cache == &mfc_unres_queue)
spin_unlock_bh(&mfc_unres_lock);
- else if (it->cache == mfc6_cache_array)
+ else if (it->cache == init_net.ipv6.mfc6_cache_array)
read_unlock(&mrt_lock);
}
@@ -674,7 +673,7 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a
int line = MFC6_HASH(mcastgrp, origin);
struct mfc6_cache *c;
- for (c = mfc6_cache_array[line]; c; c = c->next) {
+ for (c = init_net.ipv6.mfc6_cache_array[line]; c; c = c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
break;
@@ -917,7 +916,8 @@ static int ip6mr_mfc_delete(struct mf6cctl *mfc)
line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
- for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
+ for (cp = &init_net.ipv6.mfc6_cache_array[line];
+ (c = *cp) != NULL; cp = &c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
write_lock_bh(&mrt_lock);
@@ -970,12 +970,26 @@ static int __net_init ip6mr_net_init(struct net *net)
err = -ENOMEM;
goto fail;
}
+
+ /* Forwarding cache */
+ net->ipv6.mfc6_cache_array = kcalloc(MFC6_LINES,
+ sizeof(struct mfc6_cache *),
+ GFP_KERNEL);
+ if (!net->ipv6.mfc6_cache_array) {
+ err = -ENOMEM;
+ goto fail_mfc6_cache;
+ }
+ return 0;
+
+fail_mfc6_cache:
+ kfree(net->ipv6.vif6_table);
fail:
return err;
}
static void __net_exit ip6mr_net_exit(struct net *net)
{
+ kfree(net->ipv6.mfc6_cache_array);
kfree(net->ipv6.vif6_table);
}
@@ -1054,7 +1068,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
- for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
+ for (cp = &init_net.ipv6.mfc6_cache_array[line];
+ (c = *cp) != NULL; cp = &c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr))
break;
@@ -1085,8 +1100,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
c->mfc_flags |= MFC_STATIC;
write_lock_bh(&mrt_lock);
- c->next = mfc6_cache_array[line];
- mfc6_cache_array[line] = c;
+ c->next = init_net.ipv6.mfc6_cache_array[line];
+ init_net.ipv6.mfc6_cache_array[line] = c;
write_unlock_bh(&mrt_lock);
/*
@@ -1132,10 +1147,10 @@ static void mroute_clean_tables(struct sock *sk)
/*
* Wipe the cache
*/
- for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) {
+ for (i = 0; i < MFC6_LINES; i++) {
struct mfc6_cache *c, **cp;
- cp = &mfc6_cache_array[i];
+ cp = &init_net.ipv6.mfc6_cache_array[i];
while ((c = *cp) != NULL) {
if (c->mfc_flags & MFC_STATIC) {
cp = &c->next;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/8] netns: ip6mr: Declare mroute_do_assert and mroute_do_pim per-namespace
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (2 preceding siblings ...)
2008-12-08 16:01 ` [PATCH 3/8] netns: ip6mr: Dynamically allocates mfc6_cache_array Benjamin Thery
@ 2008-12-08 16:02 ` Benjamin Thery
2008-12-08 16:02 ` [PATCH 5/8] netns: ip6mr: store netns in struct mfc6_cache Benjamin Thery
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:02 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Preliminary work to make IPv6 multicast forwarding netns-aware.
Declare IPv6 multicast forwarding variables 'mroute_do_assert' and
'mroute_do_pim' per-namespace in struct netns_ipv6.
At the moment, these variables are only referenced in init_net.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/net/netns/ipv6.h | 2 ++
net/ipv6/ip6mr.c | 26 ++++++++++----------------
2 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 14c1bbe..b17e522 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -60,6 +60,8 @@ struct netns_ipv6 {
struct mfc6_cache **mfc6_cache_array;
struct mif_device *vif6_table;
int maxvif;
+ int mroute_do_assert;
+ int mroute_do_pim;
#endif
};
#endif
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 565e81e..94a3133 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -61,13 +61,6 @@ static DEFINE_RWLOCK(mrt_lock);
#define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL)
-static int mroute_do_assert; /* Set in PIM assert */
-#ifdef CONFIG_IPV6_PIMSM_V2
-static int mroute_do_pim;
-#else
-#define mroute_do_pim 0
-#endif
-
static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */
static atomic_t cache_resolve_queue_len; /* Size of unresolved */
@@ -1296,7 +1289,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
int v;
if (get_user(v, (int __user *)optval))
return -EFAULT;
- mroute_do_assert = !!v;
+ init_net.ipv6.mroute_do_assert = !!v;
return 0;
}
@@ -1309,10 +1302,10 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
v = !!v;
rtnl_lock();
ret = 0;
- if (v != mroute_do_pim) {
- mroute_do_pim = v;
- mroute_do_assert = v;
- if (mroute_do_pim)
+ if (v != init_net.ipv6.mroute_do_pim) {
+ init_net.ipv6.mroute_do_pim = v;
+ init_net.ipv6.mroute_do_assert = v;
+ if (init_net.ipv6.mroute_do_pim)
ret = inet6_add_protocol(&pim6_protocol,
IPPROTO_PIM);
else
@@ -1351,11 +1344,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
break;
#ifdef CONFIG_IPV6_PIMSM_V2
case MRT6_PIM:
- val = mroute_do_pim;
+ val = init_net.ipv6.mroute_do_pim;
break;
#endif
case MRT6_ASSERT:
- val = mroute_do_assert;
+ val = init_net.ipv6.mroute_do_assert;
break;
default:
return -ENOPROTOOPT;
@@ -1543,13 +1536,14 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
cache->mfc_un.res.wrong_if++;
true_vifi = ip6mr_find_vif(skb->dev);
- if (true_vifi >= 0 && mroute_do_assert &&
+ if (true_vifi >= 0 && init_net.ipv6.mroute_do_assert &&
/* pimsm uses asserts, when switching from RPT to SPT,
so that we cannot check that packet arrived on an oif.
It is bad, but otherwise we would need to move pretty
large chunk of pimd to kernel. Ough... --ANK
*/
- (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) &&
+ (init_net.ipv6.mroute_do_pim ||
+ cache->mfc_un.res.ttls[true_vifi] < 255) &&
time_after(jiffies,
cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
cache->mfc_un.res.last_assert = jiffies;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/8] netns: ip6mr: store netns in struct mfc6_cache
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (3 preceding siblings ...)
2008-12-08 16:02 ` [PATCH 4/8] netns: ip6mr: Declare mroute_do_assert and mroute_do_pim per-namespace Benjamin Thery
@ 2008-12-08 16:02 ` Benjamin Thery
2008-12-08 16:02 ` [PATCH 6/8] netns: ip6mr: declare reg_vif_num per-namespace Benjamin Thery
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:02 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
This patch stores into struct mfc6_cache the network namespace each
mfc6_cache belongs to. The new member is mfc6_net.
mfc6_net is assigned at cache allocation and doesn't change during
the rest of the cache entry life.
This will help to retrieve the current netns around the IPv6 multicast
forwarding code.
At the moment, all mfc6_cache are allocated in init_net.
Changelog:
==========
* Use write_pnet()/read_pnet() to set and get mfc6_net.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/linux/mroute6.h | 15 +++++++++++++++
net/ipv6/ip6mr.c | 28 +++++++++++++++++++---------
2 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 2cd9901..15d85fe 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -188,6 +188,9 @@ struct mif_device
struct mfc6_cache
{
struct mfc6_cache *next; /* Next entry on cache line */
+#ifdef CONFIG_NET_NS
+ struct net *mfc6_net;
+#endif
struct in6_addr mf6c_mcastgrp; /* Group the entry belongs to */
struct in6_addr mf6c_origin; /* Source of packet */
mifi_t mf6c_parent; /* Source interface */
@@ -210,6 +213,18 @@ struct mfc6_cache
} mfc_un;
};
+static inline
+struct net *mfc6_net(const struct mfc6_cache *mfc)
+{
+ return read_pnet(&mfc->mfc6_net);
+}
+
+static inline
+void mfc6_net_set(struct mfc6_cache *mfc, struct net *net)
+{
+ write_pnet(&mfc->mfc6_net, hold_net(net));
+}
+
#define MFC_STATIC 1
#define MFC_NOTIFY 2
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 94a3133..1583202 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -498,6 +498,14 @@ static int mif6_delete(int vifi)
return 0;
}
+static inline void ip6mr_cache_free(struct mfc6_cache *c)
+{
+#ifdef CONFIG_NET_NS
+ release_net(c->mfc6_net);
+#endif
+ kmem_cache_free(mrt_cachep, c);
+}
+
/* Destroy an unresolved cache entry, killing queued skbs
and reporting error to netlink readers.
*/
@@ -520,7 +528,7 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c)
kfree_skb(skb);
}
- kmem_cache_free(mrt_cachep, c);
+ ip6mr_cache_free(c);
}
@@ -677,22 +685,24 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a
/*
* Allocate a multicast cache entry
*/
-static struct mfc6_cache *ip6mr_cache_alloc(void)
+static struct mfc6_cache *ip6mr_cache_alloc(struct net *net)
{
struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
if (c == NULL)
return NULL;
c->mfc_un.res.minvif = MAXMIFS;
+ mfc6_net_set(c, net);
return c;
}
-static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
+static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net)
{
struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
if (c == NULL)
return NULL;
skb_queue_head_init(&c->mfc_un.unres.unresolved);
c->mfc_un.unres.expires = jiffies + 10 * HZ;
+ mfc6_net_set(c, net);
return c;
}
@@ -848,7 +858,7 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
*/
if (atomic_read(&cache_resolve_queue_len) >= 10 ||
- (c = ip6mr_cache_alloc_unres()) == NULL) {
+ (c = ip6mr_cache_alloc_unres(&init_net)) == NULL) {
spin_unlock_bh(&mfc_unres_lock);
kfree_skb(skb);
@@ -871,7 +881,7 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
*/
spin_unlock_bh(&mfc_unres_lock);
- kmem_cache_free(mrt_cachep, c);
+ ip6mr_cache_free(c);
kfree_skb(skb);
return err;
}
@@ -917,7 +927,7 @@ static int ip6mr_mfc_delete(struct mf6cctl *mfc)
*cp = c->next;
write_unlock_bh(&mrt_lock);
- kmem_cache_free(mrt_cachep, c);
+ ip6mr_cache_free(c);
return 0;
}
}
@@ -1081,7 +1091,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
return -EINVAL;
- c = ip6mr_cache_alloc();
+ c = ip6mr_cache_alloc(&init_net);
if (c == NULL)
return -ENOMEM;
@@ -1116,7 +1126,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
if (uc) {
ip6mr_cache_resolve(uc, c);
- kmem_cache_free(mrt_cachep, uc);
+ ip6mr_cache_free(uc);
}
return 0;
}
@@ -1153,7 +1163,7 @@ static void mroute_clean_tables(struct sock *sk)
*cp = c->next;
write_unlock_bh(&mrt_lock);
- kmem_cache_free(mrt_cachep, c);
+ ip6mr_cache_free(c);
}
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/8] netns: ip6mr: declare reg_vif_num per-namespace
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (4 preceding siblings ...)
2008-12-08 16:02 ` [PATCH 5/8] netns: ip6mr: store netns in struct mfc6_cache Benjamin Thery
@ 2008-12-08 16:02 ` Benjamin Thery
2008-12-08 16:02 ` [PATCH 7/8] netns: ip6mr: declare ip6mr /proc/net entries per-namespace Benjamin Thery
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:02 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Preliminary work to make IPv6 multicast forwarding netns-aware.
Declare variable 'reg_vif_num' per-namespace, moves into struct netns_ipv6.
At the moment, this variable is only referenced in init_net.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/net/netns/ipv6.h | 3 +++
net/ipv6/ip6mr.c | 19 +++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index b17e522..c0e3189 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -62,6 +62,9 @@ struct netns_ipv6 {
int maxvif;
int mroute_do_assert;
int mroute_do_pim;
+#ifdef CONFIG_IPV6_PIMSM_V2
+ int mroute_reg_vif_num;
+#endif
#endif
};
#endif
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 1583202..b9f03f7 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -334,13 +334,13 @@ static struct file_operations ip6mr_mfc_fops = {
#endif
#ifdef CONFIG_IPV6_PIMSM_V2
-static int reg_vif_num = -1;
static int pim6_rcv(struct sk_buff *skb)
{
struct pimreghdr *pim;
struct ipv6hdr *encap;
struct net_device *reg_dev = NULL;
+ int reg_vif_num = init_net.ipv6.mroute_reg_vif_num;
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
goto drop;
@@ -402,7 +402,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
read_lock(&mrt_lock);
dev->stats.tx_bytes += skb->len;
dev->stats.tx_packets++;
- ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT);
+ ip6mr_cache_report(skb, init_net.ipv6.mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
return 0;
@@ -474,8 +474,8 @@ static int mif6_delete(int vifi)
}
#ifdef CONFIG_IPV6_PIMSM_V2
- if (vifi == reg_vif_num)
- reg_vif_num = -1;
+ if (vifi == init_net.ipv6.mroute_reg_vif_num)
+ init_net.ipv6.mroute_reg_vif_num = -1;
#endif
if (vifi + 1 == init_net.ipv6.maxvif) {
@@ -613,7 +613,7 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
* Special Purpose VIF in PIM
* All the packets will be sent to the daemon
*/
- if (reg_vif_num >= 0)
+ if (init_net.ipv6.mroute_reg_vif_num >= 0)
return -EADDRINUSE;
dev = ip6mr_reg_vif();
if (!dev)
@@ -661,7 +661,7 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
v->dev = dev;
#ifdef CONFIG_IPV6_PIMSM_V2
if (v->flags & MIFF_REGISTER)
- reg_vif_num = vifi;
+ init_net.ipv6.mroute_reg_vif_num = vifi;
#endif
if (vifi + 1 > init_net.ipv6.maxvif)
init_net.ipv6.maxvif = vifi + 1;
@@ -780,7 +780,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
msg = (struct mrt6msg *)skb_transport_header(skb);
msg->im6_mbz = 0;
msg->im6_msgtype = MRT6MSG_WHOLEPKT;
- msg->im6_mif = reg_vif_num;
+ msg->im6_mif = init_net.ipv6.mroute_reg_vif_num;
msg->im6_pad = 0;
ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
@@ -966,7 +966,6 @@ static struct notifier_block ip6_mr_notifier = {
static int __net_init ip6mr_net_init(struct net *net)
{
int err = 0;
-
net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device),
GFP_KERNEL);
if (!net->ipv6.vif6_table) {
@@ -982,6 +981,10 @@ static int __net_init ip6mr_net_init(struct net *net)
err = -ENOMEM;
goto fail_mfc6_cache;
}
+
+#ifdef CONFIG_IPV6_PIMSM_V2
+ net->ipv6.mroute_reg_vif_num = -1;
+#endif
return 0;
fail_mfc6_cache:
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/8] netns: ip6mr: declare ip6mr /proc/net entries per-namespace
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (5 preceding siblings ...)
2008-12-08 16:02 ` [PATCH 6/8] netns: ip6mr: declare reg_vif_num per-namespace Benjamin Thery
@ 2008-12-08 16:02 ` Benjamin Thery
2008-12-08 16:02 ` [PATCH 8/8] ipv6: netns: enable namespace support in ipv6 multicast forwarding code Benjamin Thery
2008-12-09 16:56 ` [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:02 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
Declare IPv6 multicast forwarding /proc/net entries per-namespace:
/proc/net/ip6_mr_vif
/proc/net/ip6_mr_cache
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
net/ipv6/ip6mr.c | 104 ++++++++++++++++++++++++++++++-----------------------
1 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index b9f03f7..ad540a0 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -91,19 +91,21 @@ static struct timer_list ipmr_expire_timer;
#ifdef CONFIG_PROC_FS
struct ipmr_mfc_iter {
+ struct seq_net_private p;
struct mfc6_cache **cache;
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;
- it->cache = init_net.ipv6.mfc6_cache_array;
+ it->cache = net->ipv6.mfc6_cache_array;
read_lock(&mrt_lock);
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)
if (pos-- == 0)
return mfc;
@@ -128,17 +130,19 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
*/
struct ipmr_vif_iter {
+ struct seq_net_private p;
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)
{
- for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) {
- if (!MIF_EXISTS(&init_net, iter->ct))
+ for (iter->ct = 0; iter->ct < net->ipv6.maxvif; ++iter->ct) {
+ if (!MIF_EXISTS(net, iter->ct))
continue;
if (pos-- == 0)
- return &init_net.ipv6.vif6_table[iter->ct];
+ return &net->ipv6.vif6_table[iter->ct];
}
return NULL;
}
@@ -146,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)
__acquires(mrt_lock)
{
+ struct net *net = seq_file_net(seq);
+
read_lock(&mrt_lock);
- return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1)
- : SEQ_START_TOKEN);
+ return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1)
+ : SEQ_START_TOKEN;
}
static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct ipmr_vif_iter *iter = seq->private;
+ struct net *net = seq_file_net(seq);
++*pos;
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) {
- if (!MIF_EXISTS(&init_net, iter->ct))
+ while (++iter->ct < net->ipv6.maxvif) {
+ if (!MIF_EXISTS(net, iter->ct))
continue;
- return &init_net.ipv6.vif6_table[iter->ct];
+ return &net->ipv6.vif6_table[iter->ct];
}
return NULL;
}
@@ -175,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)
{
+ struct net *net = seq_file_net(seq);
+
if (v == SEQ_START_TOKEN) {
seq_puts(seq,
"Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
@@ -184,7 +193,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
seq_printf(seq,
"%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,
vif->bytes_out, vif->pkt_out,
vif->flags);
@@ -201,8 +210,8 @@ static struct seq_operations ip6mr_vif_seq_ops = {
static int ip6mr_vif_open(struct inode *inode, struct file *file)
{
- return seq_open_private(file, &ip6mr_vif_seq_ops,
- sizeof(struct ipmr_vif_iter));
+ return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
+ sizeof(struct ipmr_vif_iter));
}
static struct file_operations ip6mr_vif_fops = {
@@ -210,24 +219,27 @@ static struct file_operations ip6mr_vif_fops = {
.open = ip6mr_vif_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = seq_release_net,
};
static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
{
- return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1)
- : SEQ_START_TOKEN);
+ struct net *net = seq_file_net(seq);
+
+ 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)
{
struct mfc6_cache *mfc = v;
struct ipmr_mfc_iter *it = seq->private;
+ struct net *net = seq_file_net(seq);
++*pos;
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)
return mfc->next;
@@ -235,10 +247,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (it->cache == &mfc_unres_queue)
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) {
- mfc = init_net.ipv6.mfc6_cache_array[it->ct];
+ mfc = net->ipv6.mfc6_cache_array[it->ct];
if (mfc)
return mfc;
}
@@ -263,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)
{
struct ipmr_mfc_iter *it = seq->private;
+ struct net *net = seq_file_net(seq);
if (it->cache == &mfc_unres_queue)
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);
}
static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
{
int n;
+ struct net *net = seq_file_net(seq);
if (v == SEQ_START_TOKEN) {
seq_puts(seq,
@@ -294,7 +308,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
mfc->mfc_un.res.wrong_if);
for (n = mfc->mfc_un.res.minvif;
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)
seq_printf(seq,
" %2d:%-3d",
@@ -320,8 +334,8 @@ static struct seq_operations ipmr_mfc_seq_ops = {
static int ipmr_mfc_open(struct inode *inode, struct file *file)
{
- return seq_open_private(file, &ipmr_mfc_seq_ops,
- sizeof(struct ipmr_mfc_iter));
+ return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
+ sizeof(struct ipmr_mfc_iter));
}
static struct file_operations ip6mr_mfc_fops = {
@@ -329,7 +343,7 @@ static struct file_operations ip6mr_mfc_fops = {
.open = ipmr_mfc_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = seq_release_net,
};
#endif
@@ -985,8 +999,22 @@ static int __net_init ip6mr_net_init(struct net *net)
#ifdef CONFIG_IPV6_PIMSM_V2
net->ipv6.mroute_reg_vif_num = -1;
#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;
+#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:
kfree(net->ipv6.vif6_table);
fail:
@@ -995,6 +1023,10 @@ fail:
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.vif6_table);
}
@@ -1023,21 +1055,7 @@ int __init ip6_mr_init(void)
err = register_netdevice_notifier(&ip6_mr_notifier);
if (err)
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;
-#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:
del_timer(&ipmr_expire_timer);
unregister_pernet_subsys(&ip6mr_net_ops);
@@ -1048,10 +1066,6 @@ reg_pernet_fail:
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);
del_timer(&ipmr_expire_timer);
unregister_pernet_subsys(&ip6mr_net_ops);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 8/8] ipv6: netns: enable namespace support in ipv6 multicast forwarding code
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (6 preceding siblings ...)
2008-12-08 16:02 ` [PATCH 7/8] netns: ip6mr: declare ip6mr /proc/net entries per-namespace Benjamin Thery
@ 2008-12-08 16:02 ` Benjamin Thery
2008-12-09 16:56 ` [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
8 siblings, 0 replies; 11+ messages in thread
From: Benjamin Thery @ 2008-12-08 16:02 UTC (permalink / raw)
To: Dave Miller, YOSHIFUJI Hideaki
Cc: netdev, Alexey Dobriyan, Daniel Lezcano, Benjamin Thery
This last patch makes the appropriate changes to use and propagate the
network namespace where needed in IPv6 multicast forwarding code.
This consists mainly in replacing all the remaining init_net occurences
with current netns pointer retrieved from sockets, net devices or
mfc6_caches depending on the routines' contexts.
Some routines receive a new 'struct net' parameter to propagate the netns:
* ip6mr_get_route
* ip6mr_cache_report
* ip6mr_cache_find
* ip6mr_cache_unresolved
* mif6_add/mif6_delete
* ip6mr_mfc_add/ip6mr_mfc_delete
All the IPv6 multicast forwarding variables moved to struct netns_ipv6 by
the previous patches are now referenced in the correct namespace.
Changelog:
==========
* Take into account the net associated to mfc6_cache when matching entries in
mfc_unres_queue list.
* Call mroute_clean_tables() in ip6mr_net_exit() to free memory allocated
per-namespace.
* Call dev_net_set() in ip6mr_reg_vif() to initialize dev->nd_net
correctly.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
---
include/linux/mroute6.h | 3 +-
net/ipv6/ip6mr.c | 235 ++++++++++++++++++++++++++---------------------
net/ipv6/route.c | 2 +-
3 files changed, 133 insertions(+), 107 deletions(-)
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 15d85fe..5375fac 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -245,7 +245,8 @@ void mfc6_net_set(struct mfc6_cache *mfc, struct net *net)
#ifdef __KERNEL__
struct rtmsg;
-extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
+extern int ip6mr_get_route(struct net *net, struct sk_buff *skb,
+ struct rtmsg *rtm, int nowait);
#ifdef CONFIG_IPV6_MROUTE
static inline struct sock *mroute6_socket(struct net *net)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index ad540a0..739ba04 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -78,8 +78,10 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
static struct kmem_cache *mrt_cachep __read_mostly;
static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache);
-static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert);
+static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt,
+ mifi_t mifi, int assert);
static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
+static void mroute_clean_tables(struct net *net);
#ifdef CONFIG_IPV6_PIMSM_V2
static struct inet6_protocol pim6_protocol;
@@ -354,7 +356,8 @@ static int pim6_rcv(struct sk_buff *skb)
struct pimreghdr *pim;
struct ipv6hdr *encap;
struct net_device *reg_dev = NULL;
- int reg_vif_num = init_net.ipv6.mroute_reg_vif_num;
+ struct net *net = dev_net(skb->dev);
+ int reg_vif_num = net->ipv6.mroute_reg_vif_num;
if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
goto drop;
@@ -377,7 +380,7 @@ static int pim6_rcv(struct sk_buff *skb)
read_lock(&mrt_lock);
if (reg_vif_num >= 0)
- reg_dev = init_net.ipv6.vif6_table[reg_vif_num].dev;
+ reg_dev = net->ipv6.vif6_table[reg_vif_num].dev;
if (reg_dev)
dev_hold(reg_dev);
read_unlock(&mrt_lock);
@@ -413,10 +416,13 @@ static struct inet6_protocol pim6_protocol = {
static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct net *net = dev_net(dev);
+
read_lock(&mrt_lock);
dev->stats.tx_bytes += skb->len;
dev->stats.tx_packets++;
- ip6mr_cache_report(skb, init_net.ipv6.mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
+ ip6mr_cache_report(net, skb, net->ipv6.mroute_reg_vif_num,
+ MRT6MSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
return 0;
@@ -435,7 +441,7 @@ static void reg_vif_setup(struct net_device *dev)
dev->destructor = free_netdev;
}
-static struct net_device *ip6mr_reg_vif(void)
+static struct net_device *ip6mr_reg_vif(struct net *net)
{
struct net_device *dev;
@@ -443,6 +449,8 @@ static struct net_device *ip6mr_reg_vif(void)
if (dev == NULL)
return NULL;
+ dev_net_set(dev, net);
+
if (register_netdevice(dev)) {
free_netdev(dev);
return NULL;
@@ -469,14 +477,14 @@ failure:
* Delete a VIF entry
*/
-static int mif6_delete(int vifi)
+static int mif6_delete(struct net *net, int vifi)
{
struct mif_device *v;
struct net_device *dev;
- if (vifi < 0 || vifi >= init_net.ipv6.maxvif)
+ if (vifi < 0 || vifi >= net->ipv6.maxvif)
return -EADDRNOTAVAIL;
- v = &init_net.ipv6.vif6_table[vifi];
+ v = &net->ipv6.vif6_table[vifi];
write_lock_bh(&mrt_lock);
dev = v->dev;
@@ -488,17 +496,17 @@ static int mif6_delete(int vifi)
}
#ifdef CONFIG_IPV6_PIMSM_V2
- if (vifi == init_net.ipv6.mroute_reg_vif_num)
- init_net.ipv6.mroute_reg_vif_num = -1;
+ if (vifi == net->ipv6.mroute_reg_vif_num)
+ net->ipv6.mroute_reg_vif_num = -1;
#endif
- if (vifi + 1 == init_net.ipv6.maxvif) {
+ if (vifi + 1 == net->ipv6.maxvif) {
int tmp;
for (tmp = vifi - 1; tmp >= 0; tmp--) {
- if (MIF_EXISTS(&init_net, tmp))
+ if (MIF_EXISTS(net, tmp))
break;
}
- init_net.ipv6.maxvif = tmp + 1;
+ net->ipv6.maxvif = tmp + 1;
}
write_unlock_bh(&mrt_lock);
@@ -514,9 +522,7 @@ static int mif6_delete(int vifi)
static inline void ip6mr_cache_free(struct mfc6_cache *c)
{
-#ifdef CONFIG_NET_NS
- release_net(c->mfc6_net);
-#endif
+ release_net(mfc6_net(c));
kmem_cache_free(mrt_cachep, c);
}
@@ -537,7 +543,7 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c)
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
skb_trim(skb, nlh->nlmsg_len);
((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
- rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
+ rtnl_unicast(skb, mfc6_net(c), NETLINK_CB(skb).pid);
} else
kfree_skb(skb);
}
@@ -592,13 +598,14 @@ static void ipmr_expire_process(unsigned long dummy)
static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls)
{
int vifi;
+ struct net *net = mfc6_net(cache);
cache->mfc_un.res.minvif = MAXMIFS;
cache->mfc_un.res.maxvif = 0;
memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
- for (vifi = 0; vifi < init_net.ipv6.maxvif; vifi++) {
- if (MIF_EXISTS(&init_net, vifi) &&
+ for (vifi = 0; vifi < net->ipv6.maxvif; vifi++) {
+ if (MIF_EXISTS(net, vifi) &&
ttls[vifi] && ttls[vifi] < 255) {
cache->mfc_un.res.ttls[vifi] = ttls[vifi];
if (cache->mfc_un.res.minvif > vifi)
@@ -609,15 +616,15 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
}
}
-static int mif6_add(struct mif6ctl *vifc, int mrtsock)
+static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock)
{
int vifi = vifc->mif6c_mifi;
- struct mif_device *v = &init_net.ipv6.vif6_table[vifi];
+ struct mif_device *v = &net->ipv6.vif6_table[vifi];
struct net_device *dev;
int err;
/* Is vif busy ? */
- if (MIF_EXISTS(&init_net, vifi))
+ if (MIF_EXISTS(net, vifi))
return -EADDRINUSE;
switch (vifc->mif6c_flags) {
@@ -627,9 +634,9 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
* Special Purpose VIF in PIM
* All the packets will be sent to the daemon
*/
- if (init_net.ipv6.mroute_reg_vif_num >= 0)
+ if (net->ipv6.mroute_reg_vif_num >= 0)
return -EADDRINUSE;
- dev = ip6mr_reg_vif();
+ dev = ip6mr_reg_vif(net);
if (!dev)
return -ENOBUFS;
err = dev_set_allmulti(dev, 1);
@@ -641,7 +648,7 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
break;
#endif
case 0:
- dev = dev_get_by_index(&init_net, vifc->mif6c_pifi);
+ dev = dev_get_by_index(net, vifc->mif6c_pifi);
if (!dev)
return -EADDRNOTAVAIL;
err = dev_set_allmulti(dev, 1);
@@ -675,20 +682,22 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
v->dev = dev;
#ifdef CONFIG_IPV6_PIMSM_V2
if (v->flags & MIFF_REGISTER)
- init_net.ipv6.mroute_reg_vif_num = vifi;
+ net->ipv6.mroute_reg_vif_num = vifi;
#endif
- if (vifi + 1 > init_net.ipv6.maxvif)
- init_net.ipv6.maxvif = vifi + 1;
+ if (vifi + 1 > net->ipv6.maxvif)
+ net->ipv6.maxvif = vifi + 1;
write_unlock_bh(&mrt_lock);
return 0;
}
-static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_addr *mcastgrp)
+static struct mfc6_cache *ip6mr_cache_find(struct net *net,
+ struct in6_addr *origin,
+ struct in6_addr *mcastgrp)
{
int line = MFC6_HASH(mcastgrp, origin);
struct mfc6_cache *c;
- for (c = init_net.ipv6.mfc6_cache_array[line]; c; c = c->next) {
+ for (c = net->ipv6.mfc6_cache_array[line]; c; c = c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
break;
@@ -745,7 +754,7 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c)
skb_trim(skb, nlh->nlmsg_len);
((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
}
- err = rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
+ err = rtnl_unicast(skb, mfc6_net(uc), NETLINK_CB(skb).pid);
} else
ip6_mr_forward(skb, c);
}
@@ -758,7 +767,8 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c)
* Called under mrt_lock.
*/
-static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
+static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi,
+ int assert)
{
struct sk_buff *skb;
struct mrt6msg *msg;
@@ -794,7 +804,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
msg = (struct mrt6msg *)skb_transport_header(skb);
msg->im6_mbz = 0;
msg->im6_msgtype = MRT6MSG_WHOLEPKT;
- msg->im6_mif = init_net.ipv6.mroute_reg_vif_num;
+ msg->im6_mif = net->ipv6.mroute_reg_vif_num;
msg->im6_pad = 0;
ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
@@ -831,7 +841,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
skb_pull(skb, sizeof(struct ipv6hdr));
}
- if (init_net.ipv6.mroute6_sk == NULL) {
+ if (net->ipv6.mroute6_sk == NULL) {
kfree_skb(skb);
return -EINVAL;
}
@@ -839,7 +849,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
/*
* Deliver to user space multicast routing algorithms
*/
- ret = sock_queue_rcv_skb(init_net.ipv6.mroute6_sk, skb);
+ ret = sock_queue_rcv_skb(net->ipv6.mroute6_sk, skb);
if (ret < 0) {
if (net_ratelimit())
printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
@@ -854,14 +864,15 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
*/
static int
-ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
+ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb)
{
int err;
struct mfc6_cache *c;
spin_lock_bh(&mfc_unres_lock);
for (c = mfc_unres_queue; c; c = c->next) {
- if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
+ if (net_eq(mfc6_net(c), net) &&
+ ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr))
break;
}
@@ -872,7 +883,7 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
*/
if (atomic_read(&cache_resolve_queue_len) >= 10 ||
- (c = ip6mr_cache_alloc_unres(&init_net)) == NULL) {
+ (c = ip6mr_cache_alloc_unres(net)) == NULL) {
spin_unlock_bh(&mfc_unres_lock);
kfree_skb(skb);
@@ -889,7 +900,8 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
/*
* Reflect first query at pim6sd
*/
- if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) {
+ err = ip6mr_cache_report(net, skb, mifi, MRT6MSG_NOCACHE);
+ if (err < 0) {
/* If the report failed throw the cache entry
out - Brad Parker
*/
@@ -926,14 +938,14 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
* MFC6 cache manipulation by user space
*/
-static int ip6mr_mfc_delete(struct mf6cctl *mfc)
+static int ip6mr_mfc_delete(struct net *net, struct mf6cctl *mfc)
{
int line;
struct mfc6_cache *c, **cp;
line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
- for (cp = &init_net.ipv6.mfc6_cache_array[line];
+ for (cp = &net->ipv6.mfc6_cache_array[line];
(c = *cp) != NULL; cp = &c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
@@ -952,19 +964,17 @@ static int ip6mr_device_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
struct mif_device *v;
int ct;
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;
- v = &init_net.ipv6.vif6_table[0];
- for (ct = 0; ct < init_net.ipv6.maxvif; ct++, v++) {
+ v = &net->ipv6.vif6_table[0];
+ for (ct = 0; ct < net->ipv6.maxvif; ct++, v++) {
if (v->dev == dev)
- mif6_delete(ct);
+ mif6_delete(net, ct);
}
return NOTIFY_DONE;
}
@@ -1027,6 +1037,7 @@ static void __net_exit ip6mr_net_exit(struct net *net)
proc_net_remove(net, "ip6_mr_cache");
proc_net_remove(net, "ip6_mr_vif");
#endif
+ mroute_clean_tables(net);
kfree(net->ipv6.mfc6_cache_array);
kfree(net->ipv6.vif6_table);
}
@@ -1072,7 +1083,7 @@ void ip6_mr_cleanup(void)
kmem_cache_destroy(mrt_cachep);
}
-static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
+static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock)
{
int line;
struct mfc6_cache *uc, *c, **cp;
@@ -1088,7 +1099,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
- for (cp = &init_net.ipv6.mfc6_cache_array[line];
+ for (cp = &net->ipv6.mfc6_cache_array[line];
(c = *cp) != NULL; cp = &c->next) {
if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr))
@@ -1108,7 +1119,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
return -EINVAL;
- c = ip6mr_cache_alloc(&init_net);
+ c = ip6mr_cache_alloc(net);
if (c == NULL)
return -ENOMEM;
@@ -1120,8 +1131,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
c->mfc_flags |= MFC_STATIC;
write_lock_bh(&mrt_lock);
- c->next = init_net.ipv6.mfc6_cache_array[line];
- init_net.ipv6.mfc6_cache_array[line] = c;
+ c->next = net->ipv6.mfc6_cache_array[line];
+ net->ipv6.mfc6_cache_array[line] = c;
write_unlock_bh(&mrt_lock);
/*
@@ -1131,7 +1142,8 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
spin_lock_bh(&mfc_unres_lock);
for (cp = &mfc_unres_queue; (uc = *cp) != NULL;
cp = &uc->next) {
- if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
+ if (net_eq(mfc6_net(uc), net) &&
+ ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
*cp = uc->next;
if (atomic_dec_and_test(&cache_resolve_queue_len))
@@ -1152,16 +1164,16 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
* Close the multicast socket, and clear the vif tables etc
*/
-static void mroute_clean_tables(struct sock *sk)
+static void mroute_clean_tables(struct net *net)
{
int i;
/*
* Shut down all active vif entries
*/
- for (i = 0; i < init_net.ipv6.maxvif; i++) {
- if (!(init_net.ipv6.vif6_table[i].flags & VIFF_STATIC))
- mif6_delete(i);
+ for (i = 0; i < net->ipv6.maxvif; i++) {
+ if (!(net->ipv6.vif6_table[i].flags & VIFF_STATIC))
+ mif6_delete(net, i);
}
/*
@@ -1170,7 +1182,7 @@ static void mroute_clean_tables(struct sock *sk)
for (i = 0; i < MFC6_LINES; i++) {
struct mfc6_cache *c, **cp;
- cp = &init_net.ipv6.mfc6_cache_array[i];
+ cp = &net->ipv6.mfc6_cache_array[i];
while ((c = *cp) != NULL) {
if (c->mfc_flags & MFC_STATIC) {
cp = &c->next;
@@ -1185,17 +1197,17 @@ static void mroute_clean_tables(struct sock *sk)
}
if (atomic_read(&cache_resolve_queue_len) != 0) {
- struct mfc6_cache *c;
+ struct mfc6_cache *c, **cp;
spin_lock_bh(&mfc_unres_lock);
- while (mfc_unres_queue != NULL) {
- c = mfc_unres_queue;
- mfc_unres_queue = c->next;
- spin_unlock_bh(&mfc_unres_lock);
-
+ cp = &mfc_unres_queue;
+ while ((c = *cp) != NULL) {
+ if (!net_eq(mfc6_net(c), net)) {
+ cp = &c->next;
+ continue;
+ }
+ *cp = c->next;
ip6mr_destroy_unres(c);
-
- spin_lock_bh(&mfc_unres_lock);
}
spin_unlock_bh(&mfc_unres_lock);
}
@@ -1204,11 +1216,12 @@ static void mroute_clean_tables(struct sock *sk)
static int ip6mr_sk_init(struct sock *sk)
{
int err = 0;
+ struct net *net = sock_net(sk);
rtnl_lock();
write_lock_bh(&mrt_lock);
- if (likely(init_net.ipv6.mroute6_sk == NULL))
- init_net.ipv6.mroute6_sk = sk;
+ if (likely(net->ipv6.mroute6_sk == NULL))
+ net->ipv6.mroute6_sk = sk;
else
err = -EADDRINUSE;
write_unlock_bh(&mrt_lock);
@@ -1221,14 +1234,15 @@ static int ip6mr_sk_init(struct sock *sk)
int ip6mr_sk_done(struct sock *sk)
{
int err = 0;
+ struct net *net = sock_net(sk);
rtnl_lock();
- if (sk == init_net.ipv6.mroute6_sk) {
+ if (sk == net->ipv6.mroute6_sk) {
write_lock_bh(&mrt_lock);
- init_net.ipv6.mroute6_sk = NULL;
+ net->ipv6.mroute6_sk = NULL;
write_unlock_bh(&mrt_lock);
- mroute_clean_tables(sk);
+ mroute_clean_tables(net);
} else
err = -EACCES;
rtnl_unlock();
@@ -1249,9 +1263,10 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
struct mif6ctl vif;
struct mf6cctl mfc;
mifi_t mifi;
+ struct net *net = sock_net(sk);
if (optname != MRT6_INIT) {
- if (sk != init_net.ipv6.mroute6_sk && !capable(CAP_NET_ADMIN))
+ if (sk != net->ipv6.mroute6_sk && !capable(CAP_NET_ADMIN))
return -EACCES;
}
@@ -1276,7 +1291,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
if (vif.mif6c_mifi >= MAXMIFS)
return -ENFILE;
rtnl_lock();
- ret = mif6_add(&vif, sk == init_net.ipv6.mroute6_sk);
+ ret = mif6_add(net, &vif, sk == net->ipv6.mroute6_sk);
rtnl_unlock();
return ret;
@@ -1286,7 +1301,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
return -EFAULT;
rtnl_lock();
- ret = mif6_delete(mifi);
+ ret = mif6_delete(net, mifi);
rtnl_unlock();
return ret;
@@ -1302,9 +1317,10 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
return -EFAULT;
rtnl_lock();
if (optname == MRT6_DEL_MFC)
- ret = ip6mr_mfc_delete(&mfc);
+ ret = ip6mr_mfc_delete(net, &mfc);
else
- ret = ip6mr_mfc_add(&mfc, sk == init_net.ipv6.mroute6_sk);
+ ret = ip6mr_mfc_add(net, &mfc,
+ sk == net->ipv6.mroute6_sk);
rtnl_unlock();
return ret;
@@ -1316,7 +1332,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
int v;
if (get_user(v, (int __user *)optval))
return -EFAULT;
- init_net.ipv6.mroute_do_assert = !!v;
+ net->ipv6.mroute_do_assert = !!v;
return 0;
}
@@ -1329,10 +1345,10 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
v = !!v;
rtnl_lock();
ret = 0;
- if (v != init_net.ipv6.mroute_do_pim) {
- init_net.ipv6.mroute_do_pim = v;
- init_net.ipv6.mroute_do_assert = v;
- if (init_net.ipv6.mroute_do_pim)
+ if (v != net->ipv6.mroute_do_pim) {
+ net->ipv6.mroute_do_pim = v;
+ net->ipv6.mroute_do_assert = v;
+ if (net->ipv6.mroute_do_pim)
ret = inet6_add_protocol(&pim6_protocol,
IPPROTO_PIM);
else
@@ -1364,6 +1380,7 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
{
int olr;
int val;
+ struct net *net = sock_net(sk);
switch (optname) {
case MRT6_VERSION:
@@ -1371,11 +1388,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
break;
#ifdef CONFIG_IPV6_PIMSM_V2
case MRT6_PIM:
- val = init_net.ipv6.mroute_do_pim;
+ val = net->ipv6.mroute_do_pim;
break;
#endif
case MRT6_ASSERT:
- val = init_net.ipv6.mroute_do_assert;
+ val = net->ipv6.mroute_do_assert;
break;
default:
return -ENOPROTOOPT;
@@ -1405,16 +1422,17 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
struct sioc_mif_req6 vr;
struct mif_device *vif;
struct mfc6_cache *c;
+ struct net *net = sock_net(sk);
switch (cmd) {
case SIOCGETMIFCNT_IN6:
if (copy_from_user(&vr, arg, sizeof(vr)))
return -EFAULT;
- if (vr.mifi >= init_net.ipv6.maxvif)
+ if (vr.mifi >= net->ipv6.maxvif)
return -EINVAL;
read_lock(&mrt_lock);
- vif = &init_net.ipv6.vif6_table[vr.mifi];
- if (MIF_EXISTS(&init_net, vr.mifi)) {
+ vif = &net->ipv6.vif6_table[vr.mifi];
+ if (MIF_EXISTS(net, vr.mifi)) {
vr.icount = vif->pkt_in;
vr.ocount = vif->pkt_out;
vr.ibytes = vif->bytes_in;
@@ -1432,7 +1450,7 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
return -EFAULT;
read_lock(&mrt_lock);
- c = ip6mr_cache_find(&sr.src.sin6_addr, &sr.grp.sin6_addr);
+ c = ip6mr_cache_find(net, &sr.src.sin6_addr, &sr.grp.sin6_addr);
if (c) {
sr.pktcnt = c->mfc_un.res.pkt;
sr.bytecnt = c->mfc_un.res.bytes;
@@ -1465,7 +1483,8 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb)
static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
{
struct ipv6hdr *ipv6h;
- struct mif_device *vif = &init_net.ipv6.vif6_table[vifi];
+ struct net *net = mfc6_net(c);
+ struct mif_device *vif = &net->ipv6.vif6_table[vifi];
struct net_device *dev;
struct dst_entry *dst;
struct flowi fl;
@@ -1479,7 +1498,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
vif->bytes_out += skb->len;
vif->dev->stats.tx_bytes += skb->len;
vif->dev->stats.tx_packets++;
- ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT);
+ ip6mr_cache_report(net, skb, vifi, MRT6MSG_WHOLEPKT);
kfree_skb(skb);
return 0;
}
@@ -1494,7 +1513,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
}
};
- dst = ip6_route_output(&init_net, NULL, &fl);
+ dst = ip6_route_output(net, NULL, &fl);
if (!dst)
goto out_free;
@@ -1537,9 +1556,10 @@ out_free:
static int ip6mr_find_vif(struct net_device *dev)
{
+ struct net *net = dev_net(dev);
int ct;
- for (ct = init_net.ipv6.maxvif - 1; ct >= 0; ct--) {
- if (init_net.ipv6.vif6_table[ct].dev == dev)
+ for (ct = net->ipv6.maxvif - 1; ct >= 0; ct--) {
+ if (net->ipv6.vif6_table[ct].dev == dev)
break;
}
return ct;
@@ -1549,6 +1569,7 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
{
int psend = -1;
int vif, ct;
+ struct net *net = mfc6_net(cache);
vif = cache->mf6c_parent;
cache->mfc_un.res.pkt++;
@@ -1557,30 +1578,30 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
/*
* Wrong interface: drop packet and (maybe) send PIM assert.
*/
- if (init_net.ipv6.vif6_table[vif].dev != skb->dev) {
+ if (net->ipv6.vif6_table[vif].dev != skb->dev) {
int true_vifi;
cache->mfc_un.res.wrong_if++;
true_vifi = ip6mr_find_vif(skb->dev);
- if (true_vifi >= 0 && init_net.ipv6.mroute_do_assert &&
+ if (true_vifi >= 0 && net->ipv6.mroute_do_assert &&
/* pimsm uses asserts, when switching from RPT to SPT,
so that we cannot check that packet arrived on an oif.
It is bad, but otherwise we would need to move pretty
large chunk of pimd to kernel. Ough... --ANK
*/
- (init_net.ipv6.mroute_do_pim ||
+ (net->ipv6.mroute_do_pim ||
cache->mfc_un.res.ttls[true_vifi] < 255) &&
time_after(jiffies,
cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
cache->mfc_un.res.last_assert = jiffies;
- ip6mr_cache_report(skb, true_vifi, MRT6MSG_WRONGMIF);
+ ip6mr_cache_report(net, skb, true_vifi, MRT6MSG_WRONGMIF);
}
goto dont_forward;
}
- init_net.ipv6.vif6_table[vif].pkt_in++;
- init_net.ipv6.vif6_table[vif].bytes_in += skb->len;
+ net->ipv6.vif6_table[vif].pkt_in++;
+ net->ipv6.vif6_table[vif].bytes_in += skb->len;
/*
* Forward the frame
@@ -1613,9 +1634,11 @@ dont_forward:
int ip6_mr_input(struct sk_buff *skb)
{
struct mfc6_cache *cache;
+ struct net *net = dev_net(skb->dev);
read_lock(&mrt_lock);
- cache = ip6mr_cache_find(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
+ cache = ip6mr_cache_find(net,
+ &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
/*
* No usable cache entry
@@ -1625,7 +1648,7 @@ int ip6_mr_input(struct sk_buff *skb)
vif = ip6mr_find_vif(skb->dev);
if (vif >= 0) {
- int err = ip6mr_cache_unresolved(vif, skb);
+ int err = ip6mr_cache_unresolved(net, vif, skb);
read_unlock(&mrt_lock);
return err;
@@ -1648,7 +1671,8 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
{
int ct;
struct rtnexthop *nhp;
- struct net_device *dev = init_net.ipv6.vif6_table[c->mf6c_parent].dev;
+ struct net *net = mfc6_net(c);
+ struct net_device *dev = net->ipv6.vif6_table[c->mf6c_parent].dev;
u8 *b = skb_tail_pointer(skb);
struct rtattr *mp_head;
@@ -1664,7 +1688,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
nhp->rtnh_flags = 0;
nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
- nhp->rtnh_ifindex = init_net.ipv6.vif6_table[ct].dev->ifindex;
+ nhp->rtnh_ifindex = net->ipv6.vif6_table[ct].dev->ifindex;
nhp->rtnh_len = sizeof(*nhp);
}
}
@@ -1678,14 +1702,15 @@ rtattr_failure:
return -EMSGSIZE;
}
-int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+int ip6mr_get_route(struct net *net,
+ struct sk_buff *skb, struct rtmsg *rtm, int nowait)
{
int err;
struct mfc6_cache *cache;
struct rt6_info *rt = (struct rt6_info *)skb->dst;
read_lock(&mrt_lock);
- cache = ip6mr_cache_find(&rt->rt6i_src.addr, &rt->rt6i_dst.addr);
+ cache = ip6mr_cache_find(net, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
if (!cache) {
struct sk_buff *skb2;
@@ -1728,7 +1753,7 @@ int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr);
ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr);
- err = ip6mr_cache_unresolved(vif, skb2);
+ err = ip6mr_cache_unresolved(net, vif, skb2);
read_unlock(&mrt_lock);
return err;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 9da1ece..18c486c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2194,7 +2194,7 @@ static int rt6_fill_node(struct net *net,
if (iif) {
#ifdef CONFIG_IPV6_MROUTE
if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
- int err = ip6mr_get_route(skb, rtm, nowait);
+ int err = ip6mr_get_route(net, skb, rtm, nowait);
if (err <= 0) {
if (!nowait) {
if (err == 0)
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
` (7 preceding siblings ...)
2008-12-08 16:02 ` [PATCH 8/8] ipv6: netns: enable namespace support in ipv6 multicast forwarding code Benjamin Thery
@ 2008-12-09 16:56 ` Benjamin Thery
2008-12-09 23:53 ` David Miller
8 siblings, 1 reply; 11+ messages in thread
From: Benjamin Thery @ 2008-12-09 16:56 UTC (permalink / raw)
To: Dave Miller; +Cc: YOSHIFUJI Hideaki, netdev, Alexey Dobriyan, Daniel Lezcano
Dave,
While doing some more tests on the patchset I've realized that the queue
of unresolved entries (mfc_unres_queue) should also be allocated
per-netns (or at least counter cache_resolve_queue_len should be).
With the current patchset, the cache for unresolved entries is limited
to 10 entries for all namespaces. D'oh.
I'm looking at this issue and will resend the patchset with the missing
patch ASAP.
Benjamin
Benjamin Thery wrote:
> This patchset introduces the support for network namespaces in IPv6
> multicast forwarding code (net/ipv6/ip6mr.c).
>
> The first patches in the series moves global data from ip6mr.c into
> struct netns_ipv6 to prepare netns support. Data are still referenced in
> init_net only. One of these patches makes the related /proc entries
> per-namespace.
>
> The last patch does the main job and enables the network namespace support
> by replacing all the init_net references with the proper net retrieved
> from sockets or net devices.
>
> The patchset applies on top of net-next-2.6
>
> Regards,
> Benjamin
>
>
>
--
B e n j a m i n T h e r y - BULL/DT/Open Software R&D
http://www.bull.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace
2008-12-09 16:56 ` [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
@ 2008-12-09 23:53 ` David Miller
0 siblings, 0 replies; 11+ messages in thread
From: David Miller @ 2008-12-09 23:53 UTC (permalink / raw)
To: benjamin.thery; +Cc: yoshfuji, netdev, adobriyan, dlezcano
From: Benjamin Thery <benjamin.thery@bull.net>
Date: Tue, 09 Dec 2008 17:56:03 +0100
> While doing some more tests on the patchset I've realized that the queue
> of unresolved entries (mfc_unres_queue) should also be allocated
> per-netns (or at least counter cache_resolve_queue_len should be).
>
> With the current patchset, the cache for unresolved entries is limited
> to 10 entries for all namespaces. D'oh.
>
> I'm looking at this issue and will resend the patchset with the missing
> patch ASAP.
Okie dokie.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-12-09 23:53 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-08 16:01 [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
2008-12-08 16:01 ` [PATCH 1/8] netns: ip6mr: allocate mroute6_socket per-namespace Benjamin Thery
2008-12-08 16:01 ` [PATCH 2/8] netns: ip6mr: dynamically allocates vif6_table Benjamin Thery
2008-12-08 16:01 ` [PATCH 3/8] netns: ip6mr: Dynamically allocates mfc6_cache_array Benjamin Thery
2008-12-08 16:02 ` [PATCH 4/8] netns: ip6mr: Declare mroute_do_assert and mroute_do_pim per-namespace Benjamin Thery
2008-12-08 16:02 ` [PATCH 5/8] netns: ip6mr: store netns in struct mfc6_cache Benjamin Thery
2008-12-08 16:02 ` [PATCH 6/8] netns: ip6mr: declare reg_vif_num per-namespace Benjamin Thery
2008-12-08 16:02 ` [PATCH 7/8] netns: ip6mr: declare ip6mr /proc/net entries per-namespace Benjamin Thery
2008-12-08 16:02 ` [PATCH 8/8] ipv6: netns: enable namespace support in ipv6 multicast forwarding code Benjamin Thery
2008-12-09 16:56 ` [PATCH 0/8] netns: make IPv6 multicast forwarding per-namespace Benjamin Thery
2008-12-09 23:53 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).