Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *      Userspace interface
  3  *      Linux ethernet bridge
  4  *
  5  *      Authors:
  6  *      Lennert Buytenhek               <buytenh@gnu.org>
  7  *
  8  *      $Id: br_if.c,v 1.7 2001/12/24 00:59:55 davem Exp $
  9  *
 10  *      This program is free software; you can redistribute it and/or
 11  *      modify it under the terms of the GNU General Public License
 12  *      as published by the Free Software Foundation; either version
 13  *      2 of the License, or (at your option) any later version.
 14  */
 15 
 16 #include <linux/kernel.h>
 17 #include <linux/netdevice.h>
 18 #include <linux/ethtool.h>
 19 #include <linux/if_arp.h>
 20 #include <linux/module.h>
 21 #include <linux/init.h>
 22 #include <linux/rtnetlink.h>
 23 #include <net/sock.h>
 24 
 25 #include "br_private.h"
 26 
 27 /*
 28  * Determine initial path cost based on speed.
 29  * using recommendations from 802.1d standard
 30  *
 31  * Need to simulate user ioctl because not all device's that support
 32  * ethtool, use ethtool_ops.  Also, since driver might sleep need to
 33  * not be holding any locks.
 34  */
 35 static int br_initial_port_cost(struct net_device *dev)
 36 {
 37 
 38         struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 39         struct ifreq ifr;
 40         mm_segment_t old_fs;
 41         int err;
 42 
 43         strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
 44         ifr.ifr_data = (void __user *) &ecmd;
 45 
 46         old_fs = get_fs();
 47         set_fs(KERNEL_DS);
 48         err = dev_ethtool(&ifr);
 49         set_fs(old_fs);
 50         
 51         if (!err) {
 52                 switch(ecmd.speed) {
 53                 case SPEED_100:
 54                         return 19;
 55                 case SPEED_1000:
 56                         return 4;
 57                 case SPEED_10000:
 58                         return 2;
 59                 case SPEED_10:
 60                         return 100;
 61                 default:
 62                         pr_info("bridge: can't decode speed from %s: %d\n",
 63                                 dev->name, ecmd.speed);
 64                         return 100;
 65                 }
 66         }
 67 
 68         /* Old silly heuristics based on name */
 69         if (!strncmp(dev->name, "lec", 3))
 70                 return 7;
 71 
 72         if (!strncmp(dev->name, "plip", 4))
 73                 return 2500;
 74 
 75         return 100;     /* assume old 10Mbps */
 76 }
 77 
 78 static void destroy_nbp(struct net_bridge_port *p)
 79 {
 80         struct net_device *dev = p->dev;
 81 
 82         dev->br_port = NULL;
 83         p->br = NULL;
 84         p->dev = NULL;
 85         dev_put(dev);
 86 
 87         br_sysfs_freeif(p);
 88 }
 89 
 90 static void destroy_nbp_rcu(struct rcu_head *head)
 91 {
 92         struct net_bridge_port *p =
 93                         container_of(head, struct net_bridge_port, rcu);
 94         destroy_nbp(p);
 95 }
 96 
 97 /* called with RTNL */
 98 static void del_nbp(struct net_bridge_port *p)
 99 {
100         struct net_bridge *br = p->br;
101         struct net_device *dev = p->dev;
102 
103         dev_set_promiscuity(dev, -1);
104 
105         spin_lock_bh(&br->lock);
106         br_stp_disable_port(p);
107         spin_unlock_bh(&br->lock);
108 
109         br_fdb_delete_by_port(br, p);
110 
111         list_del_rcu(&p->list);
112 
113         del_timer_sync(&p->message_age_timer);
114         del_timer_sync(&p->forward_delay_timer);
115         del_timer_sync(&p->hold_timer);
116         
117         call_rcu(&p->rcu, destroy_nbp_rcu);
118 }
119 
120 /* called with RTNL */
121 static void del_br(struct net_bridge *br)
122 {
123         struct net_bridge_port *p, *n;
124 
125         list_for_each_entry_safe(p, n, &br->port_list, list) {
126                 br_sysfs_removeif(p);
127                 del_nbp(p);
128         }
129 
130         del_timer_sync(&br->gc_timer);
131 
132         br_sysfs_delbr(br->dev);
133         unregister_netdevice(br->dev);
134 }
135 
136 static struct net_device *new_bridge_dev(const char *name)
137 {
138         struct net_bridge *br;
139         struct net_device *dev;
140 
141         dev = alloc_netdev(sizeof(struct net_bridge), name,
142                            br_dev_setup);
143         
144         if (!dev)
145                 return NULL;
146 
147         br = netdev_priv(dev);
148         br->dev = dev;
149 
150         spin_lock_init(&br->lock);
151         INIT_LIST_HEAD(&br->port_list);
152         spin_lock_init(&br->hash_lock);
153 
154         br->bridge_id.prio[0] = 0x80;
155         br->bridge_id.prio[1] = 0x00;
156         memset(br->bridge_id.addr, 0, ETH_ALEN);
157 
158         br->stp_enabled = 0;
159         br->designated_root = br->bridge_id;
160         br->root_path_cost = 0;
161         br->root_port = 0;
162         br->bridge_max_age = br->max_age = 20 * HZ;
163         br->bridge_hello_time = br->hello_time = 2 * HZ;
164         br->bridge_forward_delay = br->forward_delay = 15 * HZ;
165         br->topology_change = 0;
166         br->topology_change_detected = 0;
167         br->ageing_time = 300 * HZ;
168         INIT_LIST_HEAD(&br->age_list);
169 
170         br_stp_timer_init(br);
171 
172         return dev;
173 }
174 
175 /* find an available port number */
176 static int find_portno(struct net_bridge *br)
177 {
178         int index;
179         struct net_bridge_port *p;
180         unsigned long *inuse;
181 
182         inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long),
183                         GFP_KERNEL);
184         if (!inuse)
185                 return -ENOMEM;
186 
187         memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long));
188         set_bit(0, inuse);      /* zero is reserved */
189         list_for_each_entry(p, &br->port_list, list) {
190                 set_bit(p->port_no, inuse);
191         }
192         index = find_first_zero_bit(inuse, BR_MAX_PORTS);
193         kfree(inuse);
194 
195         return (index >= BR_MAX_PORTS) ? -EXFULL : index;
196 }
197 
198 /* called with RTNL */
199 static struct net_bridge_port *new_nbp(struct net_bridge *br, 
200                                        struct net_device *dev,
201                                        unsigned long cost)
202 {
203         int index;
204         struct net_bridge_port *p;
205         
206         index = find_portno(br);
207         if (index < 0)
208                 return ERR_PTR(index);
209 
210         p = kmalloc(sizeof(*p), GFP_KERNEL);
211         if (p == NULL)
212                 return ERR_PTR(-ENOMEM);
213 
214         memset(p, 0, sizeof(*p));
215         p->br = br;
216         dev_hold(dev);
217         p->dev = dev;
218         p->path_cost = cost;
219         p->priority = 0x8000 >> BR_PORT_BITS;
220         dev->br_port = p;
221         p->port_no = index;
222         br_init_port(p);
223         p->state = BR_STATE_DISABLED;
224         kobject_init(&p->kobj);
225 
226         return p;
227 }
228 
229 int br_add_bridge(const char *name)
230 {
231         struct net_device *dev;
232         int ret;
233 
234         dev = new_bridge_dev(name);
235         if (!dev) 
236                 return -ENOMEM;
237 
238         rtnl_lock();
239         if (strchr(dev->name, '%')) {
240                 ret = dev_alloc_name(dev, dev->name);
241                 if (ret < 0)
242                         goto err1;
243         }
244 
245         ret = register_netdevice(dev);
246         if (ret)
247                 goto err2;
248 
249         /* network device kobject is not setup until
250          * after rtnl_unlock does it's hotplug magic.
251          * so hold reference to avoid race.
252          */
253         dev_hold(dev);
254         rtnl_unlock();
255 
256         ret = br_sysfs_addbr(dev);
257         dev_put(dev);
258 
259         if (ret) 
260                 unregister_netdev(dev);
261  out:
262         return ret;
263 
264  err2:
265         free_netdev(dev);
266  err1:
267         rtnl_unlock();
268         goto out;
269 }
270 
271 int br_del_bridge(const char *name)
272 {
273         struct net_device *dev;
274         int ret = 0;
275 
276         rtnl_lock();
277         dev = __dev_get_by_name(name);
278         if (dev == NULL) 
279                 ret =  -ENXIO;  /* Could not find device */
280 
281         else if (!(dev->priv_flags & IFF_EBRIDGE)) {
282                 /* Attempt to delete non bridge device! */
283                 ret = -EPERM;
284         }
285 
286         else if (dev->flags & IFF_UP) {
287                 /* Not shutdown yet. */
288                 ret = -EBUSY;
289         } 
290 
291         else 
292                 del_br(netdev_priv(dev));
293 
294         rtnl_unlock();
295         return ret;
296 }
297 
298 /* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */
299 int br_min_mtu(const struct net_bridge *br)
300 {
301         const struct net_bridge_port *p;
302         int mtu = 0;
303 
304         ASSERT_RTNL();
305 
306         if (list_empty(&br->port_list))
307                 mtu = 1500;
308         else {
309                 list_for_each_entry(p, &br->port_list, list) {
310                         if (!mtu  || p->dev->mtu < mtu)
311                                 mtu = p->dev->mtu;
312                 }
313         }
314         return mtu;
315 }
316 
317 /* called with RTNL */
318 int br_add_if(struct net_bridge *br, struct net_device *dev)
319 {
320         struct net_bridge_port *p;
321         int err = 0;
322 
323         if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
324                 return -EINVAL;
325 
326         if (dev->hard_start_xmit == br_dev_xmit)
327                 return -ELOOP;
328 
329         if (dev->br_port != NULL)
330                 return -EBUSY;
331 
332         if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
333                 return PTR_ERR(p);
334 
335         if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))
336                 destroy_nbp(p);
337  
338         else if ((err = br_sysfs_addif(p)))
339                 del_nbp(p);
340         else {
341                 dev_set_promiscuity(dev, 1);
342 
343                 list_add_rcu(&p->list, &br->port_list);
344 
345                 spin_lock_bh(&br->lock);
346                 br_stp_recalculate_bridge_id(br);
347                 if ((br->dev->flags & IFF_UP) 
348                     && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
349                         br_stp_enable_port(p);
350                 spin_unlock_bh(&br->lock);
351 
352                 dev_set_mtu(br->dev, br_min_mtu(br));
353         }
354 
355         return err;
356 }
357 
358 /* called with RTNL */
359 int br_del_if(struct net_bridge *br, struct net_device *dev)
360 {
361         struct net_bridge_port *p = dev->br_port;
362         
363         if (!p || p->br != br) 
364                 return -EINVAL;
365 
366         br_sysfs_removeif(p);
367         del_nbp(p);
368 
369         spin_lock_bh(&br->lock);
370         br_stp_recalculate_bridge_id(br);
371         spin_unlock_bh(&br->lock);
372 
373         return 0;
374 }
375 
376 void __exit br_cleanup_bridges(void)
377 {
378         struct net_device *dev, *nxt;
379 
380         rtnl_lock();
381         for (dev = dev_base; dev; dev = nxt) {
382                 nxt = dev->next;
383                 if (dev->priv_flags & IFF_EBRIDGE)
384                         del_br(dev->priv);
385         }
386         rtnl_unlock();
387 
388 }
389 
  This page was automatically generated by the LXR engine.