From f1ef8ee858288e06957130067abfbfa57580029e Mon Sep 17 00:00:00 2001
From: Justin Pettit <jpettit@nicira.com>
Date: Fri, 26 Aug 2011 23:32:20 -0700
Subject: [PATCH] datapath: Move LRO checks to netdev_send().

---
 datapath/vport-netdev.c |   25 +++++++++++++++++++++++--
 datapath/vport.c        |   30 +-----------------------------
 2 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index 972ea0a..eae4f52 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -6,6 +6,8 @@
  * kernel, by Linus Torvalds and others.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/if_arp.h>
 #include <linux/if_bridge.h>
 #include <linux/if_vlan.h>
@@ -283,8 +285,6 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 	if (unlikely(!skb))
 		return;
 
-	skb_warn_if_lro(skb);
-
 	skb_push(skb, ETH_HLEN);
 
 	if (unlikely(compute_ip_summed(skb, false))) {
@@ -296,6 +296,16 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 	vport_receive(vport, skb);
 }
 
+static inline unsigned packet_length(const struct sk_buff *skb)
+{
+	unsigned length = skb->len - ETH_HLEN;
+
+	if (skb->protocol == htons(ETH_P_8021Q))
+		length -= VLAN_HLEN;
+
+	return length;
+}
+
 static bool dev_supports_vlan_tx(struct net_device *dev)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
@@ -312,8 +322,19 @@ static bool dev_supports_vlan_tx(struct net_device *dev)
 static int netdev_send(struct vport *vport, struct sk_buff *skb)
 {
 	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+	int mtu = netdev_vport->dev->mtu;
 	int len;
 
+	if (mtu && unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+		if (net_ratelimit())
+			pr_warn("%s: dropped over-mtu packet: %d > %d\n",
+				dp_name(vport->dp), packet_length(skb), mtu);
+	    kfree_skb(skb);
+	    vport_record_error(vport, VPORT_E_TX_DROPPED);
+		return 0;
+	}
+	skb_warn_if_lro(skb);
+
 	skb->dev = netdev_vport->dev;
 	forward_ip_summed(skb, true);
 
diff --git a/datapath/vport.c b/datapath/vport.c
index 487d752..2b5a0b4 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -6,8 +6,6 @@
  * kernel, by Linus Torvalds and others.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/dcache.h>
 #include <linux/etherdevice.h>
 #include <linux/if.h>
@@ -687,16 +685,6 @@ void vport_receive(struct vport *vport, struct sk_buff *skb)
 	dp_process_received_packet(vport, skb);
 }
 
-static inline unsigned packet_length(const struct sk_buff *skb)
-{
-	unsigned length = skb->len - ETH_HLEN;
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		length -= VLAN_HLEN;
-
-	return length;
-}
-
 /**
  *	vport_send - send a packet on a device
  *
@@ -708,18 +696,7 @@ static inline unsigned packet_length(const struct sk_buff *skb)
  */
 int vport_send(struct vport *vport, struct sk_buff *skb)
 {
-	int mtu;
-	int sent;
-
-	mtu = vport_get_mtu(vport);
-	if (mtu && unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
-		if (net_ratelimit())
-			pr_warn("%s: dropped over-mtu packet: %d > %d\n",
-				dp_name(vport->dp), packet_length(skb), mtu);
-		goto error;
-	}
-
-	sent = vport->ops->send(vport, skb);
+	int sent = vport->ops->send(vport, skb);
 
 	if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
 		struct vport_percpu_stats *stats;
@@ -736,11 +713,6 @@ int vport_send(struct vport *vport, struct sk_buff *skb)
 	}
 
 	return sent;
-
-error:
-	kfree_skb(skb);
-	vport_record_error(vport, VPORT_E_TX_DROPPED);
-	return 0;
 }
 
 /**
-- 
1.7.1

