diff options
author | Eric W. Biederman <ebiederm@aristanetworks.com> | 2009-10-29 10:18:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-30 15:41:21 -0400 |
commit | ec87fd3b4e111e8bc367d247a963e27e5b86df26 (patch) | |
tree | 8c33611b3e0afb37bcad232c2ad8d8f52d469634 /drivers/net/bonding/bond_main.c | |
parent | 88ead977109da926a03068e277869ea8fedd170d (diff) |
bond: Add support for multiple network namespaces
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 111 |
1 files changed, 74 insertions, 37 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 405971374fe2..208d2c4ef068 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #include <linux/jiffies.h> | 75 | #include <linux/jiffies.h> |
76 | #include <net/route.h> | 76 | #include <net/route.h> |
77 | #include <net/net_namespace.h> | 77 | #include <net/net_namespace.h> |
78 | #include <net/netns/generic.h> | ||
78 | #include "bonding.h" | 79 | #include "bonding.h" |
79 | #include "bond_3ad.h" | 80 | #include "bond_3ad.h" |
80 | #include "bond_alb.h" | 81 | #include "bond_alb.h" |
@@ -157,11 +158,7 @@ MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the | |||
157 | static const char * const version = | 158 | static const char * const version = |
158 | DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; | 159 | DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; |
159 | 160 | ||
160 | LIST_HEAD(bond_dev_list); | 161 | int bond_net_id; |
161 | |||
162 | #ifdef CONFIG_PROC_FS | ||
163 | static struct proc_dir_entry *bond_proc_dir; | ||
164 | #endif | ||
165 | 162 | ||
166 | static __be32 arp_target[BOND_MAX_ARP_TARGETS]; | 163 | static __be32 arp_target[BOND_MAX_ARP_TARGETS]; |
167 | static int arp_ip_count; | 164 | static int arp_ip_count; |
@@ -2586,7 +2583,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2586 | fl.fl4_dst = targets[i]; | 2583 | fl.fl4_dst = targets[i]; |
2587 | fl.fl4_tos = RTO_ONLINK; | 2584 | fl.fl4_tos = RTO_ONLINK; |
2588 | 2585 | ||
2589 | rv = ip_route_output_key(&init_net, &rt, &fl); | 2586 | rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl); |
2590 | if (rv) { | 2587 | if (rv) { |
2591 | if (net_ratelimit()) { | 2588 | if (net_ratelimit()) { |
2592 | pr_warning(DRV_NAME | 2589 | pr_warning(DRV_NAME |
@@ -2694,9 +2691,6 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack | |||
2694 | unsigned char *arp_ptr; | 2691 | unsigned char *arp_ptr; |
2695 | __be32 sip, tip; | 2692 | __be32 sip, tip; |
2696 | 2693 | ||
2697 | if (dev_net(dev) != &init_net) | ||
2698 | goto out; | ||
2699 | |||
2700 | if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) | 2694 | if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) |
2701 | goto out; | 2695 | goto out; |
2702 | 2696 | ||
@@ -3359,10 +3353,11 @@ static const struct file_operations bond_info_fops = { | |||
3359 | static void bond_create_proc_entry(struct bonding *bond) | 3353 | static void bond_create_proc_entry(struct bonding *bond) |
3360 | { | 3354 | { |
3361 | struct net_device *bond_dev = bond->dev; | 3355 | struct net_device *bond_dev = bond->dev; |
3356 | struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); | ||
3362 | 3357 | ||
3363 | if (bond_proc_dir) { | 3358 | if (bn->proc_dir) { |
3364 | bond->proc_entry = proc_create_data(bond_dev->name, | 3359 | bond->proc_entry = proc_create_data(bond_dev->name, |
3365 | S_IRUGO, bond_proc_dir, | 3360 | S_IRUGO, bn->proc_dir, |
3366 | &bond_info_fops, bond); | 3361 | &bond_info_fops, bond); |
3367 | if (bond->proc_entry == NULL) | 3362 | if (bond->proc_entry == NULL) |
3368 | pr_warning(DRV_NAME | 3363 | pr_warning(DRV_NAME |
@@ -3375,8 +3370,11 @@ static void bond_create_proc_entry(struct bonding *bond) | |||
3375 | 3370 | ||
3376 | static void bond_remove_proc_entry(struct bonding *bond) | 3371 | static void bond_remove_proc_entry(struct bonding *bond) |
3377 | { | 3372 | { |
3378 | if (bond_proc_dir && bond->proc_entry) { | 3373 | struct net_device *bond_dev = bond->dev; |
3379 | remove_proc_entry(bond->proc_file_name, bond_proc_dir); | 3374 | struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); |
3375 | |||
3376 | if (bn->proc_dir && bond->proc_entry) { | ||
3377 | remove_proc_entry(bond->proc_file_name, bn->proc_dir); | ||
3380 | memset(bond->proc_file_name, 0, IFNAMSIZ); | 3378 | memset(bond->proc_file_name, 0, IFNAMSIZ); |
3381 | bond->proc_entry = NULL; | 3379 | bond->proc_entry = NULL; |
3382 | } | 3380 | } |
@@ -3385,11 +3383,11 @@ static void bond_remove_proc_entry(struct bonding *bond) | |||
3385 | /* Create the bonding directory under /proc/net, if doesn't exist yet. | 3383 | /* Create the bonding directory under /proc/net, if doesn't exist yet. |
3386 | * Caller must hold rtnl_lock. | 3384 | * Caller must hold rtnl_lock. |
3387 | */ | 3385 | */ |
3388 | static void bond_create_proc_dir(void) | 3386 | static void bond_create_proc_dir(struct bond_net *bn) |
3389 | { | 3387 | { |
3390 | if (!bond_proc_dir) { | 3388 | if (!bn->proc_dir) { |
3391 | bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net); | 3389 | bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net); |
3392 | if (!bond_proc_dir) | 3390 | if (!bn->proc_dir) |
3393 | pr_warning(DRV_NAME | 3391 | pr_warning(DRV_NAME |
3394 | ": Warning: cannot create /proc/net/%s\n", | 3392 | ": Warning: cannot create /proc/net/%s\n", |
3395 | DRV_NAME); | 3393 | DRV_NAME); |
@@ -3399,11 +3397,11 @@ static void bond_create_proc_dir(void) | |||
3399 | /* Destroy the bonding directory under /proc/net, if empty. | 3397 | /* Destroy the bonding directory under /proc/net, if empty. |
3400 | * Caller must hold rtnl_lock. | 3398 | * Caller must hold rtnl_lock. |
3401 | */ | 3399 | */ |
3402 | static void bond_destroy_proc_dir(void) | 3400 | static void bond_destroy_proc_dir(struct bond_net *bn) |
3403 | { | 3401 | { |
3404 | if (bond_proc_dir) { | 3402 | if (bn->proc_dir) { |
3405 | remove_proc_entry(DRV_NAME, init_net.proc_net); | 3403 | remove_proc_entry(DRV_NAME, bn->net->proc_net); |
3406 | bond_proc_dir = NULL; | 3404 | bn->proc_dir = NULL; |
3407 | } | 3405 | } |
3408 | } | 3406 | } |
3409 | 3407 | ||
@@ -3417,11 +3415,11 @@ static void bond_remove_proc_entry(struct bonding *bond) | |||
3417 | { | 3415 | { |
3418 | } | 3416 | } |
3419 | 3417 | ||
3420 | static void bond_create_proc_dir(void) | 3418 | static void bond_create_proc_dir(struct bond_net *bn) |
3421 | { | 3419 | { |
3422 | } | 3420 | } |
3423 | 3421 | ||
3424 | static void bond_destroy_proc_dir(void) | 3422 | static void bond_destroy_proc_dir(struct bond_net *bn) |
3425 | { | 3423 | { |
3426 | } | 3424 | } |
3427 | 3425 | ||
@@ -3540,9 +3538,6 @@ static int bond_netdev_event(struct notifier_block *this, | |||
3540 | { | 3538 | { |
3541 | struct net_device *event_dev = (struct net_device *)ptr; | 3539 | struct net_device *event_dev = (struct net_device *)ptr; |
3542 | 3540 | ||
3543 | if (dev_net(event_dev) != &init_net) | ||
3544 | return NOTIFY_DONE; | ||
3545 | |||
3546 | pr_debug("event_dev: %s, event: %lx\n", | 3541 | pr_debug("event_dev: %s, event: %lx\n", |
3547 | (event_dev ? event_dev->name : "None"), | 3542 | (event_dev ? event_dev->name : "None"), |
3548 | event); | 3543 | event); |
@@ -3575,13 +3570,11 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
3575 | { | 3570 | { |
3576 | struct in_ifaddr *ifa = ptr; | 3571 | struct in_ifaddr *ifa = ptr; |
3577 | struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev; | 3572 | struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev; |
3573 | struct bond_net *bn = net_generic(dev_net(event_dev), bond_net_id); | ||
3578 | struct bonding *bond; | 3574 | struct bonding *bond; |
3579 | struct vlan_entry *vlan; | 3575 | struct vlan_entry *vlan; |
3580 | 3576 | ||
3581 | if (dev_net(ifa->ifa_dev->dev) != &init_net) | 3577 | list_for_each_entry(bond, &bn->dev_list, bond_list) { |
3582 | return NOTIFY_DONE; | ||
3583 | |||
3584 | list_for_each_entry(bond, &bond_dev_list, bond_list) { | ||
3585 | if (bond->dev == event_dev) { | 3578 | if (bond->dev == event_dev) { |
3586 | switch (event) { | 3579 | switch (event) { |
3587 | case NETDEV_UP: | 3580 | case NETDEV_UP: |
@@ -3950,7 +3943,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
3950 | if (!capable(CAP_NET_ADMIN)) | 3943 | if (!capable(CAP_NET_ADMIN)) |
3951 | return -EPERM; | 3944 | return -EPERM; |
3952 | 3945 | ||
3953 | slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave); | 3946 | slave_dev = dev_get_by_name(dev_net(bond_dev), ifr->ifr_slave); |
3954 | 3947 | ||
3955 | pr_debug("slave_dev=%p: \n", slave_dev); | 3948 | pr_debug("slave_dev=%p: \n", slave_dev); |
3956 | 3949 | ||
@@ -5031,6 +5024,7 @@ static void bond_set_lockdep_class(struct net_device *dev) | |||
5031 | static int bond_init(struct net_device *bond_dev) | 5024 | static int bond_init(struct net_device *bond_dev) |
5032 | { | 5025 | { |
5033 | struct bonding *bond = netdev_priv(bond_dev); | 5026 | struct bonding *bond = netdev_priv(bond_dev); |
5027 | struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); | ||
5034 | 5028 | ||
5035 | pr_debug("Begin bond_init for %s\n", bond_dev->name); | 5029 | pr_debug("Begin bond_init for %s\n", bond_dev->name); |
5036 | 5030 | ||
@@ -5043,7 +5037,7 @@ static int bond_init(struct net_device *bond_dev) | |||
5043 | netif_carrier_off(bond_dev); | 5037 | netif_carrier_off(bond_dev); |
5044 | 5038 | ||
5045 | bond_create_proc_entry(bond); | 5039 | bond_create_proc_entry(bond); |
5046 | list_add_tail(&bond->bond_list, &bond_dev_list); | 5040 | list_add_tail(&bond->bond_list, &bn->dev_list); |
5047 | 5041 | ||
5048 | bond_prepare_sysfs_group(bond); | 5042 | bond_prepare_sysfs_group(bond); |
5049 | return 0; | 5043 | return 0; |
@@ -5071,7 +5065,7 @@ static struct rtnl_link_ops bond_link_ops __read_mostly = { | |||
5071 | * Caller must NOT hold rtnl_lock; we need to release it here before we | 5065 | * Caller must NOT hold rtnl_lock; we need to release it here before we |
5072 | * set up our sysfs entries. | 5066 | * set up our sysfs entries. |
5073 | */ | 5067 | */ |
5074 | int bond_create(const char *name) | 5068 | int bond_create(struct net *net, const char *name) |
5075 | { | 5069 | { |
5076 | struct net_device *bond_dev; | 5070 | struct net_device *bond_dev; |
5077 | int res; | 5071 | int res; |
@@ -5087,6 +5081,7 @@ int bond_create(const char *name) | |||
5087 | goto out; | 5081 | goto out; |
5088 | } | 5082 | } |
5089 | 5083 | ||
5084 | dev_net_set(bond_dev, net); | ||
5090 | bond_dev->rtnl_link_ops = &bond_link_ops; | 5085 | bond_dev->rtnl_link_ops = &bond_link_ops; |
5091 | 5086 | ||
5092 | if (!name) { | 5087 | if (!name) { |
@@ -5105,6 +5100,46 @@ out_netdev: | |||
5105 | goto out; | 5100 | goto out; |
5106 | } | 5101 | } |
5107 | 5102 | ||
5103 | static int bond_net_init(struct net *net) | ||
5104 | { | ||
5105 | struct bond_net *bn; | ||
5106 | int err; | ||
5107 | |||
5108 | err = -ENOMEM; | ||
5109 | bn = kzalloc(sizeof(struct bond_net), GFP_KERNEL); | ||
5110 | if (bn == NULL) | ||
5111 | goto out; | ||
5112 | |||
5113 | bn->net = net; | ||
5114 | INIT_LIST_HEAD(&bn->dev_list); | ||
5115 | |||
5116 | err = net_assign_generic(net, bond_net_id, bn); | ||
5117 | if (err) | ||
5118 | goto out_free; | ||
5119 | |||
5120 | bond_create_proc_dir(bn); | ||
5121 | out: | ||
5122 | return err; | ||
5123 | out_free: | ||
5124 | kfree(bn); | ||
5125 | goto out; | ||
5126 | } | ||
5127 | |||
5128 | static void bond_net_exit(struct net *net) | ||
5129 | { | ||
5130 | struct bond_net *bn; | ||
5131 | |||
5132 | bn = net_generic(net, bond_net_id); | ||
5133 | |||
5134 | bond_destroy_proc_dir(bn); | ||
5135 | kfree(bn); | ||
5136 | } | ||
5137 | |||
5138 | static struct pernet_operations bond_net_ops = { | ||
5139 | .init = bond_net_init, | ||
5140 | .exit = bond_net_exit, | ||
5141 | }; | ||
5142 | |||
5108 | static int __init bonding_init(void) | 5143 | static int __init bonding_init(void) |
5109 | { | 5144 | { |
5110 | int i; | 5145 | int i; |
@@ -5116,14 +5151,16 @@ static int __init bonding_init(void) | |||
5116 | if (res) | 5151 | if (res) |
5117 | goto out; | 5152 | goto out; |
5118 | 5153 | ||
5119 | bond_create_proc_dir(); | 5154 | res = register_pernet_gen_subsys(&bond_net_id, &bond_net_ops); |
5155 | if (res) | ||
5156 | goto out; | ||
5120 | 5157 | ||
5121 | res = rtnl_link_register(&bond_link_ops); | 5158 | res = rtnl_link_register(&bond_link_ops); |
5122 | if (res) | 5159 | if (res) |
5123 | goto err; | 5160 | goto err; |
5124 | 5161 | ||
5125 | for (i = 0; i < max_bonds; i++) { | 5162 | for (i = 0; i < max_bonds; i++) { |
5126 | res = bond_create(NULL); | 5163 | res = bond_create(&init_net, NULL); |
5127 | if (res) | 5164 | if (res) |
5128 | goto err; | 5165 | goto err; |
5129 | } | 5166 | } |
@@ -5139,7 +5176,7 @@ out: | |||
5139 | return res; | 5176 | return res; |
5140 | err: | 5177 | err: |
5141 | rtnl_link_unregister(&bond_link_ops); | 5178 | rtnl_link_unregister(&bond_link_ops); |
5142 | bond_destroy_proc_dir(); | 5179 | unregister_pernet_gen_subsys(bond_net_id, &bond_net_ops); |
5143 | goto out; | 5180 | goto out; |
5144 | 5181 | ||
5145 | } | 5182 | } |
@@ -5153,7 +5190,7 @@ static void __exit bonding_exit(void) | |||
5153 | bond_destroy_sysfs(); | 5190 | bond_destroy_sysfs(); |
5154 | 5191 | ||
5155 | rtnl_link_unregister(&bond_link_ops); | 5192 | rtnl_link_unregister(&bond_link_ops); |
5156 | bond_destroy_proc_dir(); | 5193 | unregister_pernet_gen_subsys(bond_net_id, &bond_net_ops); |
5157 | } | 5194 | } |
5158 | 5195 | ||
5159 | module_init(bonding_init); | 5196 | module_init(bonding_init); |