diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index e9f81d4..4d1b221 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1771,6 +1771,130 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
  		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
  		ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);

+		if (skb_is_gso(skb)) {
+			unsigned int inner_l234_hdrlen;
+			unsigned int outer_l34_hdrlen;
+			unsigned int gso_seglen;
+			struct net_device *phy_dev = rt->dst.dev;
+
+			inner_l234_hdrlen = skb_transport_header(skb) - skb_mac_header(skb);
+			if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+				inner_l234_hdrlen += tcp_hdrlen(skb);
+			if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+				inner_l234_hdrlen += sizeof(struct udphdr);
+
+			outer_l34_hdrlen = sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct vxlanhdr);
+			/* gso_seglen is the GSO-ed skb packet len, adjust gso_size
+			 * to fit into physical netdev MTU
+			 */
+			gso_seglen = outer_l34_hdrlen + inner_l234_hdrlen + skb_shinfo(skb)->gso_size;
+			if (gso_seglen > phy_dev->mtu) {
+				struct sk_buff *reply;
+				struct ethhdr *orig_eth;
+				struct ethhdr *new_eth;
+				struct ethhdr *tnl_eth;
+				struct iphdr *orig_ip;
+				struct iphdr *new_ip;
+				struct iphdr *tnl_ip;
+				struct icmphdr *new_icmp;
+				unsigned int room;
+				unsigned int data_len;
+				unsigned int reply_l234_hdrlen;
+				unsigned int vxlan_tnl_hdrlen;
+				struct vxlanhdr *vxh;
+				struct udphdr *uh;
+				__wsum csum;
+
+				/* How much room to store orignal message */
+				room = (skb->len > 576) ? 576 : skb->len;
+				room -= sizeof(struct iphdr) + sizeof(struct icmphdr);
+
+				/* Ethernet payload len */
+				data_len = skb->len - skb_network_offset(skb);
+				if (data_len > room)
+					data_len = room;
+
+				reply_l234_hdrlen = LL_RESERVED_SPACE(phy_dev) + phy_dev->needed_tailroom +
+									sizeof(struct iphdr) + sizeof(struct icmphdr);
+				vxlan_tnl_hdrlen = LL_RESERVED_SPACE(phy_dev) + phy_dev->needed_tailroom +
+									sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct vxlanhdr);
+
+				reply = alloc_skb(vxlan_tnl_hdrlen + reply_l234_hdrlen + data_len, GFP_ATOMIC);
+				reply->dev = phy_dev;
+				skb_reserve(reply, vxlan_tnl_hdrlen + reply_l234_hdrlen);
+
+				new_icmp = (struct icmphdr *)__skb_push(reply, sizeof(struct icmphdr));
+				new_icmp->type = ICMP_DEST_UNREACH;
+				new_icmp->code = ICMP_FRAG_NEEDED;
+				new_icmp->un.frag.mtu = htons(phy_dev->mtu - outer_l34_hdrlen);
+				new_icmp->checksum = 0;
+
+				new_ip = (struct iphdr *)__skb_push(reply, sizeof(struct iphdr));
+				orig_ip = ip_hdr(skb);
+				new_ip->ihl = 5;
+				new_ip->version = 4;
+				new_ip->ttl = 32;
+				new_ip->tos = 1;
+				new_ip->protocol = IPPROTO_ICMP;
+				new_ip->saddr = orig_ip->daddr;
+				new_ip->daddr = orig_ip->saddr;
+				new_ip->frag_off = 0;
+				new_ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + data_len);
+				ip_send_check(new_ip);
+
+				new_eth = (struct ethhdr *)__skb_push(reply, sizeof(struct ethhdr));
+				orig_eth = eth_hdr(skb);
+				ether_addr_copy(new_eth->h_dest, orig_eth->h_source);
+				ether_addr_copy(new_eth->h_source, orig_eth->h_dest);
+				new_eth->h_proto = htons(ETH_P_IP);
+				reply->ip_summed = CHECKSUM_UNNECESSARY;
+				reply->pkt_type = PACKET_HOST;
+				reply->protocol = htons(ETH_P_IP);
+				memcpy(skb_put(reply, data_len), skb_network_header(skb), data_len);
+				new_icmp->checksum = csum_fold(csum_partial(new_icmp, sizeof(struct icmphdr) + data_len, 0));
+
+				/* vxlan encapuslation */
+				vxh = (struct vxlanhdr *)__skb_push(reply, sizeof(*vxh));
+				vxh->vx_flags = htonl(VXLAN_FLAGS);
+				vxh->vx_vni = htonl(vni << 8);
+
+				__skb_push(reply, sizeof(*uh));
+				skb_reset_transport_header(reply);
+				uh = udp_hdr(reply);
+				uh->dest = dst_port;
+				uh->source = src_port;
+				uh->len = htons(reply->len);
+				uh->check = 0;
+				csum = skb_checksum(reply, 0, reply->len, 0);
+				uh->check = udp_v4_check(reply->len, fl4.saddr, dst->sin.sin_addr.s_addr, csum);
+
+				tnl_ip = (struct iphdr *)__skb_push(reply, sizeof(struct iphdr));
+				skb_reset_network_header(reply);
+				tnl_ip->ihl = 5;
+				tnl_ip->version = 4;
+				tnl_ip->ttl = 32;
+				tnl_ip->tos = 1;
+				tnl_ip->protocol = IPPROTO_UDP;
+				tnl_ip->saddr = dst->sin.sin_addr.s_addr;
+				tnl_ip->daddr = fl4.saddr;
+				tnl_ip->frag_off = 0;
+				tnl_ip->tot_len = htons(reply->len);
+				ip_send_check(tnl_ip);
+
+				/* fill with nosense mac header */
+				tnl_eth = (struct ethhdr *)__skb_push(reply, sizeof(struct ethhdr));
+				skb_reset_mac_header(reply);
+				orig_eth = eth_hdr(skb);
+				ether_addr_copy(tnl_eth->h_dest, orig_eth->h_source);
+				ether_addr_copy(tnl_eth->h_source, orig_eth->h_dest);
+				tnl_eth->h_proto = htons(ETH_P_IP);
+				__skb_pull(reply, skb_network_offset(reply));
+
+				/* push encapuslated ICMP message back to sender */
+				netif_rx_ni(reply);
+			}
+		}
  		err = vxlan_xmit_skb(vxlan->vn_sock, rt, skb,
  				     fl4.saddr, dst->sin.sin_addr.s_addr,
  				     tos, ttl, df, src_port, dst_port,

