linux/net/bridge/br_device.c
<<
>>
Prefs
   1/*
   2 *      Device handling code
   3 *      Linux ethernet bridge
   4 *
   5 *      Authors:
   6 *      Lennert Buytenhek               <buytenh@gnu.org>
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/netdevice.h>
  16#include <linux/etherdevice.h>
  17#include <linux/ethtool.h>
  18
  19#include <asm/uaccess.h>
  20#include "br_private.h"
  21
  22/* net device transmit always called with no BH (preempt_disabled) */
  23int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
  24{
  25        struct net_bridge *br = netdev_priv(dev);
  26        const unsigned char *dest = skb->data;
  27        struct net_bridge_fdb_entry *dst;
  28
  29        dev->stats.tx_packets++;
  30        dev->stats.tx_bytes += skb->len;
  31
  32        skb_reset_mac_header(skb);
  33        skb_pull(skb, ETH_HLEN);
  34
  35        if (dest[0] & 1)
  36                br_flood_deliver(br, skb);
  37        else if ((dst = __br_fdb_get(br, dest)) != NULL)
  38                br_deliver(dst->dst, skb);
  39        else
  40                br_flood_deliver(br, skb);
  41
  42        return 0;
  43}
  44
  45static int br_dev_open(struct net_device *dev)
  46{
  47        struct net_bridge *br = netdev_priv(dev);
  48
  49        br_features_recompute(br);
  50        netif_start_queue(dev);
  51        br_stp_enable_bridge(br);
  52
  53        return 0;
  54}
  55
  56static void br_dev_set_multicast_list(struct net_device *dev)
  57{
  58}
  59
  60static int br_dev_stop(struct net_device *dev)
  61{
  62        br_stp_disable_bridge(netdev_priv(dev));
  63
  64        netif_stop_queue(dev);
  65
  66        return 0;
  67}
  68
  69static int br_change_mtu(struct net_device *dev, int new_mtu)
  70{
  71        struct net_bridge *br = netdev_priv(dev);
  72        if (new_mtu < 68 || new_mtu > br_min_mtu(br))
  73                return -EINVAL;
  74
  75        dev->mtu = new_mtu;
  76
  77#ifdef CONFIG_BRIDGE_NETFILTER
  78        /* remember the MTU in the rtable for PMTU */
  79        br->fake_rtable.u.dst.metrics[RTAX_MTU - 1] = new_mtu;
  80#endif
  81
  82        return 0;
  83}
  84
  85/* Allow setting mac address to any valid ethernet address. */
  86static int br_set_mac_address(struct net_device *dev, void *p)
  87{
  88        struct net_bridge *br = netdev_priv(dev);
  89        struct sockaddr *addr = p;
  90
  91        if (!is_valid_ether_addr(addr->sa_data))
  92                return -EINVAL;
  93
  94        spin_lock_bh(&br->lock);
  95        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
  96        br_stp_change_bridge_id(br, addr->sa_data);
  97        br->flags |= BR_SET_MAC_ADDR;
  98        spin_unlock_bh(&br->lock);
  99
 100        return 0;
 101}
 102
 103static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 104{
 105        strcpy(info->driver, "bridge");
 106        strcpy(info->version, BR_VERSION);
 107        strcpy(info->fw_version, "N/A");
 108        strcpy(info->bus_info, "N/A");
 109}
 110
 111static int br_set_sg(struct net_device *dev, u32 data)
 112{
 113        struct net_bridge *br = netdev_priv(dev);
 114
 115        if (data)
 116                br->feature_mask |= NETIF_F_SG;
 117        else
 118                br->feature_mask &= ~NETIF_F_SG;
 119
 120        br_features_recompute(br);
 121        return 0;
 122}
 123
 124static int br_set_tso(struct net_device *dev, u32 data)
 125{
 126        struct net_bridge *br = netdev_priv(dev);
 127
 128        if (data)
 129                br->feature_mask |= NETIF_F_TSO;
 130        else
 131                br->feature_mask &= ~NETIF_F_TSO;
 132
 133        br_features_recompute(br);
 134        return 0;
 135}
 136
 137static int br_set_tx_csum(struct net_device *dev, u32 data)
 138{
 139        struct net_bridge *br = netdev_priv(dev);
 140
 141        if (data)
 142                br->feature_mask |= NETIF_F_NO_CSUM;
 143        else
 144                br->feature_mask &= ~NETIF_F_ALL_CSUM;
 145
 146        br_features_recompute(br);
 147        return 0;
 148}
 149
 150static const struct ethtool_ops br_ethtool_ops = {
 151        .get_drvinfo    = br_getinfo,
 152        .get_link       = ethtool_op_get_link,
 153        .get_tx_csum    = ethtool_op_get_tx_csum,
 154        .set_tx_csum    = br_set_tx_csum,
 155        .get_sg         = ethtool_op_get_sg,
 156        .set_sg         = br_set_sg,
 157        .get_tso        = ethtool_op_get_tso,
 158        .set_tso        = br_set_tso,
 159        .get_ufo        = ethtool_op_get_ufo,
 160        .get_flags      = ethtool_op_get_flags,
 161};
 162
 163static const struct net_device_ops br_netdev_ops = {
 164        .ndo_open                = br_dev_open,
 165        .ndo_stop                = br_dev_stop,
 166        .ndo_start_xmit          = br_dev_xmit,
 167        .ndo_set_mac_address     = br_set_mac_address,
 168        .ndo_set_multicast_list  = br_dev_set_multicast_list,
 169        .ndo_change_mtu          = br_change_mtu,
 170        .ndo_do_ioctl            = br_dev_ioctl,
 171};
 172
 173void br_dev_setup(struct net_device *dev)
 174{
 175        random_ether_addr(dev->dev_addr);
 176        ether_setup(dev);
 177
 178        dev->netdev_ops = &br_netdev_ops;
 179        dev->destructor = free_netdev;
 180        SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
 181        dev->tx_queue_len = 0;
 182        dev->priv_flags = IFF_EBRIDGE;
 183
 184        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
 185                        NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
 186                        NETIF_F_NETNS_LOCAL | NETIF_F_GSO;
 187}
 188