Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20-rc4 189 lines 4.3 kB view raw
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/etherdevice.h> 19#include <linux/ethtool.h> 20 21#include <asm/uaccess.h> 22#include "br_private.h" 23 24static struct net_device_stats *br_dev_get_stats(struct net_device *dev) 25{ 26 struct net_bridge *br = netdev_priv(dev); 27 return &br->statistics; 28} 29 30/* net device transmit always called with no BH (preempt_disabled) */ 31int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) 32{ 33 struct net_bridge *br = netdev_priv(dev); 34 const unsigned char *dest = skb->data; 35 struct net_bridge_fdb_entry *dst; 36 37 br->statistics.tx_packets++; 38 br->statistics.tx_bytes += skb->len; 39 40 skb->mac.raw = skb->data; 41 skb_pull(skb, ETH_HLEN); 42 43 if (dest[0] & 1) 44 br_flood_deliver(br, skb, 0); 45 else if ((dst = __br_fdb_get(br, dest)) != NULL) 46 br_deliver(dst->dst, skb); 47 else 48 br_flood_deliver(br, skb, 0); 49 50 return 0; 51} 52 53static int br_dev_open(struct net_device *dev) 54{ 55 struct net_bridge *br = netdev_priv(dev); 56 57 br_features_recompute(br); 58 netif_start_queue(dev); 59 br_stp_enable_bridge(br); 60 61 return 0; 62} 63 64static void br_dev_set_multicast_list(struct net_device *dev) 65{ 66} 67 68static int br_dev_stop(struct net_device *dev) 69{ 70 br_stp_disable_bridge(netdev_priv(dev)); 71 72 netif_stop_queue(dev); 73 74 return 0; 75} 76 77static int br_change_mtu(struct net_device *dev, int new_mtu) 78{ 79 if (new_mtu < 68 || new_mtu > br_min_mtu(netdev_priv(dev))) 80 return -EINVAL; 81 82 dev->mtu = new_mtu; 83 return 0; 84} 85 86/* Allow setting mac address of pseudo-bridge to be same as 87 * any of the bound interfaces 88 */ 89static int br_set_mac_address(struct net_device *dev, void *p) 90{ 91 struct net_bridge *br = netdev_priv(dev); 92 struct sockaddr *addr = p; 93 struct net_bridge_port *port; 94 int err = -EADDRNOTAVAIL; 95 96 spin_lock_bh(&br->lock); 97 list_for_each_entry(port, &br->port_list, list) { 98 if (!compare_ether_addr(port->dev->dev_addr, addr->sa_data)) { 99 br_stp_change_bridge_id(br, addr->sa_data); 100 err = 0; 101 break; 102 } 103 } 104 spin_unlock_bh(&br->lock); 105 106 return err; 107} 108 109static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) 110{ 111 strcpy(info->driver, "bridge"); 112 strcpy(info->version, BR_VERSION); 113 strcpy(info->fw_version, "N/A"); 114 strcpy(info->bus_info, "N/A"); 115} 116 117static int br_set_sg(struct net_device *dev, u32 data) 118{ 119 struct net_bridge *br = netdev_priv(dev); 120 121 if (data) 122 br->feature_mask |= NETIF_F_SG; 123 else 124 br->feature_mask &= ~NETIF_F_SG; 125 126 br_features_recompute(br); 127 return 0; 128} 129 130static int br_set_tso(struct net_device *dev, u32 data) 131{ 132 struct net_bridge *br = netdev_priv(dev); 133 134 if (data) 135 br->feature_mask |= NETIF_F_TSO; 136 else 137 br->feature_mask &= ~NETIF_F_TSO; 138 139 br_features_recompute(br); 140 return 0; 141} 142 143static int br_set_tx_csum(struct net_device *dev, u32 data) 144{ 145 struct net_bridge *br = netdev_priv(dev); 146 147 if (data) 148 br->feature_mask |= NETIF_F_NO_CSUM; 149 else 150 br->feature_mask &= ~NETIF_F_ALL_CSUM; 151 152 br_features_recompute(br); 153 return 0; 154} 155 156static struct ethtool_ops br_ethtool_ops = { 157 .get_drvinfo = br_getinfo, 158 .get_link = ethtool_op_get_link, 159 .get_sg = ethtool_op_get_sg, 160 .set_sg = br_set_sg, 161 .get_tx_csum = ethtool_op_get_tx_csum, 162 .set_tx_csum = br_set_tx_csum, 163 .get_tso = ethtool_op_get_tso, 164 .set_tso = br_set_tso, 165}; 166 167void br_dev_setup(struct net_device *dev) 168{ 169 memset(dev->dev_addr, 0, ETH_ALEN); 170 171 ether_setup(dev); 172 173 dev->do_ioctl = br_dev_ioctl; 174 dev->get_stats = br_dev_get_stats; 175 dev->hard_start_xmit = br_dev_xmit; 176 dev->open = br_dev_open; 177 dev->set_multicast_list = br_dev_set_multicast_list; 178 dev->change_mtu = br_change_mtu; 179 dev->destructor = free_netdev; 180 SET_MODULE_OWNER(dev); 181 SET_ETHTOOL_OPS(dev, &br_ethtool_ops); 182 dev->stop = br_dev_stop; 183 dev->tx_queue_len = 0; 184 dev->set_mac_address = br_set_mac_address; 185 dev->priv_flags = IFF_EBRIDGE; 186 187 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 188 NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; 189}