ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / net / bridge / br_device.c
1 /*
2  *      Device handling code
3  *      Linux ethernet bridge
4  *
5  *      Authors:
6  *      Lennert Buytenhek               <buytenh@gnu.org>
7  *
8  *      $Id: br_device.c,v 1.6 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/module.h>
19 #include <asm/uaccess.h>
20 #include "br_private.h"
21
22 static int br_dev_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
23 {
24         unsigned long args[4];
25         unsigned long *data;
26
27         if (cmd != SIOCDEVPRIVATE)
28                 return -EOPNOTSUPP;
29
30         data = (unsigned long *)rq->ifr_data;
31         if (copy_from_user(args, data, 4*sizeof(unsigned long)))
32                 return -EFAULT;
33
34         return br_ioctl_device(dev->priv, args[0], args[1], args[2], args[3]);
35 }
36
37 static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
38 {
39         struct net_bridge *br;
40
41         br = dev->priv;
42
43         return &br->statistics;
44 }
45
46 static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
47 {
48         struct net_bridge *br;
49         unsigned char *dest;
50         struct net_bridge_fdb_entry *dst;
51
52         br = dev->priv;
53         br->statistics.tx_packets++;
54         br->statistics.tx_bytes += skb->len;
55
56         dest = skb->mac.raw = skb->data;
57         skb_pull(skb, ETH_HLEN);
58
59         if (dest[0] & 1) {
60                 br_flood_deliver(br, skb, 0);
61                 return 0;
62         }
63
64         if ((dst = br_fdb_get(br, dest)) != NULL) {
65                 br_deliver(dst->dst, skb);
66                 br_fdb_put(dst);
67                 return 0;
68         }
69
70         br_flood_deliver(br, skb, 0);
71         return 0;
72 }
73
74 int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
75 {
76         int ret;
77
78         rcu_read_lock();
79         ret = __br_dev_xmit(skb, dev);
80         rcu_read_unlock();
81
82         return ret;
83 }
84
85 static int br_dev_open(struct net_device *dev)
86 {
87         netif_start_queue(dev);
88
89         br_stp_enable_bridge(dev->priv);
90
91         return 0;
92 }
93
94 static void br_dev_set_multicast_list(struct net_device *dev)
95 {
96 }
97
98 static int br_dev_stop(struct net_device *dev)
99 {
100         br_stp_disable_bridge(dev->priv);
101
102         netif_stop_queue(dev);
103
104         return 0;
105 }
106
107 static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
108 {
109         return -1;
110 }
111
112 void br_dev_setup(struct net_device *dev)
113 {
114         memset(dev->dev_addr, 0, ETH_ALEN);
115
116         ether_setup(dev);
117
118         dev->do_ioctl = br_dev_do_ioctl;
119         dev->get_stats = br_dev_get_stats;
120         dev->hard_start_xmit = br_dev_xmit;
121         dev->open = br_dev_open;
122         dev->set_multicast_list = br_dev_set_multicast_list;
123         dev->destructor = free_netdev;
124         SET_MODULE_OWNER(dev);
125         dev->stop = br_dev_stop;
126         dev->accept_fastpath = br_dev_accept_fastpath;
127         dev->tx_queue_len = 0;
128         dev->set_mac_address = NULL;
129         dev->priv_flags = IFF_EBRIDGE;
130 }