diff options
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r-- | net/bridge/br_device.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 074c59690fc..eedf2c94820 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -17,6 +17,7 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/list.h> +#include <linux/netfilter_bridge.h> #include <asm/uaccess.h> #include "br_private.h" @@ -30,6 +31,13 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct net_bridge_mdb_entry *mdst; struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); +#ifdef CONFIG_BRIDGE_NETFILTER + if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { + br_nf_pre_routing_finish_bridge_slow(skb); + return NETDEV_TX_OK; + } +#endif + brstats->tx_packets++; brstats->tx_bytes += skb->len; @@ -191,7 +199,7 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) } #ifdef CONFIG_NET_POLL_CONTROLLER -bool br_devices_support_netpoll(struct net_bridge *br) +static bool br_devices_support_netpoll(struct net_bridge *br) { struct net_bridge_port *p; bool ret = true; @@ -217,9 +225,9 @@ static void br_poll_controller(struct net_device *br_dev) netpoll_poll_dev(np->real_dev); } -void br_netpoll_cleanup(struct net_device *br_dev) +void br_netpoll_cleanup(struct net_device *dev) { - struct net_bridge *br = netdev_priv(br_dev); + struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p, *n; const struct net_device_ops *ops; @@ -235,10 +243,29 @@ void br_netpoll_cleanup(struct net_device *br_dev) } } -#else +void br_netpoll_disable(struct net_bridge *br, + struct net_device *dev) +{ + if (br_devices_support_netpoll(br)) + br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + if (dev->netdev_ops->ndo_netpoll_cleanup) + dev->netdev_ops->ndo_netpoll_cleanup(dev); + else + dev->npinfo = NULL; +} -void br_netpoll_cleanup(struct net_device *br_dev) +void br_netpoll_enable(struct net_bridge *br, + struct net_device *dev) { + if (br_devices_support_netpoll(br)) { + br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + if (br->dev->npinfo) + dev->npinfo = br->dev->npinfo; + } else if (!(br->dev->priv_flags & IFF_DISABLE_NETPOLL)) { + br->dev->priv_flags |= IFF_DISABLE_NETPOLL; + br_info(br,"new device %s does not support netpoll (disabling)", + dev->name); + } } #endif |