diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 7ffa43b..cfe5d6e 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -547,12 +547,20 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	unsigned int offset = offset_in_page(data);
 	unsigned int len = skb_headlen(skb);
 	unsigned long flags;
+        unsigned int l4_hdr = 0;
 
 	slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
 		xennet_count_skb_frag_slots(skb);
 	if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+                l4_hdr = ip_hdr(skb)->protocol;
 		net_alert_ratelimited(
-			"xennet: skb rides the rocket: %d slots\n", slots);
+                 "xennet:  xennet_start_xmit: %d slots MAX_SKB_FRAGS: %d div_roundup:%d xennet_count_skb_frag_slots:%d offset:%d skb_headlen:%d skb->len:%d, skb->data_len:%d skb->truesize:%d nr_frags:%d page_size:%d prot:%04x gso:%d linearize:%d dev:%s transp:%04x \n",
+                 slots, MAX_SKB_FRAGS,DIV_ROUND_UP(offset + len, PAGE_SIZE),
+                 xennet_count_skb_frag_slots(skb), offset, len, skb->len,
+                 skb->data_len, skb->truesize, skb_shinfo(skb)->nr_frags,
+                 PAGE_SIZE, ntohs(skb->protocol), skb_is_gso(skb), skb_linearize(skb),
+                 skb->dev->name, l4_hdr);
+
 		goto drop;
 	}
 
@@ -642,6 +650,69 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static int xennet_xmit_skb(struct sk_buff *skb, struct net_device *dev)
+{
+  char *data = skb->data;
+  int slots;
+  unsigned int offset = offset_in_page(data);
+  unsigned int len = skb_headlen(skb);
+  struct sk_buff *segs, *nskb;
+  unsigned int gso_segs;
+  unsigned int l4_hdr = 0;
+  int nr_segs = 0;
+
+  slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+      xennet_count_skb_frag_slots(skb);
+
+  if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+    gso_segs = skb_shinfo(skb)->gso_segs;
+    l4_hdr = ip_hdr(skb)->protocol;
+    net_warn_ratelimited(
+	     "xennet:  xennet_xmit_skb err_end: %d slots MAX_SKB_FRAGS: %d div_roundup:%d xennet_count_skb_frag_slots:%d offset:%d skb_headlen:%d skb->len:%d, skb->data_len:%d skb->truesize:%d nr_frags:%d page_size:%d prot:%04x gso:%d linearize:%d gso_segs:%d dev:%s transp:%04x \n",
+             slots, MAX_SKB_FRAGS,DIV_ROUND_UP(offset + len, PAGE_SIZE),
+             xennet_count_skb_frag_slots(skb), offset, len, skb->len,
+             skb->data_len, skb->truesize, skb_shinfo(skb)->nr_frags,
+             PAGE_SIZE, ntohs(skb->protocol), skb_is_gso(skb), skb_linearize(skb), gso_segs,
+	     skb->dev->name, l4_hdr);
+
+    if (skb_is_gso(skb)) {
+      segs = skb_gso_segment(skb, dev->features);
+      if (IS_ERR(segs)){
+        net_warn_ratelimited("xennet xennet_xmit_skb: segment err \n");
+	goto err_end;
+      }
+        
+      do {
+              nr_segs++;
+              nskb = segs;
+              segs = segs->next;
+              nskb->next = NULL;
+              xennet_start_xmit(nskb, dev);
+      } while (segs);
+
+      net_warn_ratelimited("xennet xennet_xmit_skb: split into segs: %d \n", nr_segs);
+      dev_kfree_skb(skb);
+
+    } else if (skb_linearize(skb) == 0) {
+        net_warn_ratelimited("xennet xennet_xmit_skb: gso == 0 and linearize == 0 \n");
+        xennet_start_xmit(skb, dev);
+    } else {
+        goto err_end;
+    }
+  } else {
+    xennet_start_xmit(skb, dev);
+  } 
+ 
+  return NETDEV_TX_OK;
+
+err_end:
+  net_warn_ratelimited("xennet xennet_xmit_skb: ERR END gso:%d linearize:%d\n",skb_is_gso(skb), skb_linearize(skb)); 
+
+  dev_kfree_skb(skb);
+  dev->stats.tx_dropped++;
+  return NETDEV_TX_OK;
+}
+
 static int xennet_close(struct net_device *dev)
 {
 	struct netfront_info *np = netdev_priv(dev);
@@ -777,7 +848,7 @@ next:
 
 	if (unlikely(frags > max)) {
 		if (net_ratelimit())
-			dev_warn(dev, "Too many frags\n");
+			dev_warn(dev, "Too many frags:%d  max:%d\n",frags,max);
 		err = -E2BIG;
 	}
 
@@ -1280,7 +1351,7 @@ static const struct net_device_ops xennet_netdev_ops = {
 	.ndo_open            = xennet_open,
 	.ndo_uninit          = xennet_uninit,
 	.ndo_stop            = xennet_close,
-	.ndo_start_xmit      = xennet_start_xmit,
+	.ndo_start_xmit      = xennet_xmit_skb,
 	.ndo_change_mtu	     = xennet_change_mtu,
 	.ndo_get_stats64     = xennet_get_stats64,
 	.ndo_set_mac_address = eth_mac_addr,
