Index: /branches/rel_apv_10_7/usr/click/lib/libip/sip.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libip/sip.c	(revision 39038)
+++ /branches/rel_apv_10_7/usr/click/lib/libip/sip.c	(working copy)
@@ -7257,6 +7257,41 @@
 	return 0;
 }
 
+int
+ip_reassembly_on()
+{
+	int ip_frag_reass = 1;
+
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", NULL, NULL, &ip_frag_reass, sizeof(ip_frag_reass));
+	printf("ip frag processing on ");
+	return 0;
+}
+
+int
+ip_reassembly_off()
+{
+	int ip_frag_reass = 0;
+
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", NULL, NULL, &ip_frag_reass, sizeof(ip_frag_reass));
+	printf("ip frag processing off ");
+	return 0;
+}
+
+int
+show_ip_reassembly()
+{
+	int ip_frag_reass = 0;
+	int len = sizeof(ip_frag_reass);
+
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", &ip_frag_reass, &len, NULL, 0);
+
+	if (ip_frag_reass == 1)
+		printf("ip frag processing on ");
+	else
+		printf("ip frag processing off ");
+	return 0;
+}
+
 /*************************** Moved form cafw.c ******************************/
 int 
 invalid_ip_check(void* ip, int isipv6, int skip)
Index: /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c	(revision 39038)
+++ /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c	(working copy)
@@ -873,6 +873,175 @@
 }
 
 static int
