Index: usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c
===================================================================
--- usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c	(revision 39028)
+++ usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c	(working copy)
@@ -83,6 +83,8 @@
 extern int rts_enable;
 extern int ertbsd_enable;
 extern LIST_HEAD(, vlan_adapter) vlan_adapter_list;
+struct mbuf *frag_arr[8];
+#define IP_HDR_SIZE 20
 
 char cloud_platform[16] = {0};
 TUNABLE_STR("cloud_platform", cloud_platform, sizeof(cloud_platform));
@@ -873,6 +875,191 @@
 }
 
 static int
+if_dpdk_send_ip_frag(struct if_dpdk_softc *sc, int queue_id, int total_segs, int l2_len)
+{
+	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));
+		if (m == NULL) {
+			frag_arr[i] = NULL;
+			goto send;
+		}
+
+		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_ip_fragments(struct mbuf *orig_mbuf, uint16_t mtu)
+{
+	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;
+	struct mbuf *m = orig_mbuf;
+	uint16_t pload_len;
+
+	//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);
+	}
+
+	switch (ether_type) {
+		case ETHERTYPE_IP:
+			ip = (struct ip *)(mtod(m, u_char *) + l2_len);
+			break;
+		case ETHERTYPE_IPV6:
+			ip6 = (struct ip6_hdr *)(mtod(m, u_char *) + l2_len);
+			break;
+	}
+
+	frag_pload_len = mtu - IP_HDR_SIZE;
+	pload_len = ntohs(ip->ip_len) - IP_HDR_SIZE;
+	frag_count = (pload_len + frag_pload_len - 1) / frag_pload_len;
+
+	// Generate unique fragment ID
+	frag_id = ntohs(ip->ip_id);
+
+	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 -1;
+		}
+		//frag->m_data += IP_HDR_SIZE;
+		// 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, IP_HDR_SIZE);
+		}
+		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, IP_HDR_SIZE);
+		}
+
+		// 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(IP_HDR_SIZE + this_frag_size);
+		frag_ip->ip_off = htons((offset >> 3) | (i < (frag_count - 1) ? IP_MF : 0));
+		frag_ip->ip_sum = 0;
+		frag_ip->ip_id = htons(frag_id);
+
+		// Adjust mbuf length as well as pkthdr len
+		frag->m_len = this_frag_size + IP_HDR_SIZE + 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 = orig_mbuf->m_pkthdr.ether_vtag;
+		frag->m_pkthdr.rcvif = orig_mbuf->m_pkthdr.rcvif ;
+
+		//update flags
+		if ( i == 0) {
+			frag->m_pkthdr.csum_flags = orig_mbuf->m_pkthdr.csum_flags;
+		}
+		else {
+			frag->m_pkthdr.csum_flags = orig_mbuf->m_pkthdr.csum_flags & CSUM_IP;
+		}
+		frag->m_flags = orig_mbuf->m_flags;
+		frag->m_flags = frag->m_flags & ~(M_SEGMENT);
+		frag->m_domain = orig_mbuf->m_domain;
+		frag->m_next = NULL;
+
+		// Copy payload data
+		m_copydata(m, l2_len + IP_HDR_SIZE + 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 +1075,9 @@
 	uint16_t ether_type = 0;
 	struct ether_vlan_header *eh_vlan = NULL;
 	uint16_t l2_len = 0;
+	uint16_t mtu = 0;
 
+	mtu = sc->ifp->if_mtu;
 	for (i = 0; i < pkts_sent; ++i) {
 
 		m = m0[i];
@@ -947,6 +1136,19 @@
 
 		m = m0[i];
 
+		//special case to handle segment paxckets as currently don't support Jumbo
+		ip = (struct ip *)(mtod(m, u_char *) + l2_len);
+		if ((ntohs(ip->ip_len) > mtu) && (ntohs(ip->ip_off) & IP_RF)) {
+			ip->ip_off = htons(ntohs(ip->ip_off) & ~IP_RF);
+			uint16_t nfrag = create_ip_fragments(m , mtu);
+			int ret = if_dpdk_send_ip_frag(sc, queue_id, nfrag, l2_len);
+			for (j = i; j+1 < pkts_sent; ++j)
+				m0[j] = m0[j+1];
+			--i ; --pkts_sent;
+			m_freem_atcp(m);
+			continue;
+		}
+
 		ret = if_dpdk_eth_alloc_mbuf_head(sc->dpdk_host_ctx, queue_id, rm_arr_segs, total_segs);
 		if (ret < 0) {
 			goto send;
