return &br->statistics;
}
-int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_bridge *br = netdev_priv(dev);
- const unsigned char *dest = skb->data;
+ struct net_bridge *br;
+ unsigned char *dest;
struct net_bridge_fdb_entry *dst;
+ br = dev->priv;
br->statistics.tx_packets++;
br->statistics.tx_bytes += skb->len;
- skb->mac.raw = skb->data;
+ dest = skb->mac.raw = skb->data;
skb_pull(skb, ETH_HLEN);
- rcu_read_lock();
- if (dest[0] & 1)
+ if (dest[0] & 1) {
br_flood_deliver(br, skb, 0);
- else if ((dst = __br_fdb_get(br, dest)) != NULL)
+ return 0;
+ }
+
+ if ((dst = br_fdb_get(br, dest)) != NULL) {
br_deliver(dst->dst, skb);
- else
- br_flood_deliver(br, skb, 0);
+ br_fdb_put(dst);
+ return 0;
+ }
- rcu_read_unlock();
+ br_flood_deliver(br, skb, 0);
return 0;
}
+int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int ret;
+
+ rcu_read_lock();
+ ret = __br_dev_xmit(skb, dev);
+ rcu_read_unlock();
+
+ return ret;
+}
+
static int br_dev_open(struct net_device *dev)
{
netif_start_queue(dev);