diff options
author | Benjamin Thery <benjamin.thery@bull.net> | 2008-12-10 19:15:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-10 19:15:08 -0500 |
commit | 4e16880cb4225bfa68878ad5b2a9ded53657d054 (patch) | |
tree | 6a8c15e47fe33edede4c4bd79c05dabc5ca2f79c /net/ipv6 | |
parent | bd91b8bf372911c1e4d66d6bb44fe409349a6791 (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')
-rw-r--r-- | net/ipv6/ip6mr.c | 107 |
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 | ||
62 | static struct mif_device vif6_table[MAXMIFS]; /* Devices */ | 62 | #define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL) |
63 | static int maxvif; | ||
64 | |||
65 | #define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL) | ||
66 | 63 | ||
67 | static int mroute_do_assert; /* Set in PIM assert */ | 64 | static 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 { | |||
145 | static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, | 142 | static 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 | |||
600 | static int mif6_add(struct mif6ctl *vifc, int mrtsock) | 598 | static 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 | ||
963 | static 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 | } | ||
973 | fail: | ||
974 | return err; | ||
975 | } | ||
976 | |||
977 | static void __net_exit ip6mr_net_exit(struct net *net) | ||
978 | { | ||
979 | kfree(net->ipv6.vif6_table); | ||
980 | } | ||
981 | |||
982 | static struct pernet_operations ip6mr_net_ops = { | ||
983 | .init = ip6mr_net_init, | ||
984 | .exit = ip6mr_net_exit, | ||
985 | }; | ||
986 | |||
965 | int __init ip6_mr_init(void) | 987 | int __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 |
995 | reg_notif_fail: | 1021 | reg_notif_fail: |
996 | del_timer(&ipmr_expire_timer); | 1022 | del_timer(&ipmr_expire_timer); |
1023 | unregister_pernet_subsys(&ip6mr_net_ops); | ||
1024 | reg_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) | |||
1401 | static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | 1430 | static 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: | |||
1474 | static int ip6mr_find_vif(struct net_device *dev) | 1503 | static 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 | } |