aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2013-01-22 02:57:26 -0500
committerJesse Gross <jesse@nicira.com>2013-01-22 02:57:26 -0500
commitd9d59089c43fc33eb403cbb928e56c131f191dd5 (patch)
tree18c2d4b631048d1bbee5cbf12c84d8034fe1a1e7 /net/openvswitch
parenta49f0d1ea3ec94fc7cf33a7c36a16343b74bd565 (diff)
openvswitch: Move LRO check from transmit to receive.
The check for LRO packets was incorrectly put in the transmit path instead of on receive. 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. Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/vport-netdev.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index a9327e2e48ce..670cbc3518de 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -35,10 +35,11 @@
35/* Must be called with rcu_read_lock. */ 35/* Must be called with rcu_read_lock. */
36static void netdev_port_receive(struct vport *vport, struct sk_buff *skb) 36static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
37{ 37{
38 if (unlikely(!vport)) { 38 if (unlikely(!vport))
39 kfree_skb(skb); 39 goto error;
40 return; 40
41 } 41 if (unlikely(skb_warn_if_lro(skb)))
42 goto error;
42 43
43 /* Make our own copy of the packet. Otherwise we will mangle the 44 /* Make our own copy of the packet. Otherwise we will mangle the
44 * packet for anyone who came before us (e.g. tcpdump via AF_PACKET). 45 * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
@@ -50,6 +51,10 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
50 51
51 skb_push(skb, ETH_HLEN); 52 skb_push(skb, ETH_HLEN);
52 ovs_vport_receive(vport, skb); 53 ovs_vport_receive(vport, skb);
54 return;
55
56error:
57 kfree_skb(skb);
53} 58}
54 59
55/* Called with rcu_read_lock and bottom-halves disabled. */ 60/* Called with rcu_read_lock and bottom-halves disabled. */
@@ -169,9 +174,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
169 goto error; 174 goto error;
170 } 175 }
171 176
172 if (unlikely(skb_warn_if_lro(skb)))
173 goto error;
174
175 skb->dev = netdev_vport->dev; 177 skb->dev = netdev_vport->dev;
176 len = skb->len; 178 len = skb->len;
177 dev_queue_xmit(skb); 179 dev_queue_xmit(skb);