import of upstream 2.4.34.4 from kernel.org
[linux-2.4.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.5.2.1 2001/12/24 00:59:27 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/if_bridge.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(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         struct net_bridge *br;
77         int ret;
78
79         br = dev->priv;
80         read_lock(&br->lock);
81         ret = __br_dev_xmit(skb, dev);
82         read_unlock(&br->lock);
83
84         return ret;
85 }
86
87 static int br_dev_open(struct net_device *dev)
88 {
89         struct net_bridge *br;
90
91         netif_start_queue(dev);
92
93         br = dev->priv;
94         read_lock(&br->lock);
95         br_stp_enable_bridge(br);
96         read_unlock(&br->lock);
97
98         return 0;
99 }
100
101 static void br_dev_set_multicast_list(struct net_device *dev)
102 {
103 }
104
105 static int br_dev_stop(struct net_device *dev)
106 {
107         struct net_bridge *br;
108
109         br = dev->priv;
110         read_lock(&br->lock);
111         br_stp_disable_bridge(br);
112         read_unlock(&br->lock);
113
114         netif_stop_queue(dev);
115
116         return 0;
117 }
118
119 static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
120 {
121         return -1;
122 }
123
124 void br_dev_setup(struct net_device *dev)
125 {
126         memset(dev->dev_addr, 0, ETH_ALEN);
127
128         dev->do_ioctl = br_dev_do_ioctl;
129         dev->get_stats = br_dev_get_stats;
130         dev->hard_start_xmit = br_dev_xmit;
131         dev->open = br_dev_open;
132         dev->set_multicast_list = br_dev_set_multicast_list;
133         dev->stop = br_dev_stop;
134         dev->accept_fastpath = br_dev_accept_fastpath;
135         dev->tx_queue_len = 0;
136         dev->set_mac_address = NULL;
137 }