aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6mr.c
diff options
context:
space:
mode:
authorBenjamin Thery <benjamin.thery@bull.net>2008-12-10 19:15:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-10 19:15:08 -0500
commit4e16880cb4225bfa68878ad5b2a9ded53657d054 (patch)
tree6a8c15e47fe33edede4c4bd79c05dabc5ca2f79c /net/ipv6/ip6mr.c
parentbd91b8bf372911c1e4d66d6bb44fe409349a6791 (diff)
netns: ip6mr: dynamically allocates vif6_table
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> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6mr.c')
-rw-r--r--net/ipv6/ip6mr.c107
1 files changed, 68 insertions, 39 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 02163dbf84c3..bae3ef649664 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -59,10 +59,7 @@ static DEFINE_RWLOCK(mrt_lock);
59 * Multicast router control variables 59 * Multicast router control variables
60 */ 60 */
61 61
62static struct mif_device vif6_table[MAXMIFS]; /* Devices */ 62#define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL)
63static int maxvif;
64
65#define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL)
66 63
67static int mroute_do_assert; /* Set in PIM assert */ 64static int mroute_do_assert; /* Set in PIM assert */
68#ifdef CONFIG_IPV6_PIMSM_V2 65#ifdef CONFIG_IPV6_PIMSM_V2
@@ -145,11 +142,11 @@ struct ipmr_vif_iter {
145static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, 142static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
146 loff_t pos) 143 loff_t pos)
147{ 144{
148 for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) { 145 for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) {
149 if (!MIF_EXISTS(iter->ct)) 146 if (!MIF_EXISTS(&init_net, iter->ct))
150 continue; 147 continue;
151 if (pos-- == 0) 148 if (pos-- == 0)
152 return &vif6_table[iter->ct]; 149 return &init_net.ipv6.vif6_table[iter->ct];
153 } 150 }
154 return NULL; 151 return NULL;
155} 152}
@@ -170,10 +167,10 @@ static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
170 if (v == SEQ_START_TOKEN) 167 if (v == SEQ_START_TOKEN)
171 return ip6mr_vif_seq_idx(iter, 0); 168 return ip6mr_vif_seq_idx(iter, 0);
172 169
173 while (++iter->ct < maxvif) { 170 while (++iter->ct < init_net.ipv6.maxvif) {
174 if (!MIF_EXISTS(iter->ct)) 171 if (!MIF_EXISTS(&init_net, iter->ct))
175 continue; 172 continue;
176 return &vif6_table[iter->ct]; 173 return &init_net.ipv6.vif6_table[iter->ct];
177 } 174 }
178 return NULL; 175 return NULL;
179} 176}
@@ -195,7 +192,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
195 192
196 seq_printf(seq, 193 seq_printf(seq,
197 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", 194 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
198 vif - vif6_table, 195 vif - init_net.ipv6.vif6_table,
199 name, vif->bytes_in, vif->pkt_in, 196 name, vif->bytes_in, vif->pkt_in,
200 vif->bytes_out, vif->pkt_out, 197 vif->bytes_out, vif->pkt_out,
201 vif->flags); 198 vif->flags);
@@ -305,7 +302,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
305 mfc->mfc_un.res.wrong_if); 302 mfc->mfc_un.res.wrong_if);
306 for (n = mfc->mfc_un.res.minvif; 303 for (n = mfc->mfc_un.res.minvif;
307 n < mfc->mfc_un.res.maxvif; n++) { 304 n < mfc->mfc_un.res.maxvif; n++) {
308 if (MIF_EXISTS(n) && 305 if (MIF_EXISTS(&init_net, n) &&
309 mfc->mfc_un.res.ttls[n] < 255) 306 mfc->mfc_un.res.ttls[n] < 255)
310 seq_printf(seq, 307 seq_printf(seq,
311 " %2d:%-3d", 308 " %2d:%-3d",
@@ -374,7 +371,7 @@ static int pim6_rcv(struct sk_buff *skb)
374 371
375 read_lock(&mrt_lock); 372 read_lock(&mrt_lock);
376 if (reg_vif_num >= 0) 373 if (reg_vif_num >= 0)
377 reg_dev = vif6_table[reg_vif_num].dev; 374 reg_dev = init_net.ipv6.vif6_table[reg_vif_num].dev;
378 if (reg_dev) 375 if (reg_dev)
379 dev_hold(reg_dev); 376 dev_hold(reg_dev);
380 read_unlock(&mrt_lock); 377 read_unlock(&mrt_lock);
@@ -470,10 +467,10 @@ static int mif6_delete(int vifi)
470{ 467{
471 struct mif_device *v; 468 struct mif_device *v;
472 struct net_device *dev; 469 struct net_device *dev;
473 if (vifi < 0 || vifi >= maxvif) 470 if (vifi < 0 || vifi >= init_net.ipv6.maxvif)
474 return -EADDRNOTAVAIL; 471 return -EADDRNOTAVAIL;
475 472
476 v = &vif6_table[vifi]; 473 v = &init_net.ipv6.vif6_table[vifi];
477 474
478 write_lock_bh(&mrt_lock); 475 write_lock_bh(&mrt_lock);
479 dev = v->dev; 476 dev = v->dev;
@@ -489,13 +486,13 @@ static int mif6_delete(int vifi)
489 reg_vif_num = -1; 486 reg_vif_num = -1;
490#endif 487#endif
491 488
492 if (vifi + 1 == maxvif) { 489 if (vifi + 1 == init_net.ipv6.maxvif) {
493 int tmp; 490 int tmp;
494 for (tmp = vifi - 1; tmp >= 0; tmp--) { 491 for (tmp = vifi - 1; tmp >= 0; tmp--) {
495 if (MIF_EXISTS(tmp)) 492 if (MIF_EXISTS(&init_net, tmp))
496 break; 493 break;
497 } 494 }
498 maxvif = tmp + 1; 495 init_net.ipv6.maxvif = tmp + 1;
499 } 496 }
500 497
501 write_unlock_bh(&mrt_lock); 498 write_unlock_bh(&mrt_lock);
@@ -586,8 +583,9 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
586 cache->mfc_un.res.maxvif = 0; 583 cache->mfc_un.res.maxvif = 0;
587 memset(cache->mfc_un.res.ttls, 255, MAXMIFS); 584 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
588 585
589 for (vifi = 0; vifi < maxvif; vifi++) { 586 for (vifi = 0; vifi < init_net.ipv6.maxvif; vifi++) {
590 if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { 587 if (MIF_EXISTS(&init_net, vifi) &&
588 ttls[vifi] && ttls[vifi] < 255) {
591 cache->mfc_un.res.ttls[vifi] = ttls[vifi]; 589 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
592 if (cache->mfc_un.res.minvif > vifi) 590 if (cache->mfc_un.res.minvif > vifi)
593 cache->mfc_un.res.minvif = vifi; 591 cache->mfc_un.res.minvif = vifi;
@@ -600,12 +598,12 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl
600static int mif6_add(struct mif6ctl *vifc, int mrtsock) 598static int mif6_add(struct mif6ctl *vifc, int mrtsock)
601{ 599{
602 int vifi = vifc->mif6c_mifi; 600 int vifi = vifc->mif6c_mifi;
603 struct mif_device *v = &vif6_table[vifi]; 601 struct mif_device *v = &init_net.ipv6.vif6_table[vifi];
604 struct net_device *dev; 602 struct net_device *dev;
605 int err; 603 int err;
606 604
607 /* Is vif busy ? */ 605 /* Is vif busy ? */
608 if (MIF_EXISTS(vifi)) 606 if (MIF_EXISTS(&init_net, vifi))
609 return -EADDRINUSE; 607 return -EADDRINUSE;
610 608
611 switch (vifc->mif6c_flags) { 609 switch (vifc->mif6c_flags) {
@@ -665,8 +663,8 @@ static int mif6_add(struct mif6ctl *vifc, int mrtsock)
665 if (v->flags & MIFF_REGISTER) 663 if (v->flags & MIFF_REGISTER)
666 reg_vif_num = vifi; 664 reg_vif_num = vifi;
667#endif 665#endif
668 if (vifi + 1 > maxvif) 666 if (vifi + 1 > init_net.ipv6.maxvif)
669 maxvif = vifi + 1; 667 init_net.ipv6.maxvif = vifi + 1;
670 write_unlock_bh(&mrt_lock); 668 write_unlock_bh(&mrt_lock);
671 return 0; 669 return 0;
672} 670}
@@ -946,8 +944,8 @@ static int ip6mr_device_event(struct notifier_block *this,
946 if (event != NETDEV_UNREGISTER) 944 if (event != NETDEV_UNREGISTER)
947 return NOTIFY_DONE; 945 return NOTIFY_DONE;
948 946
949 v = &vif6_table[0]; 947 v = &init_net.ipv6.vif6_table[0];
950 for (ct = 0; ct < maxvif; ct++, v++) { 948 for (ct = 0; ct < init_net.ipv6.maxvif; ct++, v++) {
951 if (v->dev == dev) 949 if (v->dev == dev)
952 mif6_delete(ct); 950 mif6_delete(ct);
953 } 951 }
@@ -962,6 +960,30 @@ static struct notifier_block ip6_mr_notifier = {
962 * Setup for IP multicast routing 960 * Setup for IP multicast routing
963 */ 961 */
964 962
963static int __net_init ip6mr_net_init(struct net *net)
964{
965 int err = 0;
966
967 net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device),
968 GFP_KERNEL);
969 if (!net->ipv6.vif6_table) {
970 err = -ENOMEM;
971 goto fail;
972 }
973fail:
974 return err;
975}
976
977static void __net_exit ip6mr_net_exit(struct net *net)
978{
979 kfree(net->ipv6.vif6_table);
980}
981
982static struct pernet_operations ip6mr_net_ops = {
983 .init = ip6mr_net_init,
984 .exit = ip6mr_net_exit,
985};
986
965int __init ip6_mr_init(void) 987int __init ip6_mr_init(void)
966{ 988{
967 int err; 989 int err;
@@ -973,6 +995,10 @@ int __init ip6_mr_init(void)
973 if (!mrt_cachep) 995 if (!mrt_cachep)
974 return -ENOMEM; 996 return -ENOMEM;
975 997
998 err = register_pernet_subsys(&ip6mr_net_ops);
999 if (err)
1000 goto reg_pernet_fail;
1001
976 setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); 1002 setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
977 err = register_netdevice_notifier(&ip6_mr_notifier); 1003 err = register_netdevice_notifier(&ip6_mr_notifier);
978 if (err) 1004 if (err)
@@ -994,6 +1020,8 @@ proc_vif_fail:
994#endif 1020#endif
995reg_notif_fail: 1021reg_notif_fail:
996 del_timer(&ipmr_expire_timer); 1022 del_timer(&ipmr_expire_timer);
1023 unregister_pernet_subsys(&ip6mr_net_ops);
1024reg_pernet_fail:
997 kmem_cache_destroy(mrt_cachep); 1025 kmem_cache_destroy(mrt_cachep);
998 return err; 1026 return err;
999} 1027}
@@ -1006,6 +1034,7 @@ void ip6_mr_cleanup(void)
1006#endif 1034#endif
1007 unregister_netdevice_notifier(&ip6_mr_notifier); 1035 unregister_netdevice_notifier(&ip6_mr_notifier);
1008 del_timer(&ipmr_expire_timer); 1036 del_timer(&ipmr_expire_timer);
1037 unregister_pernet_subsys(&ip6mr_net_ops);
1009 kmem_cache_destroy(mrt_cachep); 1038 kmem_cache_destroy(mrt_cachep);
1010} 1039}
1011 1040
@@ -1095,8 +1124,8 @@ static void mroute_clean_tables(struct sock *sk)
1095 /* 1124 /*
1096 * Shut down all active vif entries 1125 * Shut down all active vif entries
1097 */ 1126 */
1098 for (i = 0; i < maxvif; i++) { 1127 for (i = 0; i < init_net.ipv6.maxvif; i++) {
1099 if (!(vif6_table[i].flags & VIFF_STATIC)) 1128 if (!(init_net.ipv6.vif6_table[i].flags & VIFF_STATIC))
1100 mif6_delete(i); 1129 mif6_delete(i);
1101 } 1130 }
1102 1131
@@ -1346,11 +1375,11 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1346 case SIOCGETMIFCNT_IN6: 1375 case SIOCGETMIFCNT_IN6:
1347 if (copy_from_user(&vr, arg, sizeof(vr))) 1376 if (copy_from_user(&vr, arg, sizeof(vr)))
1348 return -EFAULT; 1377 return -EFAULT;
1349 if (vr.mifi >= maxvif) 1378 if (vr.mifi >= init_net.ipv6.maxvif)
1350 return -EINVAL; 1379 return -EINVAL;
1351 read_lock(&mrt_lock); 1380 read_lock(&mrt_lock);
1352 vif = &vif6_table[vr.mifi]; 1381 vif = &init_net.ipv6.vif6_table[vr.mifi];
1353 if (MIF_EXISTS(vr.mifi)) { 1382 if (MIF_EXISTS(&init_net, vr.mifi)) {
1354 vr.icount = vif->pkt_in; 1383 vr.icount = vif->pkt_in;
1355 vr.ocount = vif->pkt_out; 1384 vr.ocount = vif->pkt_out;
1356 vr.ibytes = vif->bytes_in; 1385 vr.ibytes = vif->bytes_in;
@@ -1401,7 +1430,7 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb)
1401static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) 1430static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
1402{ 1431{
1403 struct ipv6hdr *ipv6h; 1432 struct ipv6hdr *ipv6h;
1404 struct mif_device *vif = &vif6_table[vifi]; 1433 struct mif_device *vif = &init_net.ipv6.vif6_table[vifi];
1405 struct net_device *dev; 1434 struct net_device *dev;
1406 struct dst_entry *dst; 1435 struct dst_entry *dst;
1407 struct flowi fl; 1436 struct flowi fl;
@@ -1474,8 +1503,8 @@ out_free:
1474static int ip6mr_find_vif(struct net_device *dev) 1503static int ip6mr_find_vif(struct net_device *dev)
1475{ 1504{
1476 int ct; 1505 int ct;
1477 for (ct = maxvif - 1; ct >= 0; ct--) { 1506 for (ct = init_net.ipv6.maxvif - 1; ct >= 0; ct--) {
1478 if (vif6_table[ct].dev == dev) 1507 if (init_net.ipv6.vif6_table[ct].dev == dev)
1479 break; 1508 break;
1480 } 1509 }
1481 return ct; 1510 return ct;
@@ -1493,7 +1522,7 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
1493 /* 1522 /*
1494 * Wrong interface: drop packet and (maybe) send PIM assert. 1523 * Wrong interface: drop packet and (maybe) send PIM assert.
1495 */ 1524 */
1496 if (vif6_table[vif].dev != skb->dev) { 1525 if (init_net.ipv6.vif6_table[vif].dev != skb->dev) {
1497 int true_vifi; 1526 int true_vifi;
1498 1527
1499 cache->mfc_un.res.wrong_if++; 1528 cache->mfc_un.res.wrong_if++;
@@ -1514,8 +1543,8 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
1514 goto dont_forward; 1543 goto dont_forward;
1515 } 1544 }
1516 1545
1517 vif6_table[vif].pkt_in++; 1546 init_net.ipv6.vif6_table[vif].pkt_in++;
1518 vif6_table[vif].bytes_in += skb->len; 1547 init_net.ipv6.vif6_table[vif].bytes_in += skb->len;
1519 1548
1520 /* 1549 /*
1521 * Forward the frame 1550 * Forward the frame
@@ -1583,7 +1612,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
1583{ 1612{
1584 int ct; 1613 int ct;
1585 struct rtnexthop *nhp; 1614 struct rtnexthop *nhp;
1586 struct net_device *dev = vif6_table[c->mf6c_parent].dev; 1615 struct net_device *dev = init_net.ipv6.vif6_table[c->mf6c_parent].dev;
1587 u8 *b = skb_tail_pointer(skb); 1616 u8 *b = skb_tail_pointer(skb);
1588 struct rtattr *mp_head; 1617 struct rtattr *mp_head;
1589 1618
@@ -1599,7 +1628,7 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
1599 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 1628 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
1600 nhp->rtnh_flags = 0; 1629 nhp->rtnh_flags = 0;
1601 nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; 1630 nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
1602 nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex; 1631 nhp->rtnh_ifindex = init_net.ipv6.vif6_table[ct].dev->ifindex;
1603 nhp->rtnh_len = sizeof(*nhp); 1632 nhp->rtnh_len = sizeof(*nhp);
1604 } 1633 }
1605 } 1634 }