aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_forward.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_forward.c')
-rw-r--r--net/bridge/br_forward.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7a241c396981..a98ef1393097 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/netpoll.h>
18#include <linux/skbuff.h> 19#include <linux/skbuff.h>
19#include <linux/if_vlan.h> 20#include <linux/if_vlan.h>
20#include <linux/netfilter_bridge.h> 21#include <linux/netfilter_bridge.h>
@@ -44,13 +45,19 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
44 if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) 45 if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
45 kfree_skb(skb); 46 kfree_skb(skb);
46 else { 47 else {
47 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ 48 /* ip_fragment doesn't copy the MAC header */
48 if (nf_bridge_maybe_copy_header(skb)) 49 if (nf_bridge_maybe_copy_header(skb))
49 kfree_skb(skb); 50 kfree_skb(skb);
50 else { 51 else {
51 skb_push(skb, ETH_HLEN); 52 skb_push(skb, ETH_HLEN);
52 53
53 dev_queue_xmit(skb); 54#ifdef CONFIG_NET_POLL_CONTROLLER
55 if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) {
56 netpoll_send_skb(skb->dev->npinfo->netpoll, skb);
57 skb->dev->priv_flags &= ~IFF_IN_NETPOLL;
58 } else
59#endif
60 dev_queue_xmit(skb);
54 } 61 }
55 } 62 }
56 63
@@ -59,16 +66,30 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
59 66
60int br_forward_finish(struct sk_buff *skb) 67int br_forward_finish(struct sk_buff *skb)
61{ 68{
62 return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, 69 return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
63 br_dev_queue_push_xmit); 70 br_dev_queue_push_xmit);
64 71
65} 72}
66 73
67static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) 74static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
68{ 75{
76#ifdef CONFIG_NET_POLL_CONTROLLER
77 struct net_bridge *br = to->br;
78 if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) {
79 struct netpoll *np;
80 to->dev->npinfo = skb->dev->npinfo;
81 np = skb->dev->npinfo->netpoll;
82 np->real_dev = np->dev = to->dev;
83 to->dev->priv_flags |= IFF_IN_NETPOLL;
84 }
85#endif
69 skb->dev = to->dev; 86 skb->dev = to->dev;
70 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 87 NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
71 br_forward_finish); 88 br_forward_finish);
89#ifdef CONFIG_NET_POLL_CONTROLLER
90 if (skb->dev->npinfo)
91 skb->dev->npinfo->netpoll->dev = br->dev;
92#endif
72} 93}
73 94
74static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) 95static 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)
84 skb->dev = to->dev; 105 skb->dev = to->dev;
85 skb_forward_csum(skb); 106 skb_forward_csum(skb);
86 107
87 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, 108 NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
88 br_forward_finish); 109 br_forward_finish);
89} 110}
90 111
91/* called with rcu_read_lock */ 112/* called with rcu_read_lock */
@@ -208,17 +229,15 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
208{ 229{
209 struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; 230 struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
210 struct net_bridge *br = netdev_priv(dev); 231 struct net_bridge *br = netdev_priv(dev);
211 struct net_bridge_port *port; 232 struct net_bridge_port *prev = NULL;
212 struct net_bridge_port *lport, *rport;
213 struct net_bridge_port *prev;
214 struct net_bridge_port_group *p; 233 struct net_bridge_port_group *p;
215 struct hlist_node *rp; 234 struct hlist_node *rp;
216 235
217 prev = NULL; 236 rp = rcu_dereference(br->router_list.first);
218 237 p = mdst ? rcu_dereference(mdst->ports) : NULL;
219 rp = br->router_list.first;
220 p = mdst ? mdst->ports : NULL;
221 while (p || rp) { 238 while (p || rp) {
239 struct net_bridge_port *port, *lport, *rport;
240
222 lport = p ? p->port : NULL; 241 lport = p ? p->port : NULL;
223 rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : 242 rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
224 NULL; 243 NULL;
@@ -231,9 +250,9 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
231 goto out; 250 goto out;
232 251
233 if ((unsigned long)lport >= (unsigned long)port) 252 if ((unsigned long)lport >= (unsigned long)port)
234 p = p->next; 253 p = rcu_dereference(p->next);
235 if ((unsigned long)rport >= (unsigned long)port) 254 if ((unsigned long)rport >= (unsigned long)port)
236 rp = rp->next; 255 rp = rcu_dereference(rp->next);
237 } 256 }
238 257
239 if (!prev) 258 if (!prev)