Index: usr/src/sys/click/net/click_ether.c
===================================================================
--- usr/src/sys/click/net/click_ether.c	(revision 38156)
+++ usr/src/sys/click/net/click_ether.c	(working copy)
@@ -2230,6 +2230,93 @@
 	}
 }
 
+#define CLICKTCP6_HEADER_PULL(mp, len, m, eh, pktlen, ip6ext, curlen)\
+	do {\
+		if((len) > (pktlen)){\
+			return NULL;\
+		}\
+		if (((m) = m_pull((m), (len))) == NULL) {\
+			*(mp) = NULL;\
+			return NULL;\
+		}\
+		*(mp) = (m);\
+		(eh) = mtod((m), struct ether_header *);\
+		(ip6ext) = ((caddr_t)(eh))+(curlen);\
+	} while (0)
+
+/*
+ *This function is used to handle the case that the content carried by the ipv6 message is in different mbufs,
+ *It uses the m_pull () function copies the contents of different mbufs into continuous memory,
+ *Then analyze the four-layer protocol content carried by the ipv6 message in the continuous memory.
+ */
+caddr_t 
+clicktcp6_get_l4_hdr_for_split(struct mbuf **mp, int *proto)
+{
+	struct mbuf *m = *mp;
+	if ((m = m_pull(m, sizeof(struct ether_header) + sizeof(struct ip6_hdr))) == NULL) {
+		*mp = NULL;
+		return NULL;
+	}
+	*mp = m;
+	struct ether_header *eh = mtod(m, struct ether_header *);
+	struct ip6_hdr *ip6 = (struct ip6_hdr *)(eh + 1);/* v6 */
+	int cur_len = sizeof(struct ether_header) + sizeof(struct ip6_hdr);
+	int	pktlen = cur_len + ntohs(ip6->ip6_plen);
+	struct ip6_rthdr *ip6rt = NULL;
+	int	nxt = ip6->ip6_nxt;
+	caddr_t	ip6ext = NULL;
+	int l4_len = 0;
+
+	/* find TCP/UDP */
+	while ((nxt != IPPROTO_NONE) && (cur_len < pktlen)) {
+		switch (nxt) {
+			case IPPROTO_ROUTING:
+				CLICKTCP6_HEADER_PULL(mp, (cur_len + sizeof(struct ip6_rthdr)), m, eh, pktlen, ip6ext, cur_len);
+				ip6rt = (struct ip6_rthdr *)ip6ext;
+				if (ip6rt->ip6r_segleft != 0) {
+					return NULL; /* RFC5095 */
+				}
+				nxt = ip6rt->ip6r_nxt;
+				cur_len +=(((ip6rt->ip6r_len) + 1) << 3);
+				break;
+			case IPPROTO_HOPOPTS:
+			case IPPROTO_DSTOPTS:
+				CLICKTCP6_HEADER_PULL(mp, (cur_len + sizeof(struct ip6_ext)), m, eh, pktlen, ip6ext, cur_len);
+				nxt = ((struct ip6_ext *)ip6ext)->ip6e_nxt;
+				cur_len +=((((struct ip6_ext *)ip6ext)->ip6e_len + 1) << 3);
+				break;
+
+			case IPPROTO_FRAGMENT:
+			case IPPROTO_AH:
+			case IPPROTO_ESP:
+				return NULL;
+
+			case IPPROTO_ICMPV6:
+				l4_len = sizeof(struct icmp6_hdr);
+				goto L4_found;
+			case IPPROTO_TCP:
+				l4_len = sizeof(struct tcphdr);
+				goto L4_found;
+			case IPPROTO_UDP:
+				l4_len = sizeof(struct udphdr);
+				goto L4_found;
+
+			default:
+				return NULL;
+		}
+	}
+	return NULL;
+
+/* find tcp/udp header */
+L4_found:
+	CLICKTCP6_HEADER_PULL(mp, (cur_len + l4_len), m, eh, pktlen, ip6ext, cur_len);
+	/*Do not modify the external parameter proto before other preconditions are not valid*/
+	if (proto) {
+		*proto = nxt;
+	}
+	return ip6ext;
+}
+
 /* 
  * XXXX: The return value, it is an address of l4 header, which only can be used by TCP/UDP/ICMPV6.
  * In other procotols, it's NULL
Index: usr/src/sys/click/netinet/click_input.c
===================================================================
--- usr/src/sys/click/netinet/click_input.c	(revision 38156)
+++ usr/src/sys/click/netinet/click_input.c	(working copy)
@@ -4385,11 +4385,25 @@
 	}
 
 	bsd_packets++;
-	do {		
+	do {
+		if ((m = m_pull(m, sizeof(struct ether_header) + sizeof(struct ip))) == NULL) {
+			ertbsd_drop_snd++;
+			goto next_pkt;
+		}
 		eh = mtod(m, struct ether_header *);
 		isipv6 = IS_IP_V6((struct ip*)(eh + 1));
-		
+
 		if (isipv6){
+			l4_hdr = clicktcp6_get_l4_hdr_for_split(&m, &proto);
+			if(m == NULL){
+				ertbsd_drop_snd++;
+				goto next_pkt;
+			}
+			if (l4_hdr  == NULL) {
+				proto = IPPROTO_IP;
+			}
+			eh = mtod(m, struct ether_header *);
+			ip6 = (struct ip6_hdr *)(eh + 1);
 			ip6 = (struct ip6_hdr *)(eh + 1);/* v6 */
 			l4_hdr = clicktcp6_get_l4_hdr(ip6, &proto);
 			sip = &ip6->ip6_src;
Index: usr/src/sys/click/netinet/click_var.h
===================================================================
--- usr/src/sys/click/netinet/click_var.h	(revision 38156)
+++ usr/src/sys/click/netinet/click_var.h	(working copy)
@@ -1707,6 +1707,7 @@
 int  clicktcp_dooptions(struct mbuf *);
 int  clicktcp_strip_tcpoptions(struct mbuf *m , int isipv6, void *ip, struct tcphdr *tcp, clickpcb_t *pcb, int datalen, tcp_seq sendleftwin) ;
 caddr_t  clicktcp6_get_l4_hdr(struct ip6_hdr *ip6, int *proto);
+caddr_t clicktcp6_get_l4_hdr_for_split(struct mbuf **mp, int *proto);
 
 void clickudp_cleanup_pcb(clickpcb_udp_t *pcb);
 void clickicmp_cleanup_pcb(clickpcb_icmp_t *pcb);