+if_dpdk_send_ipv4_frag(struct if_dpdk_softc *sc, int queue_id, int total_segs, int l2_len, struct mbuf **frag_arr)
+{
+	int i,j,ret;
+	struct mbuf *m;
+	struct if_dpdk_mbuf *cur_rm;
+	int ip_cksum, tcp_cksum, udp_cksum;
+	void *rm_arr[MAX_PKT_BURST];
+	void *rm_arr_segs[MAX_MBUF_SEGS_NUM];
+
+	for (i = 0; i < total_segs; ++i) {
+		m = frag_arr[i];
+		if (i + 1 != total_segs) {
+			prefetch0(frag_arr[i+1]->m_data);
+		}
+
+		m = m_pull(m, l2_len + sizeof(struct ip) + sizeof(struct tcphdr));
+		if (m == NULL) {
+			frag_arr[i] = NULL;
+			goto send;
+		}
+ 
+		frag_arr[i] = m;
+
+		ret = if_dpdk_eth_alloc_mbuf_head(sc->dpdk_host_ctx, queue_id, rm_arr_segs, 1);
+		if (ret < 0) {
+			goto send;
+		}
+
+		rm_arr[i] = cur_rm = rm_arr_segs[0];
+		cur_rm->data_off = 0;
+		cur_rm->nb_segs = 1;
+		cur_rm->pkt_len = m->m_len;
+
+		// this need  to be done
+		if (m->m_flags & M_VLANTAG) {
+			cur_rm->vlan_tci = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
+			cur_rm->ol_flags |= DPDK_TX_VLAN_PKT;
+		}
+		cur_rm->l2_len = l2_len;
+
+		if_dpdk_attach_mbuf(cur_rm, m);
+		cur_rm->next = NULL;
+
+		ip_cksum = m->m_pkthdr.csum_flags & CSUM_IP;
+		tcp_cksum = m->m_pkthdr.csum_flags & CSUM_TCP;
+		udp_cksum = m->m_pkthdr.csum_flags & CSUM_UDP;
+		if (ip_cksum || tcp_cksum || udp_cksum) {
+			if_dpdk_eth_set_cksum_flag(rm_arr[i], ip_cksum, tcp_cksum, udp_cksum);
+		}
+	}
+
+send:
+	if (i < total_segs) {
+		/* free left mbufs, and send good rte_mbufs*/
+		for (j = i; j < total_segs; ++j) {
+			if (frag_arr[j]) {
+				m_freem_atcp(frag_arr[j]);
+			}
+		}
+	}
+	if (i) {
+		return if_dpdk_eth_send_pkts(sc->dpdk_host_ctx, queue_id, rm_arr, i);
+	} else {
+		return -1;
+	}
+}
+
+//Function to create IP fragments from an mbuf chain
+static int
+create_ipv4_fragments(const struct mbuf *m, uint16_t mtu, struct mbuf **frag_arr)
+{
+	struct ip *ip = NULL;
+	struct ip6_hdr *ip6 = NULL;
+	uint16_t ether_type = 0;
+	struct ether_header *eh = NULL;
+	struct ether_vlan_header *eh_vlan = NULL;
+	uint16_t frag_pload_len, offset, frag_id;
+	uint16_t i, l2_len, frag_count;
+	uint16_t pload_len, iphl;
+
+	//extract ethernet header + ip header
+	eh = mtod(m, struct ether_header *);
+	ether_type = ntohs(eh->ether_type);
+
+	if (ether_type == ETHERTYPE_VLAN) {
+		l2_len = sizeof(struct ether_vlan_header);
+		eh_vlan = mtod(m, struct ether_vlan_header *);
+		ether_type = ntohs(eh_vlan->evl_proto);
+	} else {
+		l2_len = sizeof(struct ether_header);
+	}
+
+	if (ether_type != ETHERTYPE_IP)
+		return 0;
+
+	ip = (struct ip *)(mtod(m, u_char *) + l2_len);
+	iphl = ip->ip_hl << 2;
+	frag_pload_len = mtu - iphl;
+	pload_len = ntohs(ip->ip_len) - iphl;
+	frag_count = (pload_len + frag_pload_len - 1) / frag_pload_len;
+
+	offset = 0;
+	for (i = 0; i < frag_count ; i++) {
+		struct mbuf *frag = NULL;
+		struct ether_header *frag_eh = NULL;
+		struct ether_vlan_header *frag_eh_vlan = NULL;
+		struct ip *frag_ip = NULL;
+		uint16_t this_frag_size;
+
+		frag = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+		if (!frag) {
+			printf("Error: Failed to allocate mbuf for fragment\n");
+			for (int j =0; j<i ;j++)
+				m_free(frag_arr[j]);
+			return 0;
+		}
+		// Copy Ethernet header + IP header
+		if (ether_type == ETHERTYPE_VLAN) {
+			frag_eh_vlan = mtod(frag, struct ether_vlan_header *);
+			memcpy(frag_eh_vlan ,eh_vlan , l2_len);
+			frag_ip = (struct ip *)(frag_eh_vlan + 1);
+			memcpy(frag_ip, ip, iphl);
+		}
+		else {
+			frag_eh = mtod(frag, struct ether_header *);
+			memcpy(frag_eh ,eh , l2_len);
+			frag_ip = (struct ip *)(frag_eh + 1);
+			memcpy(frag_ip, ip, iphl);
+		}
+
+		// Set fragment-specific fields : need to adjust m_data & m_flags
+		this_frag_size = (pload_len - offset) > frag_pload_len ? frag_pload_len : (pload_len - offset);
+		frag_ip->ip_len = htons(iphl + this_frag_size);
+		frag_ip->ip_off = htons((offset >> 3) | (i < (frag_count - 1) ? IP_MF : 0));
+		frag_ip->ip_sum = 0;
+
+		// Adjust mbuf length as well as pkthdr len
+		frag->m_len = this_frag_size + iphl + l2_len;
+		frag->m_pkthdr.len = frag->m_len;
+
+		// update pkthdr field vlan need to be fixed.
+		if (m->m_flags & M_VLANTAG)
+			frag->m_pkthdr.ether_vtag = m->m_pkthdr.ether_vtag;
+		frag->m_pkthdr.rcvif = m->m_pkthdr.rcvif;
+
+		//update flags
+		if ( i == 0) {
+			frag->m_pkthdr.csum_flags = m->m_pkthdr.csum_flags;
+		}
+		else {
+			frag->m_pkthdr.csum_flags = m->m_pkthdr.csum_flags & ~CSUM_TCP;
+		}
+		frag->m_flags = m->m_flags & ~(M_SEGMENT);
+		frag->m_domain = m->m_domain;
+		frag->m_next = NULL;
+
+		// Copy payload data
+		m_copydata(m, l2_len + iphl + offset, this_frag_size, (caddr_t)(frag_ip + 1));
+
+		// Add fragment to array
+		frag_arr[i] = frag;
+		offset += this_frag_size;
+	}
+
+	return frag_count;
+}
+
+
+static int
 if_dpdk_send_mbuf(struct if_dpdk_softc *sc, struct mbuf **m0, int pkts_sent, int queue_id)
 {
 	struct if_dpdk_mbuf *prv_rm, *cur_rm;
@@ -888,7 +1057,10 @@
 	uint16_t ether_type = 0;
 	struct ether_vlan_header *eh_vlan = NULL;
 	uint16_t l2_len = 0;
+	uint16_t mtu = 0;
+	struct mbuf *frag_arr[8];
 
+	mtu = sc->ifp->if_mtu;
 	for (i = 0; i < pkts_sent; ++i) {
 
 		m = m0[i];
@@ -947,6 +1119,24 @@
 
 		m = m0[i];
 
+		//special case to handle segment paxckets as currently don't support Jumbo
+		if (m->m_pkthdr.csum_flags & CSUM_L3_FRAG) {
+			ip = (struct ip *)(mtod(m, u_char *) + l2_len);
+			if ((ip->ip_v == IPv4) && (ntohs(ip->ip_len) > mtu)) {
+				uint16_t nfrag = create_ipv4_fragments(m , mtu, frag_arr);
+				if (nfrag) {
+					int ret = if_dpdk_send_ipv4_frag(sc, queue_id, nfrag, l2_len, frag_arr);
+					for (j = i; j+1 < pkts_sent; ++j)
+						m0[j] = m0[j+1];
+					--i ; --pkts_sent;
+					m_freem_atcp(m);
+					continue;
+				} else {
+					printf("IP fragmenation Failed \n");
+				}
+			}
+		}
+
 		ret = if_dpdk_eth_alloc_mbuf_head(sc->dpdk_host_ctx, queue_id, rm_arr_segs, total_segs);
 		if (ret < 0) {
 			goto send;
Index: /branches/rel_apv_10_7/usr/src/sys/click/net/click_ether.c
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/click/net/click_ether.c	(revision 39038)
+++ /branches/rel_apv_10_7/usr/src/sys/click/net/click_ether.c	(working copy)
@@ -2489,6 +2489,8 @@
 
 extern int atcp_max_wire_count;
 extern fastpcb_table_t *fastpcb_interface_table[];
+static int ip_frag_reass = 0; 
+SYSCTL_INT(_net_inet_clicktcp, OID_AUTO, ip_frag_reass, CTLFLAG_RW, &ip_frag_reass, 0, "supported IP frag feature");
 void
 clicktcp_enqueue(struct mbuf *m, struct ifnet *ifp, int isipv6)
 {
@@ -2509,15 +2511,18 @@
 	if(isipv6) {
 		ret = is_clicktcp6_packet(m, ifp, &ip_p, &l4_hdr);
 	} else {
-            iph = mtod(m, struct ip *);
-            if (iph->ip_off & htons(IP_MF | IP_OFFMASK)) {
-                /* XXXGL: shouldn't we save & set m_flags? */
-                m = ip_reass(m);
-                if (m == NULL)
-                    return;
-                m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID;
-                m->m_pkthdr.csum_data = 0xffff;
-            }
+	    if (unlikely(ip_frag_reass == 1)) {
+            	iph = mtod(m, struct ip *);
+            	if ((iph->ip_v == IPv4) && iph->ip_off & htons(IP_MF | IP_OFFMASK)) {
+                	/* XXXGL: shouldn't we save & set m_flags? */
+                	m = ip_reass(m);
+                	if (m == NULL)
+                     	    return;
+                	m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID;
+                	m->m_pkthdr.csum_flags |= CSUM_L3_FRAG;
+                	m->m_pkthdr.csum_data = 0xffff;
+            	}
+	    }
 		ret = is_clicktcp_packet(&m, ifp, &ip_p, &l4_hdr);
 	}
 
Index: /branches/rel_apv_10_7/usr/src/sys/netinet/ip.h
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/netinet/ip.h	(revision 39038)
+++ /branches/rel_apv_10_7/usr/src/sys/netinet/ip.h	(working copy)
@@ -42,6 +42,7 @@
  * Per RFC 791, September 1981.
  */
 #define	IPVERSION	4
+#define	IPv4		4
 
 /*
  * Structure of an internet header, naked of options.
Index: /branches/rel_apv_10_7/usr/src/sys/sys/mbuf.h
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/sys/mbuf.h	(revision 39038)
+++ /branches/rel_apv_10_7/usr/src/sys/sys/mbuf.h	(working copy)
@@ -527,6 +527,7 @@
 #define	CSUM_L5_CALC		0x10000000	/* calculated layer 5 csum */
 #define	CSUM_L5_VALID		0x20000000	/* checksum is correct */
 #define	CSUM_COALESED		0x40000000	/* contains merged segments */
+#define	CSUM_L3_FRAG		0x80000000	/* contains reassemble segments */
 
 /*
  * CSUM flag description for use with printf(9) %b identifier.
@@ -556,7 +557,7 @@
 #define	CSUM_UDP_IPV6		CSUM_IP6_UDP
 #define	CSUM_TCP_IPV6		CSUM_IP6_TCP
 #define	CSUM_SCTP_IPV6		CSUM_IP6_SCTP
-#define	CSUM_FRAGMENT		0x0		/* Unused */
+#define	CSUM_FRAGMENT		CSUM_L3_FRAG		/* Unused */
 
 /*
  * mbuf types describing the content of the mbuf (including external storage).
