* in dp_frame_hook(). In turn dp_frame_hook() can reject them
* back to network stack, but that's a waste of time. */
}
+ dev_disable_lro(dev);
rcu_assign_pointer(dp->ports[port_no], p);
list_add_rcu(&p->node, &dp->port_list);
dp->n_ports++;
static void
do_port_input(struct net_bridge_port *p, struct sk_buff *skb)
{
+ /* LRO isn't suitable for bridging. We turn it off but make sure
+ * that it wasn't reactivated. */
+ if (skb_warn_if_lro(skb))
+ return;
+
/* Make our own copy of the packet. Otherwise we will mangle the
* packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
* (No one comes after us, since we tell handle_bridge() that we took
openvswitch_sources += \
+ linux-2.6/compat-2.6/dev-openvswitch.c \
linux-2.6/compat-2.6/genetlink-openvswitch.c \
- linux-2.6/compat-2.6/random32.c
+ linux-2.6/compat-2.6/random32.c \
+ linux-2.6/compat-2.6/skbuff-openvswitch.c
openvswitch_headers += \
linux-2.6/compat-2.6/compat26.h \
linux-2.6/compat-2.6/include/asm-generic/bug.h \
--- /dev/null
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+
+#include <linux/netdevice.h>
+
+#ifndef NETIF_F_LRO
+void dev_disable_lro(struct net_device *dev) { }
+#else
+
+#include <linux/ethtool.h>
+
+/**
+ * dev_disable_lro - disable Large Receive Offload on a device
+ * @dev: device
+ *
+ * Disable Large Receive Offload (LRO) on a net device. Must be
+ * called under RTNL. This is needed if received packets may be
+ * forwarded to another interface.
+ */
+void dev_disable_lro(struct net_device *dev)
+{
+ if (dev->ethtool_ops && dev->ethtool_ops->get_flags &&
+ dev->ethtool_ops->set_flags) {
+ u32 flags = dev->ethtool_ops->get_flags(dev);
+ if (flags & ETH_FLAG_LRO) {
+ flags &= ~ETH_FLAG_LRO;
+ dev->ethtool_ops->set_flags(dev, flags);
+ }
+ }
+ WARN_ON(dev->features & NETIF_F_LRO);
+}
+
+#endif /* NETIF_F_LRO */
+
+#endif /* kernel < 2.6.27 */
extern void unregister_netdevice_many(struct list_head *head);
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+extern void dev_disable_lro(struct net_device *dev);
+#endif
+
#endif
}
#endif /* before 2.6.18 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+
+extern void __skb_warn_lro_forwarding(const struct sk_buff *skb);
+
+#ifndef NETIF_F_LRO
+static inline bool skb_warn_if_lro(const struct sk_buff *skb)
+{
+ return false;
+}
+#else
+static inline bool skb_warn_if_lro(const struct sk_buff *skb)
+{
+ /* LRO sets gso_size but not gso_type, whereas if GSO is really
+ * wanted then gso_type will be set. */
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+ if (shinfo->gso_size != 0 && unlikely(shinfo->gso_type == 0)) {
+ __skb_warn_lro_forwarding(skb);
+ return true;
+ }
+ return false;
+}
+#endif /* NETIF_F_LRO */
+#endif /* kernel < 2.6.27 */
+
#endif
--- /dev/null
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+
+#include <linux/netdevice.h>
+
+void __skb_warn_lro_forwarding(const struct sk_buff *skb)
+{
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: received packets cannot be forwarded"
+ " while LRO is enabled\n", skb->dev->name);
+}
+
+#endif /* kernel < 2.6.27 */