]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/bridge/br_forward.c
Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd
[mv-sheeva.git] / net / bridge / br_forward.c
index 396f077216a3ba95786268163f3fd087f7501a9d..a98ef13930979a129a8d0195e5a94dee3ec7bd2a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/netpoll.h>
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
 #include <linux/netfilter_bridge.h>
@@ -44,13 +45,19 @@ 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 {
-               /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
+               /* ip_fragment doesn't copy the MAC header */
                if (nf_bridge_maybe_copy_header(skb))
                        kfree_skb(skb);
                else {
                        skb_push(skb, ETH_HLEN);
 
-                       dev_queue_xmit(skb);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+                       if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) {
+                               netpoll_send_skb(skb->dev->npinfo->netpoll, skb);
+                               skb->dev->priv_flags &= ~IFF_IN_NETPOLL;
+                       } else
+#endif
+                               dev_queue_xmit(skb);
                }
        }
 
@@ -59,16 +66,30 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
 
 int br_forward_finish(struct sk_buff *skb)
 {
-       return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
+       return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
                       br_dev_queue_push_xmit);
 
 }
 
 static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 {
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       struct net_bridge *br = to->br;
+       if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) {
+               struct netpoll *np;
+               to->dev->npinfo = skb->dev->npinfo;
+               np = skb->dev->npinfo->netpoll;
+               np->real_dev = np->dev = to->dev;
+               to->dev->priv_flags |= IFF_IN_NETPOLL;
+       }
+#endif
        skb->dev = to->dev;
-       NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
-                       br_forward_finish);
+       NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
+               br_forward_finish);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       if (skb->dev->npinfo)
+               skb->dev->npinfo->netpoll->dev = br->dev;
+#endif
 }
 
 static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
@@ -84,8 +105,8 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
        skb->dev = to->dev;
        skb_forward_csum(skb);
 
-       NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
-                       br_forward_finish);
+       NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
+               br_forward_finish);
 }
 
 /* called with rcu_read_lock */