This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / net / bridge / br_device.c
index 44a9762..e91f80f 100644 (file)
@@ -28,30 +28,45 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
        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);