Index: /branches/rel_apv_10_7/tools/uosenv/postinstall.sh	(added)
===================================================================
--- /branches/rel_apv_10_7/tools/uosenv/postinstall.sh	(revision 0)
+++ /branches/rel_apv_10_7/tools/uosenv/postinstall.sh	(revision 0)
Index: /branches/rel_apv_10_7/tools/uosenv/prenv.sh	(added)
===================================================================
--- /branches/rel_apv_10_7/tools/uosenv/prenv.sh	(revision 0)
+++ /branches/rel_apv_10_7/tools/uosenv/prenv.sh	(revision 0)
Index: /branches/rel_apv_10_7/tools/update/ustacksystem.ks	(added)
===================================================================
--- /branches/rel_apv_10_7/tools/update/ustacksystem.ks	(revision 0)
+++ /branches/rel_apv_10_7/tools/update/ustacksystem.ks	(revision 0)
Index: /branches/rel_apv_10_7/tools/ustackbuildenv.ks	(added)
===================================================================
--- /branches/rel_apv_10_7/tools/ustackbuildenv.ks	(revision 0)
+++ /branches/rel_apv_10_7/tools/ustackbuildenv.ks	(revision 0)
Index: /branches/rel_apv_10_7/usr/click/bin/backend/sys_tool.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/bin/backend/sys_tool.c	(revision 39072)
+++ /branches/rel_apv_10_7/usr/click/bin/backend/sys_tool.c	(working copy)
@@ -528,6 +528,14 @@
 	},
 	/* DHCP, end */
 
+	/* IP FRAG */
+ 	{
+	write_ip_reassembly,
+	CMD_NORMAL|CMD_ARRAYOS|CMD_SPROXY,
+	"#ip reassembly configuration"
+	},
+	/* IP FRAG, end */
+
 	{
 	write_ip,
 	CMD_NORMAL|CMD_ARRAYOS|CMD_SPROXY,
Index: /branches/rel_apv_10_7/usr/click/lib/libcaui/ca_ui.h
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libcaui/ca_ui.h	(revision 39072)
+++ /branches/rel_apv_10_7/usr/click/lib/libcaui/ca_ui.h	(working copy)
@@ -330,6 +330,7 @@
 /*functions for DHCP*/
 extern int ip_dhcp_on(char*);
 extern char * write_ip_dhcp(char *segment);
+extern char * write_ip_reassembly(char *segment);
 extern int clear_ip_dhcp(void);
 extern int ip_dhcp_off(char*);
 extern int ip_dhcp_fail(char*);
Index: /branches/rel_apv_10_7/usr/click/lib/libip/sip.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libip/sip.c	(revision 39072)
+++ /branches/rel_apv_10_7/usr/click/lib/libip/sip.c	(working copy)
@@ -7257,6 +7257,69 @@
 	return 0;
 }
 
+static int ip_frag_enable = 0;
+char*
+write_ip_reassembly(char *segment)
+{
+	char *save_ip_reass = NULL;
+	char *tmp = NULL;
+	int  buffsize = 64;
+
+	if (nic_init() != IP_SUCCESS) {
+		printf("write_ip_reassembly():nic_init failed \n");
+		return save_ip_reass;
+	}
+
+	if(ip_frag_enable == 1) {
+		if ((tmp = (char *)realloc(save_ip_reass, buffsize)) == NULL) {
+			printf("write_ip_reassembly: fail to realloc.\n");
+			return NULL;
+		} else {
+			if (save_ip_reass == NULL) {
+				/* must do bzero for the first allocation */
+				bzero(tmp, buffsize);
+			}
+			save_ip_reass = tmp;
+		}
+		strcat(save_ip_reass, "ip reassembly on");
+		strcat(save_ip_reass, "\n");
+	}
+
+	return save_ip_reass;
+}
+
+int
+ip_reassembly_on()
+{
+	ip_frag_enable = 1;
+
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", NULL, NULL, &ip_frag_enable, sizeof(ip_frag_enable));
+	printf("ip reassembly on ");
+	return 0;
+}
+
+int
+ip_reassembly_off()
+{
+	ip_frag_enable = 0;
+
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", NULL, NULL, &ip_frag_enable, sizeof(ip_frag_enable));
+	printf("ip reassembly off ");
+	return 0;
+}
+
+int
+show_ip_reassembly()
+{
+	int len = sizeof(ip_frag_enable);
+	sysctlbyname("net.inet.clicktcp.ip_frag_reass", &ip_frag_enable, &len, NULL, 0);
+	if (ip_frag_enable == 1)
+		printf("ip reassembly on ");
+	else
+		printf("ip reassembly 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/libparser/commands.pm
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(revision 39072)
+++ /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(working copy)
@@ -53795,6 +53795,35 @@
 					},
 		],
 	},
+ 	{
+ 		obj_type => "MENU",
+		name => "reassembly",
+		parent_menu => "root_ip",
+		uniq_name => "root_ip_reassembly",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		help_string => "Modify IP FRAGMENT REASSEMBLY settings",
+	},
+ 	{
+		obj_type => "ITEM",
+		name => "on",
+		menu => "root_ip_reassembly",
+		help_string => "Enable IP FRAGMENT REASSEMBLY",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_GLOBAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "ip_reassembly_on",
+		function_args => [],
+	},
+ 	{
+		obj_type => "ITEM",
+		name => "off",
+		menu => "root_ip_reassembly",
+		help_string => "Disable IP FRAGMENT REASSEMBLY",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_GLOBAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "ip_reassembly_off",
+		function_args => [],
+	},
 	{
 		obj_type => "MENU",
 		name => "lldp",
@@ -53936,6 +53965,16 @@
 		function_name => "show_ip_dhcp",
 		function_args => [],
 	},
