Skip to contentSkip to conversation

openvswitch: orphan frags on local receive

PATCH In review Qin Chuanyu 3 participants 4 messages Feb 24, 2014 – Feb 25, 2014

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 openvswitch: orphan frags on local receive

with vhost tx zero_copy, guest nic might get hang when host reserving skb in socket queue delivered by guest, the case has been solved in tun, it also been needed by openvswitch. This could easily happened when a LAST_ACK state tcp occuring between guest and host.

---
 net/openvswitch/vport-internal_dev.c |    3 +++
 net/openvswitch/vport.c              |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
net/openvswitch/vport-internal_dev.c +3 -0
index 729c687..adb25e2 100644
@@ -212,6 +212,9 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
 	struct net_device *netdev = netdev_vport_priv(vport)->dev;
 	int len;
 
+	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+		return -NET_RX_DROP;
+
 	len = skb->len;
 
 	skb_dst_drop(skb);
net/openvswitch/vport.c +1 -0
index 208dd9a..04172d6 100644
@@ -383,6 +383,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
 		u64_stats_update_end(&stats->syncp);
 	} else if (sent < 0) {
 		ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
+		skb_tx_error(skb);
 		kfree_skb(skb);
 	} else
 		ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
Signature · 1 line
1.7.3.1.msysgit.0
#1 lore raw
Quoted 6 lines · Qin Chuanyu

with vhost tx zero_copy, guest nic might get hang when host reserving skb in socket queue delivered by guest, the case has been solved in tun, it also been needed by openvswitch. This could easily happened when a LAST_ACK state tcp occuring between guest and host.

Same question as with bridge.

Quoted 36 lines
---
 net/openvswitch/vport-internal_dev.c |    3 +++
 net/openvswitch/vport.c              |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
net/openvswitch/vport-internal_dev.c +3 -0
index 729c687..adb25e2 100644
@@ -212,6 +212,9 @@ static int internal_dev_recv(struct vport
 *vport, struct sk_buff *skb)
 	struct net_device *netdev = netdev_vport_priv(vport)->dev;
 	int len;
 
+	if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+		return -NET_RX_DROP;
+
 	len = skb->len;
 
net/openvswitch/vport-internal_dev.c +0 -0
 	skb_dst_drop(skb);
net/openvswitch/vport.c +1 -0
index 208dd9a..04172d6 100644
@@ -383,6 +383,7 @@ int ovs_vport_send(struct vport *vport, struct
 sk_buff *skb)
 		u64_stats_update_end(&stats->syncp);
 	} else if (sent < 0) {
 		ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
+		skb_tx_error(skb);
 		kfree_skb(skb);
 	} else

ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);

Signature · 1 line
1.7.3.1.msysgit.0
#2 lore raw
In reply to Qin Chuanyu

Hi,

I'm also planning a similar patch, but it will call skb_orphan_frags on the skb in datapath.c::queue_userspace_packet, right before skb_zerocopy, so packets sent up to userspace via Netlink doesn't harm guests. I haven't checked your patch thoroughly, does it handle a different scenario?

Regards,

Zoltan Kiss

Quoted 39 lines · Qin Chuanyu

with vhost tx zero_copy, guest nic might get hang when host reserving skb in socket queue delivered by guest, the case has been solved in tun, it also been needed by openvswitch. This could easily happened when a LAST_ACK state tcp occuring between guest and host.

---
 net/openvswitch/vport-internal_dev.c |    3 +++
 net/openvswitch/vport.c              |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
net/openvswitch/vport-internal_dev.c +3 -0
index 729c687..adb25e2 100644
@@ -212,6 +212,9 @@ static int internal_dev_recv(struct vport *vport, 
 struct sk_buff *skb)
     struct net_device *netdev = netdev_vport_priv(vport)->dev;
     int len;
 
+    if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+        return -NET_RX_DROP;
+
     len = skb->len;
 
     skb_dst_drop(skb);
net/openvswitch/vport.c +1 -0
index 208dd9a..04172d6 100644
@@ -383,6 +383,7 @@ int ovs_vport_send(struct vport *vport, struct 
 sk_buff *skb)
         u64_stats_update_end(&stats->syncp);
     } else if (sent < 0) {
         ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
+        skb_tx_error(skb);
         kfree_skb(skb);
     } else
         ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
#3 lore raw
Quoted 8 lines · Zoltan Kiss

Hi,

I'm also planning a similar patch, but it will call skb_orphan_frags on the skb in datapath.c::queue_userspace_packet, right before skb_zerocopy, so packets sent up to userspace via Netlink doesn't harm guests. I haven't checked your patch thoroughly, does it handle a different scenario?

yes, it handle another scenario, and Michael had noted that __netif_receive_skb_core could solve it.

I think your patch is still needed, because netif_receive_skb didn't handle the netlink receive patch. and any skb reserved by host socket queue might cause guest nic hang.

Quoted 49 lines

Regards,

Zoltan Kiss

Quoted 39 lines · Qin Chuanyu

with vhost tx zero_copy, guest nic might get hang when host reserving skb in socket queue delivered by guest, the case has been solved in tun, it also been needed by openvswitch. This could easily happened when a LAST_ACK state tcp occuring between guest and host.

---
 net/openvswitch/vport-internal_dev.c |    3 +++
 net/openvswitch/vport.c              |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
net/openvswitch/vport-internal_dev.c +3 -0
index 729c687..adb25e2 100644
@@ -212,6 +212,9 @@ static int internal_dev_recv(struct vport *vport,
 struct sk_buff *skb)
     struct net_device *netdev = netdev_vport_priv(vport)->dev;
     int len;
 
+    if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+        return -NET_RX_DROP;
+
     len = skb->len;
 
     skb_dst_drop(skb);
net/openvswitch/vport.c +1 -0
index 208dd9a..04172d6 100644
@@ -383,6 +383,7 @@ int ovs_vport_send(struct vport *vport, struct
 sk_buff *skb)
         u64_stats_update_end(&stats->syncp);
     } else if (sent < 0) {
         ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
+        skb_tx_error(skb);
         kfree_skb(skb);
     } else
Quoted 1 line
         ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);

.