Import 2.3.49pre2
[davej-history.git] / drivers / net / bonding.c
blobf1a4526d44d3cad90e1dbb80d4f1cfc96f6a9077
1 /*
2 * originally based on the dummy device.
4 * Copyright 1999, Thomas Davis, tadavis@lbl.gov.
5 * Licensed under the GPL. Based on dummy.c, and eql.c devices.
7 * bond.c: a bonding/etherchannel/sun trunking net driver
9 * This is useful to talk to a Cisco 5500, running Etherchannel, aka:
10 * Linux Channel Bonding
11 * Sun Trunking (Solaris)
13 * How it works:
14 * ifconfig bond0 ipaddress netmask up
15 * will setup a network device, with an ip address. No mac address
16 * will be assigned at this time. The hw mac address will come from
17 * the first slave bonded to the channel. All slaves will then use
18 * this hw mac address.
20 * ifconfig bond0 down
21 * will release all slaves, marking them as down.
23 * ifenslave bond0 eth0
24 * will attache eth0 to bond0 as a slave. eth0 hw mac address will either
25 * a: be used as initial mac address
26 * b: if a hw mac address already is there, eth0's hw mac address
27 * will then be set from bond0.
29 * v0.1 - first working version.
30 * v0.2 - changed stats to be calculated by summing slaves stats.
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/sched.h>
37 #include <linux/types.h>
38 #include <linux/fcntl.h>
39 #include <linux/interrupt.h>
40 #include <linux/ptrace.h>
41 #include <linux/ioport.h>
42 #include <linux/in.h>
43 #include <linux/malloc.h>
44 #include <linux/string.h>
45 #include <linux/init.h>
46 #include <asm/system.h>
47 #include <asm/bitops.h>
48 #include <asm/io.h>
49 #include <asm/dma.h>
50 #include <asm/uaccess.h>
51 #include <linux/errno.h>
53 #include <linux/netdevice.h>
54 #include <linux/etherdevice.h>
55 #include <linux/skbuff.h>
57 #include <linux/if_bonding.h>
59 typedef struct slave
61 struct slave *next;
62 struct slave *prev;
63 struct net_device *dev;
64 } slave_t;
66 typedef struct bonding
68 slave_t *next;
69 slave_t *prev;
70 struct net_device *master;
72 slave_t *current_slave;
73 struct net_device_stats stats;
74 } bonding_t;
77 static int bond_xmit(struct sk_buff *skb, struct net_device *dev);
78 static struct net_device_stats *bond_get_stats(struct net_device *dev);
80 static struct net_device *this_bond;
82 static int bond_open(struct net_device *dev)
84 MOD_INC_USE_COUNT;
85 return 0;
88 static int bond_close(struct net_device *master)
90 bonding_t *bond = master->priv;
91 slave_t *slave;
93 while ((slave = bond->next) != (slave_t*)bond) {
95 spin_lock_bh(&master->xmit_lock);
96 slave->next->prev = slave->prev;
97 slave->prev->next = slave->next;
98 bond->current_slave = (slave_t*)bond;
99 spin_unlock_bh(&master->xmit_lock);
101 netdev_set_master(slave->dev, NULL);
103 kfree(slave);
106 MOD_DEC_USE_COUNT;
107 return 0;
110 /* Fake multicast ability.
112 NB. It is possible and necessary to make it true one, otherwise
113 the device is not functional.
115 static void bond_set_multicast_list(struct net_device *dev)
119 static int bond_enslave(struct net_device *master, struct net_device *dev)
121 int err;
122 bonding_t *bond = master->priv;
123 slave_t *slave;
125 if (dev->type != master->type)
126 return -ENODEV;
128 if ((slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL)
129 return -ENOMEM;
131 memset(slave, 0, sizeof(slave_t));
133 err = netdev_set_master(dev, master);
134 if (err) {
135 kfree(slave);
136 return err;
139 slave->dev = dev;
141 spin_lock_bh(&master->xmit_lock);
143 dev_hold(dev);
145 slave->prev = bond->prev;
146 slave->next = (slave_t*)bond;
147 slave->prev->next = slave;
148 slave->next->prev = slave;
150 spin_unlock_bh(&master->xmit_lock);
152 MOD_INC_USE_COUNT;
153 return 0;
156 static int bond_release(struct net_device *master, struct net_device *dev)
158 bonding_t *bond = master->priv;
159 slave_t *slave;
161 if (dev->master != master)
162 return -EINVAL;
164 netdev_set_master(dev, NULL);
166 for (slave = bond->next; slave != (slave_t*)bond; slave = slave->next) {
167 if (slave->dev == dev) {
168 spin_lock_bh(&master->xmit_lock);
169 if (bond->current_slave == slave)
170 bond->current_slave = slave->next;
171 slave->next->prev = slave->prev;
172 slave->prev->next = slave->next;
173 spin_unlock_bh(&master->xmit_lock);
175 kfree(slave);
176 dev_put(dev);
177 MOD_DEC_USE_COUNT;
178 break;
182 return 0;
185 /* It is pretty silly, SIOCSIFHWADDR exists to make this. */
187 static int bond_sethwaddr(struct net_device *master, struct net_device *slave)
189 memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
190 return 0;
193 static int bond_ioctl(struct net_device *master, struct ifreq *ifr, int cmd)
195 struct net_device *slave = __dev_get_by_name(ifr->ifr_slave);
197 if (slave == NULL)
198 return -ENODEV;
200 switch (cmd) {
201 case BOND_ENSLAVE:
202 return bond_enslave(master, slave);
203 case BOND_RELEASE:
204 return bond_release(master, slave);
205 case BOND_SETHWADDR:
206 return bond_sethwaddr(master, slave);
207 default:
208 return -EOPNOTSUPP;
212 static int bond_event(struct notifier_block *this, unsigned long event, void *ptr)
214 struct net_device *slave = ptr;
216 if (this_bond == NULL ||
217 this_bond == slave ||
218 this_bond != slave->master)
219 return NOTIFY_DONE;
221 switch (event) {
222 case NETDEV_UNREGISTER:
223 bond_release(this_bond, slave);
224 break;
227 return NOTIFY_DONE;
230 struct notifier_block bond_netdev_notifier={
231 bond_event,
232 NULL,
236 int __init bond_init(struct net_device *dev)
238 bonding_t *bond;
240 bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);
241 if (bond == NULL)
242 return -ENOMEM;
244 memset(bond, 0, sizeof(struct bonding));
245 bond->next = (slave_t*)bond;
246 bond->prev = (slave_t*)bond;
247 bond->master = dev;
248 bond->current_slave = (slave_t*)bond;
249 dev->priv = bond;
251 /* Initialize the device structure. */
252 dev->hard_start_xmit = bond_xmit;
253 dev->get_stats = bond_get_stats;
254 dev->open = bond_open;
255 dev->stop = bond_close;
256 dev->set_multicast_list = bond_set_multicast_list;
257 dev->do_ioctl = bond_ioctl;
259 /* Fill in the fields of the device structure with ethernet-generic
260 values. */
261 ether_setup(dev);
262 dev->tx_queue_len = 0;
263 dev->flags |= IFF_MASTER;
265 this_bond = dev;
267 register_netdevice_notifier(&bond_netdev_notifier);
269 return 0;
272 static int bond_xmit(struct sk_buff *skb, struct net_device *dev)
274 bonding_t *bond = dev->priv;
275 slave_t *slave, *start_at;
276 int pkt_len = skb->len;
278 slave = start_at = bond->current_slave;
280 do {
281 if (slave == (slave_t*)bond)
282 continue;
284 if (netif_running(slave->dev) && netif_carrier_ok(dev)) {
285 bond->current_slave = slave->next;
286 skb->dev = slave->dev;
288 if (dev_queue_xmit(skb)) {
289 bond->stats.tx_dropped++;
290 } else {
291 bond->stats.tx_packets++;
292 bond->stats.tx_bytes += pkt_len;
294 return 0;
296 } while ((slave = slave->next) != start_at);
298 bond->stats.tx_dropped++;
299 kfree_skb(skb);
300 return 0;
303 static struct net_device_stats *bond_get_stats(struct net_device *dev)
305 bonding_t *bond = dev->priv;
307 return &bond->stats;
310 #ifdef MODULE
312 static char bond_name[16];
314 static struct net_device dev_bond = {
315 bond_name, /* Needs to be writeable */
316 0, 0, 0, 0,
317 0x0, 0,
318 0, 0, 0, NULL, bond_init };
320 int init_module(void)
322 /* Find a name for this unit */
323 int err=dev_alloc_name(&dev_bond,"bond%d");
325 if (err<0)
326 return err;
328 if (register_netdev(&dev_bond) != 0)
329 return -EIO;
331 return 0;
334 void cleanup_module(void)
336 unregister_netdevice_notifier(&bond_netdev_notifier);
338 unregister_netdev(&dev_bond);
340 kfree(dev_bond.priv);
342 #endif /* MODULE */
345 * Local variables:
346 * c-indent-level: 8
347 * c-basic-offset: 8
348 * tab-width: 8
349 * End: