aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Thery <benjamin.thery@bull.net>2009-01-21 23:56:16 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-22 16:57:34 -0500
commitcf958ae377ee2545ae70cf48d38e7eb4308c27ea (patch)
treef304ea66b789f4287968fcaa57831cd4fa8e2576
parent70a269e6c9c9b38b1a37dce068c59e9a912f8578 (diff)
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 <benjamin.thery@bull.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netns/ipv4.h2
-rw-r--r--net/ipv4/ipmr.c109
2 files changed, 70 insertions, 41 deletions
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 4f00722c7478..edbcccbbc318 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -57,6 +57,8 @@ struct netns_ipv4 {
57 57
58#ifdef CONFIG_IP_MROUTE 58#ifdef CONFIG_IP_MROUTE
59 struct sock *mroute_sk; 59 struct sock *mroute_sk;
60 struct vif_device *vif_table;
61 int maxvif;
60#endif 62#endif
61}; 63};
62#endif 64#endif
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ac324b702e8b..75a5f79cc226 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -77,10 +77,7 @@ static DEFINE_RWLOCK(mrt_lock);
77 * Multicast router control variables 77 * Multicast router control variables
78 */ 78 */
79 79
80static struct vif_device vif_table[MAXVIFS]; /* Devices */ 80#define VIF_EXISTS(_net, _idx) ((_net)->ipv4.vif_table[_idx].dev != NULL)
81static int maxvif;
82
83#define VIF_EXISTS(idx) (vif_table[idx].dev != NULL)
84 81
85static int mroute_do_assert; /* Set in PIM assert */ 82static int mroute_do_assert; /* Set in PIM assert */
86static int mroute_do_pim; 83static int mroute_do_pim;
@@ -286,10 +283,10 @@ static int vif_delete(int vifi, int notify)
286 struct net_device *dev; 283 struct net_device *dev;
287 struct in_device *in_dev; 284 struct in_device *in_dev;
288 285
289 if (vifi < 0 || vifi >= maxvif) 286 if (vifi < 0 || vifi >= init_net.ipv4.maxvif)
290 return -EADDRNOTAVAIL; 287 return -EADDRNOTAVAIL;
291 288
292 v = &vif_table[vifi]; 289 v = &init_net.ipv4.vif_table[vifi];
293 290
294 write_lock_bh(&mrt_lock); 291 write_lock_bh(&mrt_lock);
295 dev = v->dev; 292 dev = v->dev;
@@ -305,13 +302,13 @@ static int vif_delete(int vifi, int notify)
305 reg_vif_num = -1; 302 reg_vif_num = -1;
306#endif 303#endif
307 304
308 if (vifi+1 == maxvif) { 305 if (vifi+1 == init_net.ipv4.maxvif) {
309 int tmp; 306 int tmp;
310 for (tmp=vifi-1; tmp>=0; tmp--) { 307 for (tmp=vifi-1; tmp>=0; tmp--) {
311 if (VIF_EXISTS(tmp)) 308 if (VIF_EXISTS(&init_net, tmp))
312 break; 309 break;
313 } 310 }
314 maxvif = tmp+1; 311 init_net.ipv4.maxvif = tmp+1;
315 } 312 }
316 313
317 write_unlock_bh(&mrt_lock); 314 write_unlock_bh(&mrt_lock);
@@ -411,8 +408,9 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
411 cache->mfc_un.res.maxvif = 0; 408 cache->mfc_un.res.maxvif = 0;
412 memset(cache->mfc_un.res.ttls, 255, MAXVIFS); 409 memset(cache->mfc_un.res.ttls, 255, MAXVIFS);
413 410
414 for (vifi=0; vifi<maxvif; vifi++) { 411 for (vifi = 0; vifi < init_net.ipv4.maxvif; vifi++) {
415 if (VIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { 412 if (VIF_EXISTS(&init_net, vifi) &&
413 ttls[vifi] && ttls[vifi] < 255) {
416 cache->mfc_un.res.ttls[vifi] = ttls[vifi]; 414 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
417 if (cache->mfc_un.res.minvif > vifi) 415 if (cache->mfc_un.res.minvif > vifi)
418 cache->mfc_un.res.minvif = vifi; 416 cache->mfc_un.res.minvif = vifi;
@@ -425,13 +423,13 @@ static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
425static int vif_add(struct vifctl *vifc, int mrtsock) 423static int vif_add(struct vifctl *vifc, int mrtsock)
426{ 424{
427 int vifi = vifc->vifc_vifi; 425 int vifi = vifc->vifc_vifi;
428 struct vif_device *v = &vif_table[vifi]; 426 struct vif_device *v = &init_net.ipv4.vif_table[vifi];
429 struct net_device *dev; 427 struct net_device *dev;
430 struct in_device *in_dev; 428 struct in_device *in_dev;
431 int err; 429 int err;
432 430
433 /* Is vif busy ? */ 431 /* Is vif busy ? */
434 if (VIF_EXISTS(vifi)) 432 if (VIF_EXISTS(&init_net, vifi))
435 return -EADDRINUSE; 433 return -EADDRINUSE;
436 434
437 switch (vifc->vifc_flags) { 435 switch (vifc->vifc_flags) {
@@ -509,8 +507,8 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
509 if (v->flags&VIFF_REGISTER) 507 if (v->flags&VIFF_REGISTER)
510 reg_vif_num = vifi; 508 reg_vif_num = vifi;
511#endif 509#endif
512 if (vifi+1 > maxvif) 510 if (vifi+1 > init_net.ipv4.maxvif)
513 maxvif = vifi+1; 511 init_net.ipv4.maxvif = vifi+1;
514 write_unlock_bh(&mrt_lock); 512 write_unlock_bh(&mrt_lock);
515 return 0; 513 return 0;
516} 514}
@@ -849,8 +847,8 @@ static void mroute_clean_tables(struct sock *sk)
849 /* 847 /*
850 * Shut down all active vif entries 848 * Shut down all active vif entries
851 */ 849 */
852 for (i=0; i<maxvif; i++) { 850 for (i = 0; i < init_net.ipv4.maxvif; i++) {
853 if (!(vif_table[i].flags&VIFF_STATIC)) 851 if (!(init_net.ipv4.vif_table[i].flags&VIFF_STATIC))
854 vif_delete(i, 0); 852 vif_delete(i, 0);
855 } 853 }
856 854
@@ -1088,11 +1086,11 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
1088 case SIOCGETVIFCNT: 1086 case SIOCGETVIFCNT:
1089 if (copy_from_user(&vr, arg, sizeof(vr))) 1087 if (copy_from_user(&vr, arg, sizeof(vr)))
1090 return -EFAULT; 1088 return -EFAULT;
1091 if (vr.vifi >= maxvif) 1089 if (vr.vifi >= init_net.ipv4.maxvif)
1092 return -EINVAL; 1090 return -EINVAL;
1093 read_lock(&mrt_lock); 1091 read_lock(&mrt_lock);
1094 vif=&vif_table[vr.vifi]; 1092 vif = &init_net.ipv4.vif_table[vr.vifi];
1095 if (VIF_EXISTS(vr.vifi)) { 1093 if (VIF_EXISTS(&init_net, vr.vifi)) {
1096 vr.icount = vif->pkt_in; 1094 vr.icount = vif->pkt_in;
1097 vr.ocount = vif->pkt_out; 1095 vr.ocount = vif->pkt_out;
1098 vr.ibytes = vif->bytes_in; 1096 vr.ibytes = vif->bytes_in;
@@ -1140,8 +1138,8 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
1140 1138
1141 if (event != NETDEV_UNREGISTER) 1139 if (event != NETDEV_UNREGISTER)
1142 return NOTIFY_DONE; 1140 return NOTIFY_DONE;
1143 v=&vif_table[0]; 1141 v = &init_net.ipv4.vif_table[0];
1144 for (ct=0; ct<maxvif; ct++,v++) { 1142 for (ct = 0; ct < init_net.ipv4.maxvif; ct++, v++) {
1145 if (v->dev == dev) 1143 if (v->dev == dev)
1146 vif_delete(ct, 1); 1144 vif_delete(ct, 1);
1147 } 1145 }
@@ -1204,7 +1202,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
1204static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) 1202static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
1205{ 1203{
1206 const struct iphdr *iph = ip_hdr(skb); 1204 const struct iphdr *iph = ip_hdr(skb);
1207 struct vif_device *vif = &vif_table[vifi]; 1205 struct vif_device *vif = &init_net.ipv4.vif_table[vifi];
1208 struct net_device *dev; 1206 struct net_device *dev;
1209 struct rtable *rt; 1207 struct rtable *rt;
1210 int encap = 0; 1208 int encap = 0;
@@ -1305,8 +1303,8 @@ out_free:
1305static int ipmr_find_vif(struct net_device *dev) 1303static int ipmr_find_vif(struct net_device *dev)
1306{ 1304{
1307 int ct; 1305 int ct;
1308 for (ct=maxvif-1; ct>=0; ct--) { 1306 for (ct = init_net.ipv4.maxvif-1; ct >= 0; ct--) {
1309 if (vif_table[ct].dev == dev) 1307 if (init_net.ipv4.vif_table[ct].dev == dev)
1310 break; 1308 break;
1311 } 1309 }
1312 return ct; 1310 return ct;
@@ -1326,7 +1324,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
1326 /* 1324 /*
1327 * Wrong interface: drop packet and (maybe) send PIM assert. 1325 * Wrong interface: drop packet and (maybe) send PIM assert.
1328 */ 1326 */
1329 if (vif_table[vif].dev != skb->dev) { 1327 if (init_net.ipv4.vif_table[vif].dev != skb->dev) {
1330 int true_vifi; 1328 int true_vifi;
1331 1329
1332 if (skb->rtable->fl.iif == 0) { 1330 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
1362 goto dont_forward; 1360 goto dont_forward;
1363 } 1361 }
1364 1362
1365 vif_table[vif].pkt_in++; 1363 init_net.ipv4.vif_table[vif].pkt_in++;
1366 vif_table[vif].bytes_in += skb->len; 1364 init_net.ipv4.vif_table[vif].bytes_in += skb->len;
1367 1365
1368 /* 1366 /*
1369 * Forward the frame 1367 * Forward the frame
@@ -1500,7 +1498,7 @@ static int __pim_rcv(struct sk_buff *skb, unsigned int pimlen)
1500 1498
1501 read_lock(&mrt_lock); 1499 read_lock(&mrt_lock);
1502 if (reg_vif_num >= 0) 1500 if (reg_vif_num >= 0)
1503 reg_dev = vif_table[reg_vif_num].dev; 1501 reg_dev = init_net.ipv4.vif_table[reg_vif_num].dev;
1504 if (reg_dev) 1502 if (reg_dev)
1505 dev_hold(reg_dev); 1503 dev_hold(reg_dev);
1506 read_unlock(&mrt_lock); 1504 read_unlock(&mrt_lock);
@@ -1581,7 +1579,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
1581{ 1579{
1582 int ct; 1580 int ct;
1583 struct rtnexthop *nhp; 1581 struct rtnexthop *nhp;
1584 struct net_device *dev = vif_table[c->mfc_parent].dev; 1582 struct net_device *dev = init_net.ipv4.vif_table[c->mfc_parent].dev;
1585 u8 *b = skb_tail_pointer(skb); 1583 u8 *b = skb_tail_pointer(skb);
1586 struct rtattr *mp_head; 1584 struct rtattr *mp_head;
1587 1585
@@ -1597,7 +1595,7 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
1597 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 1595 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
1598 nhp->rtnh_flags = 0; 1596 nhp->rtnh_flags = 0;
1599 nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; 1597 nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
1600 nhp->rtnh_ifindex = vif_table[ct].dev->ifindex; 1598 nhp->rtnh_ifindex = init_net.ipv4.vif_table[ct].dev->ifindex;
1601 nhp->rtnh_len = sizeof(*nhp); 1599 nhp->rtnh_len = sizeof(*nhp);
1602 } 1600 }
1603 } 1601 }
@@ -1672,11 +1670,11 @@ struct ipmr_vif_iter {
1672static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter, 1670static struct vif_device *ipmr_vif_seq_idx(struct ipmr_vif_iter *iter,
1673 loff_t pos) 1671 loff_t pos)
1674{ 1672{
1675 for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { 1673 for (iter->ct = 0; iter->ct < init_net.ipv4.maxvif; ++iter->ct) {
1676 if (!VIF_EXISTS(iter->ct)) 1674 if (!VIF_EXISTS(&init_net, iter->ct))
1677 continue; 1675 continue;
1678 if (pos-- == 0) 1676 if (pos-- == 0)
1679 return &vif_table[iter->ct]; 1677 return &init_net.ipv4.vif_table[iter->ct];
1680 } 1678 }
1681 return NULL; 1679 return NULL;
1682} 1680}
@@ -1697,10 +1695,10 @@ static void *ipmr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1697 if (v == SEQ_START_TOKEN) 1695 if (v == SEQ_START_TOKEN)
1698 return ipmr_vif_seq_idx(iter, 0); 1696 return ipmr_vif_seq_idx(iter, 0);
1699 1697
1700 while (++iter->ct < maxvif) { 1698 while (++iter->ct < init_net.ipv4.maxvif) {
1701 if (!VIF_EXISTS(iter->ct)) 1699 if (!VIF_EXISTS(&init_net, iter->ct))
1702 continue; 1700 continue;
1703 return &vif_table[iter->ct]; 1701 return &init_net.ipv4.vif_table[iter->ct];
1704 } 1702 }
1705 return NULL; 1703 return NULL;
1706} 1704}
@@ -1722,7 +1720,7 @@ static int ipmr_vif_seq_show(struct seq_file *seq, void *v)
1722 1720
1723 seq_printf(seq, 1721 seq_printf(seq,
1724 "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n", 1722 "%2Zd %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n",
1725 vif - vif_table, 1723 vif - init_net.ipv4.vif_table,
1726 name, vif->bytes_in, vif->pkt_in, 1724 name, vif->bytes_in, vif->pkt_in,
1727 vif->bytes_out, vif->pkt_out, 1725 vif->bytes_out, vif->pkt_out,
1728 vif->flags, vif->local, vif->remote); 1726 vif->flags, vif->local, vif->remote);
@@ -1864,9 +1862,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
1864 mfc->mfc_un.res.wrong_if); 1862 mfc->mfc_un.res.wrong_if);
1865 for (n = mfc->mfc_un.res.minvif; 1863 for (n = mfc->mfc_un.res.minvif;
1866 n < mfc->mfc_un.res.maxvif; n++ ) { 1864 n < mfc->mfc_un.res.maxvif; n++ ) {
1867 if (VIF_EXISTS(n) 1865 if (VIF_EXISTS(&init_net, n) &&
1868 && mfc->mfc_un.res.ttls[n] < 255) 1866 mfc->mfc_un.res.ttls[n] < 255)
1869 seq_printf(seq, 1867 seq_printf(seq,
1870 " %2d:%-3d", 1868 " %2d:%-3d",
1871 n, mfc->mfc_un.res.ttls[n]); 1869 n, mfc->mfc_un.res.ttls[n]);
1872 } 1870 }
@@ -1913,6 +1911,29 @@ static struct net_protocol pim_protocol = {
1913/* 1911/*
1914 * Setup for IP multicast routing 1912 * Setup for IP multicast routing
1915 */ 1913 */
1914static int __net_init ipmr_net_init(struct net *net)
1915{
1916 int err = 0;
1917
1918 net->ipv4.vif_table = kcalloc(MAXVIFS, sizeof(struct vif_device),
1919 GFP_KERNEL);
1920 if (!net->ipv4.vif_table) {
1921 err = -ENOMEM;
1922 goto fail;
1923 }
1924fail:
1925 return err;
1926}
1927
1928static void __net_exit ipmr_net_exit(struct net *net)
1929{
1930 kfree(net->ipv4.vif_table);
1931}
1932
1933static struct pernet_operations ipmr_net_ops = {
1934 .init = ipmr_net_init,
1935 .exit = ipmr_net_exit,
1936};
1916 1937
1917int __init ip_mr_init(void) 1938int __init ip_mr_init(void)
1918{ 1939{
@@ -1925,6 +1946,10 @@ int __init ip_mr_init(void)
1925 if (!mrt_cachep) 1946 if (!mrt_cachep)
1926 return -ENOMEM; 1947 return -ENOMEM;
1927 1948
1949 err = register_pernet_subsys(&ipmr_net_ops);
1950 if (err)
1951 goto reg_pernet_fail;
1952
1928 setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); 1953 setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
1929 err = register_netdevice_notifier(&ip_mr_notifier); 1954 err = register_netdevice_notifier(&ip_mr_notifier);
1930 if (err) 1955 if (err)
@@ -1945,6 +1970,8 @@ proc_vif_fail:
1945#endif 1970#endif
1946reg_notif_fail: 1971reg_notif_fail:
1947 del_timer(&ipmr_expire_timer); 1972 del_timer(&ipmr_expire_timer);
1973 unregister_pernet_subsys(&ipmr_net_ops);
1974reg_pernet_fail:
1948 kmem_cache_destroy(mrt_cachep); 1975 kmem_cache_destroy(mrt_cachep);
1949 return err; 1976 return err;
1950} 1977}