diff options
Diffstat (limited to 'net/bridge/br_forward.c')
-rw-r--r-- | net/bridge/br_forward.c | 51 |
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 | ||
60 | int br_forward_finish(struct sk_buff *skb) | 67 | int 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 | ||
67 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | 74 | static 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 | ||
74 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 95 | 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) | |||
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) |