From 70a269e6c9c9b38b1a37dce068c59e9a912f8578 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:15 +0000 Subject: netns: ipmr: allocate mroute_socket per-namespace. Preliminary work to make IPv4 multicast routing netns-aware. Make IPv4 multicast routing mroute_socket per-namespace, moves it into struct netns_ipv4. At the moment, mroute_socket is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 977f482d97a..4f00722c747 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -54,5 +54,9 @@ struct netns_ipv4 { struct timer_list rt_secret_timer; atomic_t rt_genid; + +#ifdef CONFIG_IP_MROUTE + struct sock *mroute_sk; +#endif }; #endif -- cgit v1.2.3-70-g09d2 From cf958ae377ee2545ae70cf48d38e7eb4308c27ea Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:16 +0000 Subject: netns: ipmr: dynamically allocate vif_table Preliminary work to make IPv6 multicast routing netns-aware. Dynamically allocate interface table vif_table and move it to struct netns_ipv4, and update MIF_EXISTS() macro. At the moment, vif_table is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 + net/ipv4/ipmr.c | 109 +++++++++++++++++++++++++++++------------------ 2 files changed, 70 insertions(+), 41 deletions(-) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 4f00722c747..edbcccbbc31 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -57,6 +57,8 @@ struct netns_ipv4 { #ifdef CONFIG_IP_MROUTE struct sock *mroute_sk; + struct vif_device *vif_table; + int maxvif; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index ac324b702e8..75a5f79cc22 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -77,10 +77,7 @@ static DEFINE_RWLOCK(mrt_lock); * Multicast router control variables */ -static struct vif_device vif_table[MAXVIFS]; /* Devices */ -static int maxvif; - -#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL) +#define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; @@ -286,10 +283,10 @@ static int vif_delete(int vifi, int notify) struct net_device *dev; struct in_device *in_dev; - if (vifi < 0 || vifi >= maxvif) + if (vifi < 0 || vifi >= init_net.ipv4.maxvif) return -EADDRNOTAVAIL; - v = &vif_table[vifi]; + v = &init_net.ipv4.vif_table[vifi]; write_lock_bh(&mrt_lock); dev = v->dev; @@ -305,13 +302,13 @@ static int vif_delete(int vifi, int notify) reg_vif_num = -1; #endif - if (vifi+1 == maxvif) { + if (vifi+1 == init_net.ipv4.maxvif) { int tmp; for (tmp=vifi-1; tmp>=0; tmp--) { - if (VIF_EXISTS(tmp)) + if (VIF_EXISTS(&init_net, tmp)) break; } - maxvif = tmp+1; + init_net.ipv4.maxvif = tmp+1; } write_unlock_bh(&mrt_lock); @@ -411,8 +408,9 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) cache->mfc_un.res.maxvif = 0; memset(cache->mfc_un.res.ttls, 255, MAXVIFS); - for (vifi=0; vifimfc_un.res.ttls[vifi] = ttls[vifi]; if (cache->mfc_un.res.minvif > vifi) cache->mfc_un.res.minvif = vifi; @@ -425,13 +423,13 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) static int vif_add(struct vifctl *vifc, int mrtsock) { int vifi = vifc->vifc_vifi; - struct vif_device *v = &vif_table[vifi]; + struct vif_device *v = &init_net.ipv4.vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; int err; /* Is vif busy ? */ - if (VIF_EXISTS(vifi)) + if (VIF_EXISTS(&init_net, vifi)) return -EADDRINUSE; switch (vifc->vifc_flags) { @@ -509,8 +507,8 @@ static int vif_add(struct vifctl *vifc, int mrtsock) if (v->flags&VIFF_REGISTER) reg_vif_num = vifi; #endif - if (vifi+1 > maxvif) - maxvif = vifi+1; + if (vifi+1 > init_net.ipv4.maxvif) + init_net.ipv4.maxvif = vifi+1; write_unlock_bh(&mrt_lock); return 0; } @@ -849,8 +847,8 @@ static void mroute_clean_tables(struct sock *sk) /* * Shut down all active vif entries */ - for (i=0; i= maxvif) + if (vr.vifi >= init_net.ipv4.maxvif) return -EINVAL; read_lock(&mrt_lock); - vif=&vif_table[vr.vifi]; - if (VIF_EXISTS(vr.vifi)) { + vif = &init_net.ipv4.vif_table[vr.vifi]; + if (VIF_EXISTS(&init_net, vr.vifi)) { vr.icount = vif->pkt_in; vr.ocount = vif->pkt_out; vr.ibytes = vif->bytes_in; @@ -1140,8 +1138,8 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; - v=&vif_table[0]; - for (ct=0; ctdev == dev) vif_delete(ct, 1); } @@ -1204,7 +1202,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) { const struct iphdr *iph = ip_hdr(skb); - struct vif_device *vif = &vif_table[vifi]; + struct vif_device *vif = &init_net.ipv4.vif_table[vifi]; struct net_device *dev; struct rtable *rt; int encap = 0; @@ -1305,8 +1303,8 @@ out_free: static int ipmr_find_vif(struct net_device *dev) { int ct; - for (ct=maxvif-1; ct>=0; ct--) { - if (vif_table[ct].dev == dev) + for (ct = init_net.ipv4.maxvif-1; ct >= 0; ct--) { + if (init_net.ipv4.vif_table[ct].dev == dev) break; } return ct; @@ -1326,7 +1324,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local /* * Wrong interface: drop packet and (maybe) send PIM assert. */ - if (vif_table[vif].dev != skb->dev) { + if (init_net.ipv4.vif_table[vif].dev != skb->dev) { int true_vifi; if (skb->rtable->fl.iif == 0) { @@ -1362,8 +1360,8 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local goto dont_forward; } - vif_table[vif].pkt_in++; - vif_table[vif].bytes_in += skb->len; + init_net.ipv4.vif_table[vif].pkt_in++; + init_net.ipv4.vif_table[vif].bytes_in += skb->len; /* * Forward the frame @@ -1500,7 +1498,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) read_lock(&mrt_lock); if (reg_vif_num >= 0) - reg_dev = vif_table[reg_vif_num].dev; + reg_dev = init_net.ipv4.vif_table[reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); @@ -1581,7 +1579,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) { int ct; struct rtnexthop *nhp; - struct net_device *dev = vif_table[c->mfc_parent].dev; + struct net_device *dev = init_net.ipv4.vif_table[c->mfc_parent].dev; u8 *b = skb_tail_pointer(skb); struct rtattr *mp_head; @@ -1597,7 +1595,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_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 = vif_table[ct].dev->ifindex; + nhp->rtnh_ifindex = init_net.ipv4.vif_table[ct].dev->ifindex; nhp->rtnh_len = sizeof(*nhp); } } @@ -1672,11 +1670,11 @@ struct ipmr_vif_iter { static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, loff_t pos) { - for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { - if (!VIF_EXISTS(iter->ct)) + for (iter->ct = 0; iter->ct < init_net.ipv4.maxvif; ++iter->ct) { + if (!VIF_EXISTS(&init_net, iter->ct)) continue; if (pos-- == 0) - return &vif_table[iter->ct]; + return &init_net.ipv4.vif_table[iter->ct]; } return NULL; } @@ -1697,10 +1695,10 @@ static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) return ipmr_vif_seq_idx(iter, 0); - while (++iter->ct < maxvif) { - if (!VIF_EXISTS(iter->ct)) + while (++iter->ct < init_net.ipv4.maxvif) { + if (!VIF_EXISTS(&init_net, iter->ct)) continue; - return &vif_table[iter->ct]; + return &init_net.ipv4.vif_table[iter->ct]; } return NULL; } @@ -1722,7 +1720,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", - vif - vif_table, + vif - init_net.ipv4.vif_table, name, vif->bytes_in, vif->pkt_in, vif->bytes_out, vif->pkt_out, vif->flags, vif->local, vif->remote); @@ -1864,9 +1862,9 @@ 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 (VIF_EXISTS(n) - && mfc->mfc_un.res.ttls[n] < 255) - seq_printf(seq, + if (VIF_EXISTS(&init_net, n) && + mfc->mfc_un.res.ttls[n] < 255) + seq_printf(seq, " %2d:%-3d", n, mfc->mfc_un.res.ttls[n]); } @@ -1913,6 +1911,29 @@ static struct net_protocol pim_protocol = { /* * Setup for IP multicast routing */ +static int __net_init ipmr_net_init(struct net *net) +{ + int err = 0; + + net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device), + GFP_KERNEL); + if (!net->ipv4.vif_table) { + err = -ENOMEM; + goto fail; + } +fail: + return err; +} + +static void __net_exit ipmr_net_exit(struct net *net) +{ + kfree(net->ipv4.vif_table); +} + +static struct pernet_operations ipmr_net_ops = { + .init = ipmr_net_init, + .exit = ipmr_net_exit, +}; int __init ip_mr_init(void) { @@ -1925,6 +1946,10 @@ int __init ip_mr_init(void) if (!mrt_cachep) return -ENOMEM; + err = register_pernet_subsys(&ipmr_net_ops); + if (err) + goto reg_pernet_fail; + setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); err = register_netdevice_notifier(&ip_mr_notifier); if (err) @@ -1945,6 +1970,8 @@ proc_vif_fail: #endif reg_notif_fail: del_timer(&ipmr_expire_timer); + unregister_pernet_subsys(&ipmr_net_ops); +reg_pernet_fail: kmem_cache_destroy(mrt_cachep); return err; } -- cgit v1.2.3-70-g09d2 From 2bb8b26c3ea8bde1943dc5cd4dda2dc9f48fb281 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:18 +0000 Subject: netns: ipmr: dynamically allocate mfc_cache_array Preliminary work to make IPv4 multicast routing netns-aware. Dynamically allocate IPv4 multicast forwarding cache, mfc_cache_array, and move it to struct netns_ipv4. At the moment, mfc_cache_array is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + net/ipv4/ipmr.c | 41 ++++++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index edbcccbbc31..0b4285ac29d 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -57,6 +57,7 @@ struct netns_ipv4 { #ifdef CONFIG_IP_MROUTE struct sock *mroute_sk; + struct mfc_cache **mfc_cache_array; struct vif_device *vif_table; int maxvif; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8428a0fb5c1..35b868dd3bf 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -82,8 +82,6 @@ static DEFINE_RWLOCK(mrt_lock); static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; -static struct mfc_cache *mfc_cache_array[MFC_LINES]; /* Forwarding cache */ - static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ static atomic_t cache_resolve_queue_len; /* Size of unresolved */ @@ -524,7 +522,7 @@ static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp) int line = MFC_HASH(mcastgrp, origin); struct mfc_cache *c; - for (c=mfc_cache_array[line]; c; c = c->next) { + for (c = init_net.ipv4.mfc_cache_array[line]; c; c = c->next) { if (c->mfc_origin==origin && c->mfc_mcastgrp==mcastgrp) break; } @@ -764,7 +762,8 @@ static int ipmr_mfc_delete(struct mfcctl *mfc) line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { + for (cp = &init_net.ipv4.mfc_cache_array[line]; + (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { write_lock_bh(&mrt_lock); @@ -785,7 +784,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); - for (cp=&mfc_cache_array[line]; (c=*cp) != NULL; cp = &c->next) { + for (cp = &init_net.ipv4.mfc_cache_array[line]; + (c = *cp) != NULL; cp = &c->next) { if (c->mfc_origin == mfc->mfcc_origin.s_addr && c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) break; @@ -816,8 +816,8 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) c->mfc_flags |= MFC_STATIC; write_lock_bh(&mrt_lock); - c->next = mfc_cache_array[line]; - mfc_cache_array[line] = c; + c->next = init_net.ipv4.mfc_cache_array[line]; + init_net.ipv4.mfc_cache_array[line] = c; write_unlock_bh(&mrt_lock); /* @@ -866,7 +866,7 @@ static void mroute_clean_tables(struct sock *sk) for (i=0; imfc_flags&MFC_STATIC) { cp = &c->next; @@ -1767,10 +1767,11 @@ static struct mfc_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) { struct mfc_cache *mfc; - it->cache = mfc_cache_array; + it->cache = init_net.ipv4.mfc_cache_array; read_lock(&mrt_lock); for (it->ct = 0; it->ct < MFC_LINES; it->ct++) - for (mfc = mfc_cache_array[it->ct]; mfc; mfc = mfc->next) + for (mfc = init_net.ipv4.mfc_cache_array[it->ct]; + mfc; mfc = mfc->next) if (pos-- == 0) return mfc; read_unlock(&mrt_lock); @@ -1812,10 +1813,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 != mfc_cache_array); + BUG_ON(it->cache != init_net.ipv4.mfc_cache_array); while (++it->ct < MFC_LINES) { - mfc = mfc_cache_array[it->ct]; + mfc = init_net.ipv4.mfc_cache_array[it->ct]; if (mfc) return mfc; } @@ -1843,7 +1844,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 == mfc_cache_array) + else if (it->cache == init_net.ipv4.mfc_cache_array) read_unlock(&mrt_lock); } @@ -1929,12 +1930,26 @@ static int __net_init ipmr_net_init(struct net *net) err = -ENOMEM; goto fail; } + + /* Forwarding cache */ + net->ipv4.mfc_cache_array = kcalloc(MFC_LINES, + sizeof(struct mfc_cache *), + GFP_KERNEL); + if (!net->ipv4.mfc_cache_array) { + err = -ENOMEM; + goto fail_mfc_cache; + } + return 0; + +fail_mfc_cache: + kfree(net->ipv4.vif_table); fail: return err; } static void __net_exit ipmr_net_exit(struct net *net) { + kfree(net->ipv4.mfc_cache_array); kfree(net->ipv4.vif_table); } -- cgit v1.2.3-70-g09d2 From 1e8fb3b6a4ac6c5e486298d88289038456957545 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:19 +0000 Subject: netns: ipmr: declare counter cache_resolve_queue_len per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare variable cache_resolve_queue_len per-namespace: move it into struct netns_ipv4. This variable counts the number of unresolved cache entries queued in the list mfc_unres_queue. This list is kept global to all netns as the number of entries per namespace is limited to 10 (hardcoded in routine ipmr_cache_unresolved). Entries belonging to different namespaces in mfc_unres_queue will be identified by matching the mfc_net member introduced previously in struct mfc_cache. Keeping this list global to all netns, also allows us to keep a single timer (ipmr_expire_timer) to handle their expiration. In some places cache_resolve_queue_len value was tested for arming or deleting the timer. These tests were equivalent to testing mfc_unres_queue value instead and are replaced in this patch. At the moment, cache_resolve_queue_len is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + net/ipv4/ipmr.c | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 0b4285ac29d..90b7cd20aa6 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -60,6 +60,7 @@ struct netns_ipv4 { struct mfc_cache **mfc_cache_array; struct vif_device *vif_table; int maxvif; + atomic_t cache_resolve_queue_len; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 35b868dd3bf..feafd14eb7b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -83,7 +83,6 @@ static int mroute_do_assert; /* Set in PIM assert */ static int mroute_do_pim; static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ -static atomic_t cache_resolve_queue_len; /* Size of unresolved */ /* Special spinlock for queue of unresolved entries */ static DEFINE_SPINLOCK(mfc_unres_lock); @@ -340,7 +339,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) struct sk_buff *skb; struct nlmsgerr *e; - atomic_dec(&cache_resolve_queue_len); + atomic_dec(&init_net.ipv4.cache_resolve_queue_len); while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved))) { if (ip_hdr(skb)->version == 0) { @@ -374,7 +373,7 @@ static void ipmr_expire_process(unsigned long dummy) return; } - if (atomic_read(&cache_resolve_queue_len) == 0) + if (mfc_unres_queue == NULL) goto out; now = jiffies; @@ -395,7 +394,7 @@ static void ipmr_expire_process(unsigned long dummy) ipmr_destroy_unres(c); } - if (atomic_read(&cache_resolve_queue_len)) + if (mfc_unres_queue != NULL) mod_timer(&ipmr_expire_timer, jiffies + expires); out: @@ -690,7 +689,8 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) spin_lock_bh(&mfc_unres_lock); for (c=mfc_unres_queue; c; c=c->next) { - if (c->mfc_mcastgrp == iph->daddr && + if (net_eq(mfc_net(c), &init_net) && + c->mfc_mcastgrp == iph->daddr && c->mfc_origin == iph->saddr) break; } @@ -700,7 +700,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) * Create a new entry if allowable */ - if (atomic_read(&cache_resolve_queue_len) >= 10 || + if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) >= 10 || (c = ipmr_cache_alloc_unres(&init_net)) == NULL) { spin_unlock_bh(&mfc_unres_lock); @@ -729,7 +729,7 @@ ipmr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) return err; } - atomic_inc(&cache_resolve_queue_len); + atomic_inc(&init_net.ipv4.cache_resolve_queue_len); c->next = mfc_unres_queue; mfc_unres_queue = c; @@ -827,14 +827,16 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) spin_lock_bh(&mfc_unres_lock); for (cp = &mfc_unres_queue; (uc=*cp) != NULL; cp = &uc->next) { - if (uc->mfc_origin == c->mfc_origin && + if (net_eq(mfc_net(uc), &init_net) && + uc->mfc_origin == c->mfc_origin && uc->mfc_mcastgrp == c->mfc_mcastgrp) { *cp = uc->next; - if (atomic_dec_and_test(&cache_resolve_queue_len)) - del_timer(&ipmr_expire_timer); + atomic_dec(&init_net.ipv4.cache_resolve_queue_len); break; } } + if (mfc_unres_queue == NULL) + del_timer(&ipmr_expire_timer); spin_unlock_bh(&mfc_unres_lock); if (uc) { @@ -880,18 +882,19 @@ static void mroute_clean_tables(struct sock *sk) } } - if (atomic_read(&cache_resolve_queue_len) != 0) { - struct mfc_cache *c; + if (atomic_read(&init_net.ipv4.cache_resolve_queue_len) != 0) { + struct mfc_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(mfc_net(c), &init_net)) { + cp = &c->next; + continue; + } + *cp = c->next; ipmr_destroy_unres(c); - - spin_lock_bh(&mfc_unres_lock); } spin_unlock_bh(&mfc_unres_lock); } -- cgit v1.2.3-70-g09d2 From 6f9374a9342e896c68df7cf7c0b039ab5cca994c Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:20 +0000 Subject: netns: ipmr: declare mroute_do_assert and mroute_do_pim per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare IPv multicast routing variables 'mroute_do_assert' and 'mroute_do_pim' per-namespace in struct netns_ipv4. At the moment, these variables are only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 ++ net/ipv4/ipmr.c | 24 +++++++++++------------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 90b7cd20aa6..8451722782b 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -61,6 +61,8 @@ struct netns_ipv4 { struct vif_device *vif_table; int maxvif; atomic_t cache_resolve_queue_len; + int mroute_do_assert; + int mroute_do_pim; #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index feafd14eb7b..d6a28acc068 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -79,9 +79,6 @@ static DEFINE_RWLOCK(mrt_lock); #define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL) -static int mroute_do_assert; /* Set in PIM assert */ -static int mroute_do_pim; - static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */ /* Special spinlock for queue of unresolved entries */ @@ -1003,7 +1000,7 @@ int ip_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)?1:0; + init_net.ipv4.mroute_do_assert = (v) ? 1 : 0; return 0; } #ifdef CONFIG_IP_PIMSM @@ -1017,11 +1014,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int rtnl_lock(); ret = 0; - if (v != mroute_do_pim) { - mroute_do_pim = v; - mroute_do_assert = v; + if (v != init_net.ipv4.mroute_do_pim) { + init_net.ipv4.mroute_do_pim = v; + init_net.ipv4.mroute_do_assert = v; #ifdef CONFIG_IP_PIMSM_V2 - if (mroute_do_pim) + if (init_net.ipv4.mroute_do_pim) ret = inet_add_protocol(&pim_protocol, IPPROTO_PIM); else @@ -1073,10 +1070,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int val = 0x0305; #ifdef CONFIG_IP_PIMSM else if (optname == MRT_PIM) - val = mroute_do_pim; + val = init_net.ipv4.mroute_do_pim; #endif else - val = mroute_do_assert; + val = init_net.ipv4.mroute_do_assert; if (copy_to_user(optval, &val, olr)) return -EFAULT; return 0; @@ -1356,13 +1353,14 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local cache->mfc_un.res.wrong_if++; true_vifi = ipmr_find_vif(skb->dev); - if (true_vifi >= 0 && mroute_do_assert && + if (true_vifi >= 0 && init_net.ipv4.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.ipv4.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; @@ -1550,7 +1548,7 @@ int pim_rcv_v1(struct sk_buff * skb) pim = igmp_hdr(skb); - if (!mroute_do_pim || + if (!init_net.ipv4.mroute_do_pim || pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER) goto drop; -- cgit v1.2.3-70-g09d2 From 6c5143dbcfe50ac722965dc7d096abbeeec8bb33 Mon Sep 17 00:00:00 2001 From: Benjamin Thery Date: Thu, 22 Jan 2009 04:56:21 +0000 Subject: netns: ipmr: declare reg_vif_num per-namespace Preliminary work to make IPv4 multicast routing netns-aware. Declare variable 'reg_vif_num' per-namespace, move into struct netns_ipv4. At the moment, this variable is only referenced in init_net. Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 3 +++ net/ipv4/ipmr.c | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'include/net/netns/ipv4.h') diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 8451722782b..2eb3814d625 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -63,6 +63,9 @@ struct netns_ipv4 { atomic_t cache_resolve_queue_len; int mroute_do_assert; int mroute_do_pim; +#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2) + int mroute_reg_vif_num; +#endif #endif }; #endif diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index d6a28acc068..346e67b50d6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -197,14 +197,12 @@ failure: #ifdef CONFIG_IP_PIMSM -static int reg_vif_num = -1; - 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++; - ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); + ipmr_cache_report(skb, init_net.ipv4.mroute_reg_vif_num, IGMPMSG_WHOLEPKT); read_unlock(&mrt_lock); kfree_skb(skb); return 0; @@ -292,8 +290,8 @@ static int vif_delete(int vifi, int notify) } #ifdef CONFIG_IP_PIMSM - if (vifi == reg_vif_num) - reg_vif_num = -1; + if (vifi == init_net.ipv4.mroute_reg_vif_num) + init_net.ipv4.mroute_reg_vif_num = -1; #endif if (vifi+1 == init_net.ipv4.maxvif) { @@ -439,7 +437,7 @@ static int vif_add(struct vifctl *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.ipv4.mroute_reg_vif_num >= 0) return -EADDRINUSE; dev = ipmr_reg_vif(); if (!dev) @@ -505,7 +503,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) v->dev = dev; #ifdef CONFIG_IP_PIMSM if (v->flags&VIFF_REGISTER) - reg_vif_num = vifi; + init_net.ipv4.mroute_reg_vif_num = vifi; #endif if (vifi+1 > init_net.ipv4.maxvif) init_net.ipv4.maxvif = vifi+1; @@ -623,7 +621,7 @@ static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); msg->im_msgtype = IGMPMSG_WHOLEPKT; msg->im_mbz = 0; - msg->im_vif = reg_vif_num; + msg->im_vif = init_net.ipv4.mroute_reg_vif_num; ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + sizeof(struct iphdr)); @@ -1506,8 +1504,8 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen) return 1; read_lock(&mrt_lock); - if (reg_vif_num >= 0) - reg_dev = init_net.ipv4.vif_table[reg_vif_num].dev; + if (init_net.ipv4.mroute_reg_vif_num >= 0) + reg_dev = init_net.ipv4.vif_table[init_net.ipv4.mroute_reg_vif_num].dev; if (reg_dev) dev_hold(reg_dev); read_unlock(&mrt_lock); @@ -1940,6 +1938,10 @@ static int __net_init ipmr_net_init(struct net *net) err = -ENOMEM; goto fail_mfc_cache; } + +#ifdef CONFIG_IP_PIMSM + net->ipv4.mroute_reg_vif_num = -1; +#endif return 0; fail_mfc_cache: -- cgit v1.2.3-70-g09d2