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) |