+	{
+		obj_type => "ITEM",
+		name => "reassembly",
+		help_string => "Display IP REASSEMBLY status",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+		user_level => "CLI_LEVEL_ENABLE",
+		menu => "root_show_ip",
+		function_name => "show_ip_reassembly",
+		function_args => [],
+	},
 # Bug 9585,9614, zhangwy, 2005/02/03
 # SLB RS health check server commands
 	{
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 39072)
+++ /branches/rel_apv_10_7/usr/click/lib/libuinet-atcp/lib/libuinet/uinet_if_dpdk.c	(working copy)
@@ -81,6 +81,7 @@
 extern uint32_t ffo_nic_status_changed;
 extern int rtsbsd_enable;
 extern int rts_enable;
+extern int ip_frag_reass;
 extern int ertbsd_enable;
 extern LIST_HEAD(, vlan_adapter) vlan_adapter_list;
 
@@ -869,9 +870,201 @@
 	*len = total_len;
 
 	return 0;
-	
+
+}
+
+static int
+if_dpdk_send_ipv4_frag(struct if_dpdk_softc *sc, int queue_id, int nb_pkts, 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 < nb_pkts; ++i) {
+		m = frag_arr[i];
+		if (i + 1 != nb_pkts) {
+			prefetch0(frag_arr[i+1]->m_data);
+		}
+
+		m = m_pull(m, m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen + m->m_pkthdr.l4hlen );
+		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 = m->m_pkthdr.l2hlen;
+
+		if_dpdk_attach_mbuf(cur_rm, m);
+		cur_rm->next = NULL;
+
+		// in ip fragment case skip tcp cksum calculation to NIC .
+		ip_cksum = m->m_pkthdr.csum_flags & CSUM_IP;
+		tcp_cksum = 0;
+		udp_cksum = 0;
+		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 < nb_pkts) {
+		/* free left mbufs, and send good rte_mbufs*/
+		for (j = i; j < nb_pkts; ++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;
+	}
+}
+
+static uint16_t
+tcp_cksum_sw(struct ip *ip, struct mbuf *m, uint16_t iphl, uint16_t l2_len) {
+	uint32_t f_sum;
+	uint16_t th_sum;
+
+	th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+      		htons(ntohs(ip->ip_len) - iphl + IPPROTO_TCP));
+	f_sum = in_cksum_skip(m, ntohs(ip->ip_len) + l2_len, iphl + l2_len);
+	f_sum = (~f_sum)&0xffff;
+	f_sum += th_sum;
+	f_sum = (f_sum + (f_sum >> 16)) & 0xffff;
+	th_sum = ~f_sum;
+	return th_sum;
+
 }
 
+//Function to create IP fragments from an mbuf chain
+static int
+create_ipv4_fragments(struct mbuf *m, uint16_t mtu, struct mbuf **frag_arr)
+{
+	struct ip *ip = NULL;
+	struct tcphdr *tcph = NULL;
+	uint16_t ether_type = 0;
+	struct ether_header *eh = NULL;
+	struct ether_vlan_header *eh_vlan = NULL;
+	uint16_t frag_pload_len, offset;
+	uint16_t i, l2_len, frag_count;
+	uint16_t pload_len, iphl , tcpl;
+
+	//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;
+	tcph = (struct tcphdr *)(mtod(m, u_char *) + l2_len + iphl);
+	tcpl = tcph->th_off << 2;
+	frag_pload_len = mtu - iphl;
+	frag_pload_len &= ~7;
+	pload_len = ntohs(ip->ip_len) - iphl;
+	frag_count = (pload_len + frag_pload_len - 1) / frag_pload_len;
+
+	//calculate tcp checksum .
+	tcph->th_sum = 0;
+	tcph->th_sum = tcp_cksum_sw(ip, m, iphl, l2_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;
+		frag->m_pkthdr.l2hlen = l2_len;
+		frag->m_pkthdr.l3hlen = iphl;
+		frag->m_pkthdr.l4hlen = tcpl;
+
+		// 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;
+
+		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)((caddr_t)frag_ip + iphl));
+
+		// 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)
 {
@@ -888,7 +1081,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 +1143,24 @@
 
 		m = m0[i];
 
+		//special case to handle segment paxckets as currently don't support Jumbo
+		if (ip_frag_reass == 1) {
+			ip = (struct ip *)(mtod(m, u_char *) + l2_len);
+			if ((ip->ip_v == IPv4) && (ip->ip_p == IPPROTO_TCP) && (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, 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 39072)
+++ /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[];
+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,20 +2511,22 @@
 	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_data = 0xffff;
+			}
+		}
 		ret = is_clicktcp_packet(&m, ifp, &ip_p, &l4_hdr);
 	}
 
 	/* If not management traffic, do bandwidth limit */
-	if ((ret != CLICKTCP_ERR_PACKET) && 
+	if ((ret != CLICKTCP_ERR_PACKET) &&
 		(ret != CLICKTCP_NOT_OUR_PACKET_IS_MGMT)) {
 		if (bandwidth_deny(m)) {
 			m_freem(m);
Index: /branches/rel_apv_10_7/usr/src/sys/netinet/ip.h
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/netinet/ip.h	(revision 39072)
+++ /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.
