summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2013-01-21 05:13:32 -0800
committerJesse Gross <jesse@nicira.com>2013-01-21 17:26:36 -0800
commitb06214ae37785a76af1002c797d1b52a5db74d6f (patch)
treed90d682ee3942e8d7e71812f5a024079a6a4cd65
parentd9cfc29cabf0cdfaa2c0e1db4ccff56d3c1a1ad1 (diff)
downloadopenvswitch-b06214ae37785a76af1002c797d1b52a5db74d6f.tar.gz
datapath: Move LRO check from transmit to receive.
Commit 24b019f808211a95078efd916064af0975ca5733 (datapath: Disable LRO from userspace instead of the kernel.) accidentally moved the check for LRO packets from the receive path to transmit. Since this check is supposed to protect OVS (and other parts of the system) from packets that it cannot handle it is obviously not useful on egress. Therefore, this commit moves it back to the receive side. The primary problem that this caused is upcalls to userspace tried to segment the packet even though no segmentation information is available. This would later cause NULL pointer dereferences when skb_gso_segment() did nothing. Bug #14772 Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
-rw-r--r--datapath/vport-netdev.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c
index e24e5883b..3b59c88a3 100644
--- a/datapath/vport-netdev.c
+++ b/datapath/vport-netdev.c
@@ -249,10 +249,11 @@ int ovs_netdev_get_mtu(const struct vport *vport)
/* Must be called with rcu_read_lock. */
static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
{
- if (unlikely(!vport)) {
- kfree_skb(skb);
- return;
- }
+ if (unlikely(!vport))
+ goto error;
+
+ if (unlikely(skb_warn_if_lro(skb)))
+ goto error;
/* 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).
@@ -264,13 +265,16 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
skb_push(skb, ETH_HLEN);
- if (unlikely(compute_ip_summed(skb, false))) {
- kfree_skb(skb);
- return;
- }
+ if (unlikely(compute_ip_summed(skb, false)))
+ goto error;
+
vlan_copy_skb_tci(skb);
ovs_vport_receive(vport, skb);
+ return;
+
+error:
+ kfree_skb(skb);
}
static unsigned packet_length(const struct sk_buff *skb)
@@ -309,9 +313,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
goto error;
}
- if (unlikely(skb_warn_if_lro(skb)))
- goto error;
-
skb->dev = netdev_vport->dev;
forward_ip_summed(skb, true);