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.1.1.1 2008/10/15 03:27:33 james26_jang 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 22static 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 37static 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 46static 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 74int 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 87static 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 101static void br_dev_set_multicast_list(struct net_device *dev) 102{ 103} 104 105static 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 119static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst) 120{ 121 return -1; 122} 123 124extern void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr); 125 126static int 127br_set_mac_address(struct net_device *dev, void *addr) 128{ 129 struct net_bridge *br = dev->priv; 130 struct sockaddr *sa = (struct sockaddr *) addr; 131 132 write_lock_bh(&br->lock); 133 134 memcpy(br->preferred_id.addr, sa->sa_data, ETH_ALEN); 135 136 br_stp_recalculate_bridge_id(br); 137 138 write_unlock_bh(&br->lock); 139 140 return 0; 141} 142 143void br_dev_setup(struct net_device *dev) 144{ 145 memset(dev->dev_addr, 0, ETH_ALEN); 146 147 dev->do_ioctl = br_dev_do_ioctl; 148 dev->get_stats = br_dev_get_stats; 149 dev->hard_start_xmit = br_dev_xmit; 150 dev->open = br_dev_open; 151 dev->set_multicast_list = br_dev_set_multicast_list; 152 dev->stop = br_dev_stop; 153 dev->accept_fastpath = br_dev_accept_fastpath; 154 dev->tx_queue_len = 0; 155 dev->set_mac_address = br_set_mac_address; 156} 157