Index: /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_input.c
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_input.c	(revision 38379)
+++ /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_input.c	(working copy)
@@ -18503,9 +18503,12 @@
 				int mtu = ifp->if_mtu;
 				ip = mtod(m, struct ip *);
 				struct mbuf *mp = NULL;
-				if (ip->ip_p == IPPROTO_UDP && ntohs(ip->ip_len) > mtu) {
+				if ((ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) && ntohs(ip->ip_len) > mtu) {
 					/*hardware checksum may work abormal for UDP if IP fragment happened*/
-					clickudp_udp_cksum_sw(m, ifp);
+                                        if ( ip->ip_p == IPPROTO_UDP )
+					    clickudp_udp_cksum_sw(m, ifp);
+                                        else if ( ip->ip_p == IPPROTO_TCP )
+					    clicktcp_tcp_cksum_sw(m, ifp);
 
 					/*enable IP fragment*/
 					ip->ip_off = 0;
Index: /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_var.h
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_var.h	(revision 38379)
+++ /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_var.h	(working copy)
@@ -1940,6 +1940,19 @@
 		   flag, 1);
 }
 
+static __inline void
+clicktcp_tcp_cksum_sw(struct mbuf *mp, struct ifnet *ifp)
+{
+    struct ip *ip = mtod(mp, struct ip *);
+    struct tcphdr *tcp = (struct tcphdr *)((caddr_t)ip + sizeof(struct ip));
+    int totalsize = ntohs(ip->ip_len);
+    int iphl = (ip->ip_hl) << 2;       /* IP header length */
+
+    tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+                             htons(totalsize - iphl + IPPROTO_TCP));
+    mp->m_pkthdr.csum_flags &= ~CSUM_TCP;
+    tcp->th_sum = in_cksum_skip(mp, totalsize, iphl);
+}
 
 /*
  * Given a packet header mbuf containing TCP/IP headers (in network
