bridge: Use rcu_barrier() instead of syncronize_net() on unload.
[safe/jmp/linux-2.6] / net / bridge / br_forward.c
index 6ccd32b..d2c27c8 100644 (file)
@@ -5,8 +5,6 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br_forward.c,v 1.4 2001/08/14 22:05:57 davem Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     as published by the Free Software Foundation; either version
@@ -21,7 +19,7 @@
 #include "br_private.h"
 
 /* Don't forward packets to originating port or forwarding diasabled */
-static inline int should_deliver(const struct net_bridge_port *p, 
+static inline int should_deliver(const struct net_bridge_port *p,
                                 const struct sk_buff *skb)
 {
        return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
@@ -38,13 +36,14 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
        if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
                kfree_skb(skb);
        else {
-#ifdef CONFIG_BRIDGE_NETFILTER
                /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
-               nf_bridge_maybe_copy_header(skb);
-#endif
-               skb_push(skb, ETH_HLEN);
+               if (nf_bridge_maybe_copy_header(skb))
+                       kfree_skb(skb);
+               else {
+                       skb_push(skb, ETH_HLEN);
 
-               dev_queue_xmit(skb);
+                       dev_queue_xmit(skb);
+               }
        }
 
        return 0;
@@ -68,9 +67,14 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
 {
        struct net_device *indev;
 
+       if (skb_warn_if_lro(skb)) {
+               kfree_skb(skb);
+               return;
+       }
+
        indev = skb->dev;
        skb->dev = to->dev;
-       skb->ip_summed = CHECKSUM_NONE;
+       skb_forward_csum(skb);
 
        NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
                        br_forward_finish);
@@ -99,24 +103,13 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
 }
 
 /* called under bridge lock */
-static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
-       void (*__packet_hook)(const struct net_bridge_port *p, 
+static void br_flood(struct net_bridge *br, struct sk_buff *skb,
+       void (*__packet_hook)(const struct net_bridge_port *p,
                              struct sk_buff *skb))
 {
        struct net_bridge_port *p;
        struct net_bridge_port *prev;
 
-       if (clone) {
-               struct sk_buff *skb2;
-
-               if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-                       br->statistics.tx_dropped++;
-                       return;
-               }
-
-               skb = skb2;
-       }
-
        prev = NULL;
 
        list_for_each_entry_rcu(p, &br->port_list, list) {
@@ -125,7 +118,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
                                struct sk_buff *skb2;
 
                                if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-                                       br->statistics.tx_dropped++;
+                                       br->dev->stats.tx_dropped++;
                                        kfree_skb(skb);
                                        return;
                                }
@@ -147,13 +140,13 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
 
 
 /* called with rcu_read_lock */
-void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, int clone)
+void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
 {
-       br_flood(br, skb, clone, __br_deliver);
+       br_flood(br, skb, __br_deliver);
 }
 
 /* called under bridge lock */
-void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone)
+void br_flood_forward(struct net_bridge *br, struct sk_buff *skb)
 {
-       br_flood(br, skb, clone, __br_forward);
+       br_flood(br, skb, __br_forward);
 }