Index: /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftp.c
===================================================================
--- /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftp.c	(revision 39675)
+++ /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftp.c	(working copy)
@@ -19,8 +19,6 @@
 #include <sys/types.h>
 #include <sys/proc.h>
 #include <sys/pcpu.h>
-#include <sys/queue.h>
-#include <sys/time.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -52,6 +50,7 @@
 #include <click/netinet/click_splice.h>
 #include <click/netinet/click_utils.h>
 #include <click/netinet/click_ftp.h>
+#include <click/netinet/click_ftps_client.h>
 #include <click/netinet/click_ippool.h>
 #include <click/app/proxy/proxy_libc.h> /* for strncasecmp */
 #include <click/app/englog/englog.h>
@@ -98,36 +97,8 @@
 uint16_t ftp_portrange_start;
 uint16_t ftp_portrange_end;
 
-/*
- * TWSD-621
- * The management of firewall rules for the FTPS data channel(encrypted mode).
- * 1. Connect:
- *    Add the new "bound_pcb" to the "recod_bound_pcb_tailhead" list.
- * 2. Disconnect:
- *    Add the "bound_pcb" with a timestamp to the "next_del_bound_pcb_tailhead" list
- *    from the "recod_bound_pcb_tailhead" list.
- * 3. Other event:
- *    Check each "bound_pcb" in "next_del_bound_pcb_tailhead"
- *    and delete those that have exceeded 0.05 seconds.
- */
-struct ftps_bound_pcb_node {
-    struct timeval mark_time;
-    uint32_t server_addr;
-    uint16_t server_port;
-    clickpcb_t *bound_pcb;
-    TAILQ_ENTRY(ftps_bound_pcb_node) entries;
-};
-TAILQ_HEAD(ftps_bound_pcb_tailhead, ftps_bound_pcb_node);
-
-#define  DELETE_BOUND_PCB_THRESHOLD 50000  // 50ms
-__thread int tailhead_initialized = 0;
-__thread struct ftps_bound_pcb_tailhead recod_bound_pcb_tailhead;
-__thread struct ftps_bound_pcb_tailhead next_del_bound_pcb_tailhead;
-void init_ftps_bound_pcb_tailhead();
-void delete_ftps_bound_pcb();
-void delete_ftps_bound_pcb_by_ptr(clickpcb_t *bound_pcb);
-void mark_ftps_bound_pcb(clickpcb_t *pcb);
-void recod_ftps_bound_pcb(clickpcb_t *server_pcb, clickpcb_t *bound_pcb);
+struct ftps_client_node_tree *ftps_client_node_root;
+struct mtx ftps_client_node_tree_mtx;
 
 static int  ftp_new(clickpcb_t *pcb, int app_t);
 static void ftp_predelete(clickpcb_t *pcb);
@@ -219,12 +190,9 @@
 			 ((x) < '0' || (x) > '9'))
 
 static __inline void 
-ftps_delete_listen_pcb(clickpcb_t *pcb, int check_bound_pcb_list)
+ftps_delete_listen_pcb(clickpcb_t *pcb)
 {
 	if (pcb != NULL) {
-		if (check_bound_pcb_list) {
-			delete_ftps_bound_pcb_by_ptr(pcb);
-		}
 		if(CLICKPCB_IS_IPV6(pcb)) {
 			l7popen_cleanup6(&pcb->cp_remoteip6,
 				&pcb->cp_localip6,
@@ -247,12 +215,36 @@
 	return;
 }
 
+static int
+ftps_data_channel_close(clickpcb_t *pcb)
+{
+	if (pcb == NULL) {
+		return -1;
+	}
+
+	if (pcb->cp_app_close == NULL) {
+		return -1;
+	}
+
+	ftps_client_node_t *tmp_node;
+	tmp_node = ftps_client_node_create(pcb, NULL);
+
+	ftps_client_node_t *find_node = NULL;
+	find_node = ftps_client_node_find(ftps_client_node_root, tmp_node, &ftps_client_node_tree_mtx);
+	if (find_node) {
+		ftps_delete_listen_pcb(find_node->bound_pcb);
+	}
+	ftps_client_node_remove(ftps_client_node_root, tmp_node, &ftps_client_node_tree_mtx);
+
+	return 0;
+}
+
 static __inline void
 ftps_setupdataconn(clickpcb_t *listen_pcb, clickpcb_t *passive_open_pcb,
            clickpcb_t *active_open_pcb, click_ftpdata_t *ftpdata)
 {
 	clickpcb_t *ippcb;
-	ftps_delete_listen_pcb(ftpdata->bound_data_pcb, 1);
+	ftps_delete_listen_pcb(ftpdata->bound_data_pcb);
 	listen_pcb->cp_app_head = ((clickpcb_pipe_t *)active_open_pcb)->target->ippcb.cp_app_head;
 	listen_pcb->cp_udata = passive_open_pcb;
 	
@@ -654,7 +646,7 @@
 		if (pcb->cp_udata != NULL) {
 			ftpdata = (click_ftpdata_t *)pcb->cp_udata;
 			if(ftpdata != NULL) {
-				ftps_delete_listen_pcb(ftpdata->bound_data_pcb, 1);
+				ftps_delete_listen_pcb(ftpdata->bound_data_pcb);
 				if (ftpdata->data_pcb != NULL) {
 					if (ftpdata->data_pcb->cp_app != ftps_datachannel_plaintext_delete) {
 						/*ftps ciphertext*/
@@ -685,7 +677,6 @@
 		} else {
 			SPLICE_TARGET_PCB(pcb) = NULL;
 		}
-		delete_ftps_bound_pcb();
 		return 0;
 	}
            	 
@@ -735,7 +726,7 @@
 		if (!FTP_IS_CLIENT(pcb)) {
 			ftpdata = (click_ftpdata_t *)pcb->cp_udata;
 			if(ftpdata != NULL) {
-				ftps_delete_listen_pcb(ftpdata->bound_data_pcb, 1);
+				ftps_delete_listen_pcb(ftpdata->bound_data_pcb);
 				if(ftpdata->data_pcb != NULL) {
 					if (ftpdata->data_pcb->cp_app != ftps_datachannel_plaintext_delete) {
 						/*
@@ -2141,8 +2132,6 @@
 		}
 	}
 
-	delete_ftps_bound_pcb();
-
 	if((vs&&vs->ftp_portrange_start != 0) || ftp_portrange_start != 0) {
 		listen_pcb = clicktcp_bind_ftp(vs, ippcb->cp_localip.s_addr,
 			ippcb->cp_remoteip.s_addr, bind_port, IPPROTO_TCP, 1,
@@ -2187,16 +2176,6 @@
 		listen_pcb->cp_extflags |= CLICKPCB_FTPS_DATA;
 	}
 
-	/* bug 17757, qiuzj, 20071023 */
-	/* give listen_pcb the VS infomation from clnt_pcb */
-	ftp_data_pcb_set_slb_info(listen_pcb, clnt_pcb);
-
-	if (clnt_pcb->cp_type == PCB_PIPE) {/* FTPS */
-		ftps_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
-	} else {
-		ftp_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
-	}
-
 	if(CLICKPCB_IS_IPV6(listen_pcb)) {
 		l7popen_insearch6(&listen_pcb->cp_remoteip6,
 		    &listen_pcb->cp_localip6,
@@ -2211,6 +2190,16 @@
 		    listen_pcb->cp_ip_p);
 	}
 
+	/* bug 17757, qiuzj, 20071023 */
+	/* give listen_pcb the VS infomation from clnt_pcb */
+	ftp_data_pcb_set_slb_info(listen_pcb, clnt_pcb);
+
+	if (clnt_pcb->cp_type == PCB_PIPE) {/* FTPS */
+		ftps_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
+	} else {
+		ftp_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
+	}
+
 	if ((pcb->cp_flags & CLICKPCB_SLB_CONN) && (!SLB_IS_VS_IPV6(vs) && (vs->ftp_extip != 0))) {
 		myip = ntohl(vs->ftp_extip); /*configured external data connection ip */
 	} else {
@@ -2690,8 +2679,6 @@
 		}
 	}
 
-	delete_ftps_bound_pcb();
-
 	if((vs&&vs->ftp_portrange_start != 0) || ftp_portrange_start != 0) {
 		if (CLICKPCB_IS_IPV6 (ippcb)) {
 			listen_pcb = clicktcp6_bind_ftp(vs, &ippcb->cp_localip6,
@@ -2732,16 +2719,6 @@
 	return;
     }
 
-	/* bug 17757, qiuzj, 20071023 */
-	/* give listen_pcb the VS infomation from clnt_pcb */
-	ftp_data_pcb_set_slb_info(listen_pcb, clnt_pcb);
-
-	if(clnt_pcb->cp_type == PCB_PIPE) {/* FTPS */
-		ftps_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
-	} else {
-		ftp_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
-	}
-
 	if(CLICKPCB_IS_IPV6(listen_pcb)) {
 		l7popen_insearch6(&listen_pcb->cp_remoteip6,
 		    &listen_pcb->cp_localip6,
@@ -2755,6 +2732,15 @@
 		    listen_pcb->cp_localport,
 		    listen_pcb->cp_ip_p);
 	}
+    /* bug 17757, qiuzj, 20071023 */
+    /* give listen_pcb the VS infomation from clnt_pcb */
+    ftp_data_pcb_set_slb_info(listen_pcb, clnt_pcb);
+
+	if(clnt_pcb->cp_type == PCB_PIPE) {/* FTPS */
+		ftps_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
+	} else {
+		ftp_setupdataconn(listen_pcb, pcb, clnt_pcb, ftpdata);
+	}
 
 	if ((pcb->cp_flags & CLICKPCB_SLB_CONN) && (!SLB_IS_VS_IPV6(vs) && (vs->ftp_extip != 0))) {
 		myip = ntohl(vs->ftp_extip); /*configured external data connection ip */
@@ -3086,13 +3072,10 @@
 		}
 		pcb->cp_app = NULL;
 		pcb->cp_flags &= ~CLICKPCB_PRE_DELETE;
-		delete_ftps_bound_pcb();
-		mark_ftps_bound_pcb(pcb);
 		return 0;
 	}
 
 	if (pcb_is_new(pcb)) {
-		delete_ftps_bound_pcb();
 		sslp = (struct ssl_data *)(pcb->cp_udata);	
 		if (sslp != NULL && sslp->proxy_data.pcb != NULL) {
 			bound_pcb = sslp->proxy_data.pcb;
@@ -3135,7 +3118,7 @@
 		if (pcb->cp_type == PCB_PIPE && 
 		    ((sslp->session_cache && sslp->session_cache->proxy_data.error_code != 0) ||
 		    (!sslp->session_cache && sslp->proxy_data.error_code != 0))) {
-			ftps_delete_listen_pcb(bound_pcb, 1);
+			ftps_delete_listen_pcb(bound_pcb);
 			if(control_data != NULL) {
 				control_data->bound_data_pcb = NULL;
 			}
@@ -3204,7 +3187,7 @@
 			control_data->bound_data_pcb = NULL;
 			pcb->cp_app = NULL;
 			pcb_terminate(pcb, RST_ID_FTPS_12);
-			ftps_delete_listen_pcb(bound_pcb, 1);
+			ftps_delete_listen_pcb(bound_pcb);
 			return 1;
 		}
 		
@@ -3231,7 +3214,6 @@
 		}
 
 		control_data->bound_data_pcb = NULL;
-		recod_ftps_bound_pcb(server_pcb, bound_pcb);
 #if 0
 		if(!CLICKPCB_IS_IPV6(ippcb)) {
 			eroute_rule = find_eroute_without_mbuf(ippcb->cp_remoteip.s_addr, ippcb->cp_localip.s_addr,
@@ -3261,6 +3243,19 @@
 		server_pcb->splice_data.target = control_pcb; /*NOTE: associate with control connection */
 		control_data->flags |= FTPS_SERVER_DATA_FLAG;
 
+		clickpcb_t *lpcb = ((clickpcb_pipe_t *)pcb)->target->lpcb;
+		lpcb->cp_app_close = ftps_data_channel_close;
+
+		if (ftps_client_node_root == NULL)
+		{
+			MALLOC(ftps_client_node_root, struct ftps_client_node_tree *, sizeof(struct ftps_client_node_tree), M_FTPDATA, M_NOWAIT);
+			RB_INIT(ftps_client_node_root);
+			mtx_init(&ftps_client_node_tree_mtx, "ftps client tree lock", NULL, MTX_DEF);
+		}
+
+		ftps_client_node_t *new_node = ftps_client_node_create(lpcb, bound_pcb);
+		ftps_client_node_insert(ftps_client_node_root, new_node, &ftps_client_node_tree_mtx);
+
 		FASTLOG_SETUP_CONNECTION(CLICKTCP_SETUP_CONN_LOG, pcb, server_pcb);
 	}
 
@@ -4171,89 +4166,3 @@
 	}
 	return 0;
 }
-
-/*
- * Initialize the management list for FTPS bound_pcb
- */
-void init_ftps_bound_pcb_tailhead() {
-	if (tailhead_initialized == 0) {
-		TAILQ_INIT(&recod_bound_pcb_tailhead);
-		TAILQ_INIT(&next_del_bound_pcb_tailhead);
-		tailhead_initialized = 1;
-	}
-}
-
-/*
- * Delete bound_pcb that have been disconnected for more than X seconds.
- */
-void delete_ftps_bound_pcb() {
-	clickpcb_t *bound_pcb = NULL;
-	struct timeval now;
-	struct ftps_bound_pcb_node *node, *tmp_node;
-
-	init_ftps_bound_pcb_tailhead();
-	microuptime(&now);
-	TAILQ_FOREACH_SAFE(node, &next_del_bound_pcb_tailhead, entries, tmp_node) {
-		long long elapsed_usec = (now.tv_sec - node->mark_time.tv_sec) * 1000000LL +
-									(now.tv_usec - node->mark_time.tv_usec);
-		if (elapsed_usec >= DELETE_BOUND_PCB_THRESHOLD) {
-			bound_pcb = node->bound_pcb;
-			ftps_delete_listen_pcb(bound_pcb, 0);
-			TAILQ_REMOVE(&next_del_bound_pcb_tailhead, node, entries);
-			FREE(node, M_TEMP);
-		} else {
-			break;
-		}
-	}
-}
-
-/*
- * Delete a specific bound_pcb from the FTPS management list.
- */
-void delete_ftps_bound_pcb_by_ptr(clickpcb_t *bound_pcb) {
-	struct ftps_bound_pcb_node *node, *tmp_node;
-
-	init_ftps_bound_pcb_tailhead();
-	TAILQ_FOREACH_SAFE(node, &recod_bound_pcb_tailhead, entries, tmp_node) {
-		if (node->bound_pcb == bound_pcb) {
-			TAILQ_REMOVE(&recod_bound_pcb_tailhead, node, entries);
-			FREE(node, M_TEMP);
-		}
-	}
-	TAILQ_FOREACH_SAFE(node, &next_del_bound_pcb_tailhead, entries, tmp_node) {
-		if (node->bound_pcb == bound_pcb) {
-			TAILQ_REMOVE(&next_del_bound_pcb_tailhead, node, entries);
-			FREE(node, M_TEMP);
-		}
-	}
-}
-
-/*
- * Add a timestamp to bound_pcb when the connection is closed.
- */
-void mark_ftps_bound_pcb(clickpcb_t *pcb) {
-	struct ftps_bound_pcb_node *node, *tmp_node;
-
-	init_ftps_bound_pcb_tailhead();
-	TAILQ_FOREACH_SAFE(node, &recod_bound_pcb_tailhead, entries, tmp_node) {
-		if (node->server_addr == pcb->cp_remoteip.s_addr && node->server_port == pcb->cp_remoteport) {
-			TAILQ_REMOVE(&recod_bound_pcb_tailhead, node, entries);
-			TAILQ_INSERT_TAIL(&next_del_bound_pcb_tailhead, node, entries);
-			microuptime(&node->mark_time);
-		}
-	}
-}
-
-/*
- * Record a new bound_pcb.
- */
-void recod_ftps_bound_pcb(clickpcb_t *server_pcb, clickpcb_t *bound_pcb) {
-	struct ftps_bound_pcb_node *node;
-
-	init_ftps_bound_pcb_tailhead();
-	MALLOC(node, struct ftps_bound_pcb_node *, sizeof(struct ftps_bound_pcb_node), M_TEMP, M_NOWAIT);
-	node->server_addr = server_pcb->cp_remoteip.s_addr;
-	node->server_port = server_pcb->cp_remoteport;
-	node->bound_pcb = bound_pcb;
-	TAILQ_INSERT_TAIL(&recod_bound_pcb_tailhead, node, entries);
-}
\ No newline at end of file
Index: /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftps_client.h
===================================================================
--- /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftps_client.h	(revision 0)
+++ /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_ftps_client.h	(working copy)
@@ -0,0 +1,124 @@
+#ifndef _CLICK_FTPS_CLIENT_H_
+#define _CLICK_FTPS_CLIENT_H_
+
+#include <sys/tree.h>
+#include <sys/mutex.h>
+
+typedef struct ftps_client_node {
+	/* Red-black tree entry point */
+	RB_ENTRY(ftps_client_node) entry;
+
+	uint64_t tree_key;
+
+	clickpcb_t *lpcb;
+	clickpcb_t *bound_pcb;
+} ftps_client_node_t;
+
+/* Comparison function used for red-black trees. */
+static __inline int
+ftps_client_node_compare(ftps_client_node_t *node_a, ftps_client_node_t *node_b) {
+    return (node_a->tree_key < node_b->tree_key ? -1 : node_a->tree_key > node_b->tree_key);
+}
+
+/* Define the structure and functions for a red-black tree. */
+RB_HEAD(ftps_client_node_tree, ftps_client_node);
+RB_PROTOTYPE_STATIC(ftps_client_node_tree, ftps_client_node, entry, ftps_client_node_compare)
+RB_GENERATE_STATIC(ftps_client_node_tree, ftps_client_node, entry, ftps_client_node_compare)
+
+/* Initialize the node of the red-black tree. */
+static __inline ftps_client_node_t *
+ftps_client_node_create(clickpcb_t *lpcb, clickpcb_t *bound_pcb) {
+	ftps_client_node_t *node;
+	MALLOC(node, ftps_client_node_t *, sizeof(ftps_client_node_t), M_FTPDATA, M_NOWAIT);
+	if (node != NULL) {
+		node->tree_key = (uint64_t)(uintptr_t)lpcb;
+		node->lpcb = lpcb;
+		node->bound_pcb = bound_pcb;
+	}
+	return node;
+}
+
+/*
+ * Search for a node in the red-black tree.
+ * return:
+ * - the node if found
+ * - NULL if not found
+ */
+static __inline ftps_client_node_t *
+ftps_client_node_find(
+    struct ftps_client_node_tree *root,
+    ftps_client_node_t *data_node,
+    struct mtx *tree_mtx
+) {
+    /* RB_FIND will return the node if found, otherwise it will return NULL. */
+    mtx_lock(tree_mtx);
+    ftps_client_node_t *tmp_node =
+        RB_FIND(ftps_client_node_tree, root, data_node);
+    mtx_unlock(tree_mtx);
+
+    return tmp_node;
+}
+
+/*
+ * Insert a node into the red-black tree.
+ * return:
+ * - NULL is successful return NULL
+ * - already exists reutrn existing node
+ */
+static __inline ftps_client_node_t *
+ftps_client_node_insert(
+    struct ftps_client_node_tree *root,
+    ftps_client_node_t *data_node,
+    struct mtx *tree_mtx
+) {
+    ftps_client_node_t *tmp_node
+        = ftps_client_node_find(root, data_node, tree_mtx);
+
+    if (tmp_node == NULL) {
+        /*
+         * RB_INSERT returns NULL if the insertion is successful;
+         * if the node already exists, it returns the existing node.
+         */
+        mtx_lock(tree_mtx);
+        tmp_node = RB_INSERT(ftps_client_node_tree, root, data_node);
+        mtx_unlock(tree_mtx);
+        return tmp_node;
+    }
+
+    return NULL;
+}
+
+/* Free the memory of the node. */
+static __inline void
+free_ftps_client_node(
+    ftps_client_node_t *data_node
+) {
+    FREE(data_node, M_FTPDATA);
+}
+
+/*
+ * Removing a node from a red-black tree and linked list.
+ * return:
+ * - 1 for success
+ * - 0 for not found
+ */
+static __inline int
+ftps_client_node_remove(
+    struct ftps_client_node_tree *root,
+    ftps_client_node_t *data_node,
+    struct mtx *tree_mtx
+) {
+    ftps_client_node_t *tmp_node
+        = ftps_client_node_find(root, data_node, tree_mtx);
+
+    if (tmp_node != NULL) {
+        mtx_lock(tree_mtx);
+		RB_REMOVE(ftps_client_node_tree, root, tmp_node);
+        mtx_unlock(tree_mtx);
+		free_ftps_client_node(tmp_node);
+        return 1;
+    }
+    return 0;
+}
+
+#endif /* _CLICK_FTPS_CLIENT_H_ */

Property changes on: usr/src/sys/click/netinet/click_ftps_client.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_input.c
===================================================================
--- /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_input.c	(revision 39675)
+++ /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_input.c	(working copy)
@@ -12106,6 +12106,11 @@
 			/* try to close sf */
 			sf_session_close(pcb);
 
+			if (pcb->cp_app_close) {
+				pcb->cp_app_close(pcb);
+				pcb->cp_app_close = NULL;
+			}
+
 			PCB_TO_SPCB(pcb, spcb);
 		}
 		else {
@@ -12178,6 +12183,11 @@
 		/* try to close sf */
 		sf_session_close(pcb);
 
+		if (pcb->cp_app_close) {
+			pcb->cp_app_close(pcb);
+			pcb->cp_app_close = NULL;
+		}
+
 		PCB_TO_SPCB(pcb, spcb);
 		clicktcp_leave_func(int, 0);
 	}
@@ -12696,6 +12706,11 @@
 		/* try to close sf */
 		sf_session_close(pcb);
 
+		if (pcb->cp_app_close) {
+			pcb->cp_app_close(pcb);
+			pcb->cp_app_close = NULL;
+		}
+
 		if (PCB_SSF_STANDBY(pcb)) {
 			/* For ssf standby, don't into timewait, directly free the pcb */
 			pcb_cleanup(pcb);
@@ -17759,6 +17774,11 @@
 	clicktcp_disable_listen_port(IPPROTO_TCP, pcb->cp_remoteport, PT_RS);
     }
 
+	if (pcb->cp_app_close) {
+		pcb->cp_app_close(pcb);
+		pcb->cp_app_close = NULL;
+	}
+
     clicktcp_close_slb_conn(pcb);
     clicktcp_cleanup_pcb(pcb);
     clickpcb_delete(pcb);
Index: /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_pcb.h
===================================================================
--- /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_pcb.h	(revision 39675)
+++ /branches/rel_apv_10_7_3/usr/src/sys/click/netinet/click_pcb.h	(working copy)
@@ -1,594 +1,596 @@
-#ifndef _CLICK_PCB_H
-#define _CLICK_PCB_H
-#include <click/kern/click_callout.h>
-#include <click/app/cm/sf_var.h>
-
-/* type of PCBs */
-#define PCB_TCP		1
-#define PCB_UDP		2
-#define PCB_PIPE	3
-#define PCB_ICMP	4
-#define CLICKPCB_RETRY 2
-
-#define PCB_SERVER_SIDE(pcb) (pcb->cp_rs)
-#define PCB_CLIENT_SIDE(pcb) (!pcb->cp_rs && pcb->cp_vs)
-
-
-#define PROTOCOL_ALL (PCB_TCP | PCB_UDP | PCB_ICMP)
-#define PROTOCOL_UNKNOWN 0
-
-#ifndef _KERNEL
-	#define MAX_SACK_BLKS	6	/* Max # SACK blocks stored at receiver side */
-	#define CLICKPCB_IPV6		0x00000200
-	#define CLICKPCB_ACL_DENY     0x00080000	
-	#define CLICKPCB_IS_IPV6(pcb) ((pcb)->cp_extflags & CLICKPCB_IPV6)
-	
-	struct eroute_info {
-		uint32_t rule_id;
-		struct eroute_rule *rule;
-	};
-
-#endif
-
-struct clickpcb;
-
-/*
- * similar like struct sackhole
- */
-struct click_sackhole {
-	tcp_seq start;		/* start seq no. of hole */
-	tcp_seq end;		/* end seq no. */
-	TAILQ_ENTRY(click_sackhole) scblink;	/* scoreboard linkage */
-};
-
-struct click_sackhint {
-	struct click_sackhole *nexthole;
-	int sack_bytes_rexmit;
-};
-
-
-typedef struct clickpcb2
-{
-    /* TCP Option: WS*/
-    u_char	snd_scale;		/* window scaling for send window */
-    u_char	rcv_scale;		/* window scaling for recv window */
-
-    /* SACK related state */
-	int	snd_numholes;		/* number of holes seen by sender */
-	TAILQ_HEAD(click_sackhole_head, click_sackhole) snd_holes;	/* sorted */
-	tcp_seq	snd_fack;		/* last seq number(+1) sack'd by rcv'r*/
-	tcp_seq	sack_nextrexmt;	/* the highest sequence number + 1
-							   which has been retransmitted during
-							   the current loss recovery phase,
-							   the next rexmt should start from this seq */
-	struct click_sackhint sackhint;
-
-    int	rcv_numsacks;		/* # distinct sack blks present */
-    struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */
-
-	/* support ts option */
-	uint32_t last_ack_sent;/*save the last ack from TM*/
-	uint32_t ts_recent;/* timestamp echo data */
-	uint32_t ts_recent_age;/* when last updated */
-
-	uint32_t t_srtt;/* smoothed round-trip time */
-	uint32_t t_rttvar;/* variance in round-trip time */
-	struct clickpcb *pcb;	/* coreference pcb */
-	TIMER_ENTRY(clickpcb2) ssf;		/* queue of pending ssf slow timeout events */
-	TAILQ_ENTRY(clickpcb2) ssf_send;	/* queue of store ssf send pending event */
-	TAILQ_ENTRY(clickpcb2) ssf_recv;	/* queue of store ssf receive pending event */
-	ssf_tcp_sync_head_t ssf_tcp_sync_head;	/* SSF standby store received SF_APP_TCP_SYNC app_id packet 
-						or SF_TCP_EVENT_SYNC_SEND event_type packet data which is sent by SSF active */
-	ssf_pcb_event_data_head_t ssf_pcb_ssl_event_head; /* SSF standby store SF_APP_SSL app_id event data which is sent by SSF active */					
-	ssf_pcb_event_data_head_t ssf_pcb_http_event_head; /* SSF standby store SF_APP_HTTP app_id event data which is sent by SSF active */
-	uint32_t	ssf_event_seq;
-	uint32_t	ssf_tcp_sync_pkt_num;
-}clickpcb2_t;
-
-/* fields common to all PCBs */
-typedef struct basic_clickpcb
-{
-	uint32_t   bcp_type;                          /* see above for values */
-	uint32_t   ncp_flags;                         /* flags */
-	uint64_t   ncp_extflags;                      /* bug 17757, qiuzj, 20071023 */
-	uint32_t   incarnation_id;                    /* unique per alloc */
-	uint32_t   incomp_conn_incarnation_id;        /* for incomplete conn*/
-	uint32_t   index;                             /* unique pcb index - uproxy */
-	void*      bcp_udata;                         /* application data */
-	int        (*bcp_app)(struct clickpcb *);     /* application handler */
-	clickpcb2_t *bcp_pcb2;
-	TAILQ_ENTRY(basic_clickpcb) bcp_pe; /* queue of pending proxy events */
-	STAILQ_ENTRY(basic_clickpcb) bcp_dq; /* used for L7 uproxy delete queue */
-	/* flag values are defined separately for each PCB type */
-	
-	uint32_t bcp_segment_id;	/* the segment id */
-	uint32_t bcp_segment_inst;	/* the instance id for the segment */
-} basic_clickpcb_t;
-
-/* fields common to all network type PCBs, including TIME_WAIT */
-typedef struct basic_network_clickpcb
-{
-	basic_clickpcb_t bcp;
-	union {
-		struct in_addr   bnc_localip4;
-		struct in6_addr  bnc_localip6;
-	} bnc_local_ip;
-
-	union {
-		struct in_addr		bnc_remoteip4;
-		struct in6_addr	bnc_remoteip6; 
-	}bnc_remote_ip;
-	
-	uint16_t         bnc_localport, bnc_remoteport;
-	uint8_t          bnc_ip_p;                  /* IP protocol */
-	uint8_t          bnc_state;                 /* state for TCP/UDP */
-	uint8_t          bnc_realstate;	            /* real state of TCP */
-	uint8_t		sf_app_id;
-	struct click_hash_node *bnc_node;           /* pointer to container node */
-} basic_network_clickpcb_t;
-
-
-
-#define	bnc_localip bnc_local_ip.bnc_localip4
-#define	bnc_remoteip bnc_remote_ip.bnc_remoteip4
-#define	bnc_localip6 bnc_local_ip.bnc_localip6
-#define	bnc_remoteip6 bnc_remote_ip.bnc_remoteip6
-
-struct _tuxedo_data {
-	uint32_t member_id;
-	uint32_t wsh_port_offset;	
-};
-
-/* this is a vs pcb, and the client is a l4device, 
- * record the l4device id and send response packet to the l4 device
- */
-struct _orch_data {
-	uint32_t l4device_id;
-	uint32_t l4device_instance_id;
-};
-
-/* fields common to network type PCBs, not including TIME_WAIT */
-typedef struct network_clickpcb
-{
-	basic_network_clickpcb_t bnc;
-	
-	struct _slb_rs           *ncp_rs;       /* real server for this conn */
-	struct _nat_table        *ncp_nat_table; /* point to the nat item */
-
-	struct _slb_vs           *ncp_vs;       /* virtual server for this conn */
-                                            /* Note: In many cases, ncp_vs is NULL */
-	union {
-		struct _webagent_ws *ncp_ws;       /* webagent service for this conn */
-		void		 *ncp_doh;		/* doh server for this conn */
-	};
-
-	union {
-		struct _tuxedo_data      ncp_tuxedo;
-		struct _orch_data        orch_data;
-	};
-
-	uint32_t                 ncp_nat_inst;  /* for nat item*/
-	uint32_t                 ncp_rs_inst;	/* instance id for real */
-
-	uint32_t                 ncp_vs_inst;
-	
-	uint32_t                 ncp_ws_inst;
-	
-	struct eroute_info       ncp_eroute;    /* extended routing table entry, support both ipv4 and ipv6 */
-	
-/* bug54429,remove unused field of pcb.For ncp_fwif is annotationed by "#if 0" in other plases,so here follow it*/
-#if 0
-	/* Bug 13459, luozy, 20061107*/
-	struct ifnet * ncp_fwif;                /* webwall interface pointer */
-	/*Bug 13459, end*/
-	LIST_ENTRY (clickpcb) ncp_ddpcb; /* dd pcb list */
-#endif
-
-#ifdef _KERNEL	
-	app_timeout_head_t       *ncp_app_head; /* inactivity timer */
-#else
-	void                     *ncp_app_head; /* inactivity timer */
-#endif
-	u_int16_t                ncp_mss;       /* client max segment size */
-	struct ifnet *numa_ifp;
-} network_clickpcb_t;
-
-
-/* pseudo-struct for TIME_WAIT PCBs */
-typedef struct network_clickpcb_and_timewait
-{
-	basic_network_clickpcb_t bnc;
-	struct _slb_vs       *ncp_vs; /* add vs info for spcb */
-} network_clickpcb_and_timewait_t;
-
-/* pseudo-struct for non-network PCBs */
-typedef struct non_network_clickpcb
-{
-	struct {
-		basic_clickpcb_t bcp;
-	} bnc;
-} non_network_clickpcb_t;
-
-typedef struct clickpcb_timewait
-{
-    network_clickpcb_and_timewait_t ncp;
-
-    tcp_seq	recvnextseq;
-    TAILQ_ENTRY(clickpcb_timewait) tw;	        /* queue of TIME_WAIT entries */
-    int	time_wait_expire;               /* amount of time to wait */
-    int time_wait_timer_flag;
-} clickpcb_timewait_t;
-
-
-/* macros for easy access */
-#define cp_pcb2       ncp.bnc.bcp.bcp_pcb2
-#define cp_type       ncp.bnc.bcp.bcp_type
-#define cp_incid      ncp.bnc.bcp.incarnation_id
-#define cp_incomp_conn_incid ncp.bnc.bcp.incomp_conn_incarnation_id
-#define cp_udata      ncp.bnc.bcp.bcp_udata
-#define cp_index      ncp.bnc.bcp.index
-#define cp_app        ncp.bnc.bcp.bcp_app
-#define cp_flags      ncp.bnc.bcp.ncp_flags
-#define cp_extflags   ncp.bnc.bcp.ncp_extflags
-#define cp_localip    ncp.bnc.bnc_localip
-#define cp_remoteip   ncp.bnc.bnc_remoteip
-#define cp_localip6   ncp.bnc.bnc_localip6
-#define cp_remoteip6  ncp.bnc.bnc_remoteip6
-#define cp_localport  ncp.bnc.bnc_localport
-#define cp_remoteport ncp.bnc.bnc_remoteport
-#define cp_ip_p       ncp.bnc.bnc_ip_p
-#define cp_state      ncp.bnc.bnc_state
-#define cp_realstate  ncp.bnc.bnc_realstate
-#define cp_sf_app_id		ncp.bnc.sf_app_id
-#define cp_node       ncp.bnc.bnc_node
-#define cp_rs         ncp.ncp_rs
-#define cp_rs_inst    ncp.ncp_rs_inst
-#define cp_vs         ncp.ncp_vs
-#define cp_vs_inst    ncp.ncp_vs_inst
-#define cp_ws         ncp.ncp_ws
-#define cp_ws_inst    ncp.ncp_ws_inst
-#define cp_tuxedo     ncp.ncp_tuxedo
-#define cp_doh	      ncp.ncp_doh
-
-#define cp_eroute     ncp.ncp_eroute/* for both ipv4 and ipv6 */
-
-#if 0
-/* Bug 13459, luozy, 20061107*/
-#define cp_fwif       ncp.ncp_fwif
-/*Bug 13459, end*/
-#define cp_ddpcb      ncp.ncp_ddpcb
-#endif
-#define cp_app_head   ncp.ncp_app_head
-#define cp_mss        ncp.ncp_mss
-/* the following two are aliases for ICMP */
-#define cp_id         cp_localport
-#define cp_dummy      cp_remoteport
-#define cp_nat_table  ncp.ncp_nat_table
-#define cp_nat_inst   ncp.ncp_nat_inst
-#define cp_segment_id    ncp.bnc.bcp.bcp_segment_id
-#define cp_segment_inst  ncp.bnc.bcp.bcp_segment_inst
-
-/*
- * Here are the groups of PCBs used in the description below.
- *
- *  network - TCP, UDP and ICMP (note this doesn't include TIME_WAIT)
- *  SLB     - TCP and UDP
- *
- * PCB fields shared between structs and their actual use are as follows.
- *
- *  basic_clickpcb: all
- *   type            all
- *   udata           all
- *   app             all
- *   flags           all, but used for different meanings depending on type
- *
- *  basic_network_clickpcb: TCP, T_W TCP, UDP and ICMP
- *   localip         network and T_W TCP
- *   remoteip        network and T_W TCP
- *   localport       network and T_W TCP
- *   remoteport      network and T_W TCP
- *   ip_p            network and T_W TCP
- *   state           TCP, T_W TCP and UDP
- *   realstate       TCP
- *   node            network and T_W TCP
- *
- *  network_clickpcb: TCP, UDP and ICMP 
- *   rs              SLB
- *   rs_inst         SLB
- *   eroute          network
- *   app_head        TCP (and IP)
- *   mss             TCP (and IP)
- */
-
-typedef struct click_splice_data
-{
-    u_int32_t        seq_offset;  /* sequence number offset -
-				     add this to seq# flowing in this direction */
-    struct clickpcb *target;      /* pointer to target (client or server) pcb */
-#if 0
-    u_int16_t        cksum_patch; /* tcp checksum patch */
-    u_int16_t        ipsum_patch; /* ip checksum patch */
-#endif
-} click_splice_t;
-
-typedef struct clickpcb_ippcb
-{
-    network_clickpcb_t ncp;
-} clickpcb_ippcb_t;
-
-struct click_ipfrag {
-    TAILQ_ENTRY(click_ipfrag) next_pcb;
-    TAILQ_ENTRY(click_ipfrag) next_global;
-    struct clickpcb_udp *pcb;
-    int	           last_used;
-    struct in_addr remoteip;
-    struct in_addr localip;
-    struct mbuf	   *pkts; /* buffered packets */
-    uint32_t	   num_pkts; /* Number of buffered packets */
-    /* 32 bit to avoid someone playing with us */
-    uint32_t	   tot_len;
-    uint32_t	   cur_len;
-    uint16_t	   ip_id;
-};
-
-
-typedef struct clickpcb_udp
-{
-    network_clickpcb_t ncp;
-
-    struct mbuf    *packet;
-    struct clickpcb_udp *reverse; /*Other side of UDP connection */
-    /*for ddos slb dns*/
-    struct timeval *ddos_dns_start_time; /*DDOS_DNS_MAX*/
-	int ddos_dns_is_calcu_resptime;
-    /* for timers */
-    struct click_callout timeout_callout;      /* timeout timer     */
-    /* 
-     * Bug 16510, luozy, 20050515 
-     *
-     * "u_int16_t" is not enough 
-     * (65535/HZ = 655 seconds),
-     * change "u_int16_t" to "u_int32_t"
-     */
-    u_int32_t            timeout;              /* connection timeout time */
-    /* Bug 16510, end */
-    TAILQ_HEAD(frags, click_ipfrag) frags;
-    TAILQ_ENTRY(clickpcb_udp) next_server;
-    TAILQ_ENTRY(clickpcb_udp) dq;
-	uint16_t reset_errorcode;
-
-	/* Record slb connection time */
-	int slb_conn_time;
-} clickpcb_udp_t;
-
-
-typedef struct clickpcb_icmp
-{
-    network_clickpcb_t ncp;
-
-    struct mbuf    *packet;
-    struct clickpcb_icmp *reverse; /*Other side of ICMP connection */
-
-
-    /* the number of echorequest without echoreply */
-    int32_t        outstanding_requests;
-
-    /* for timers */
-    struct click_callout timeout_callout;	   /* timeout timer	*/
-    TAILQ_ENTRY(clickpcb_icmp) dq;
-    /* 
-     * Bug 16510, luozy, 20050515 
-     *
-     * "u_int16_t" is not enough 
-     * (65535/HZ = 655 seconds),
-     * change "u_int16_t" to "u_int32_t"
-     */
-    u_int32_t	     timeout;		   /* connection timeout time */
-    /* Bug 16510, end */
-} clickpcb_icmp_t;
-
-struct custom_tcp_opt {
-    TAILQ_ENTRY(custom_tcp_opt) next_opt;
-    u_int8_t opt_kind;
-    u_char *opt_value;
-    u_int32_t opt_len;
-};
-
-
-
-/*
- * XXX IMPORTATANT >>>>>> Please read this before modifying clickpcb
- *
- * For now, since click_var.h cannot be included from userland, it is
- * duplicated partially in uproxy_connapi.h
- * Not all of clickpcb is useful to uproxy.. all its needs are for stuff
- * above the splicing section of clickpcb. This part has been duplicated
- * in userland.
- * If you need to modify clickpcb:
- *   - duplicate your changes in smp/uproxy/driver/uproxy_connapi.h
- *   - make your changes just before the "for splicing" comment.. i.e
- *     after "int rexmt_conseq"
- * I realize that this is sub-optimal.. and bad. Eventually, we will
- * separate out the clickpcb definition into its own self contained
- * header which others can include.
- */
-typedef struct clickpcb
-{
-    network_clickpcb_t ncp;
-
-    /* for receiving */
-    /*
-     * The receive buffer is one mbuf chain.  It doesn't have a packet
-     * header, as all the necessary information is in the pcb
-     * structure itself.  The m_nextpkt field should be NULL.
-     *
-     * As a slight optimization, there is a pointer (recv_tail) to the
-     * last mbuf in the chain as well.  Most of the time, incoming
-     * packets will be compared and linked directly to this item.
-     */
-    struct mbuf *recv_head,                    /* start of receive buffer    */
-                *recv_tail;                    /* last data before first gap */
-    /*
-     * The reassembly queue has multiple mbuf chains.  They are sorted
-     * in increasing order of sequence numbers and are linked together
-     * using the m_nextpkt field.
-     * 
-     * When the packet that fills the gap before the reassembly queue
-     * arrives, as many packets as possible are removed from the
-     * reassembly queue and linked together into one chain.  It is
-     * then appended to the end of the receive buffer after removing
-     * the TCP/IP headers.
-     */
-    struct mbuf	*reass_head, *reass_tail;      /* reassembly queue */
-    
-    /*
-     * The receive window looks like the following:
-     *
-     * +-----------------+------------------------+
-     * | data arrived    |                        |
-     * |  but unread     | no data yet            |
-     * |  by application |                        |
-     * +-----------------+------------------------+
-     *  ^                 ^                        ^
-     *  |                 |                        |
-     * recvleftwin       recvnextseq              recvrightwin
-     *
-     * Note that packets in the reassembly queue are in the "no data
-     * yet" area and don't show up here.  The value of recvnextseq
-     * will be sent out as an acknowledgment number for every outgoing
-     * packet.
-     *
-     * Also note that recvnextseq is pointing to the next octet of
-     * data expected, and recvrightwin is pointing to the first octet
-     * of data that will overflow our receive window.
-     */
-    tcp_seq	recvleftwin, recvrightwin;     /* current edges of window  */
-    tcp_seq	recvnextseq;		       /* next seq number expected */
-    tcp_seq	initseq;		       /* init seq number after the three handshake, for ddos*/
-
-    int		dupacks;	       /* number of consecutive duplicate acks */
-
-    /* for sending */
-    /*
-     * The send buffer is a simple mbuf chain.  The m_nextpkt fields
-     * should be NULL.  The first mbuf has a packet header.
-     *
-     * Note only unsent data is in the send buffer.  The mbuf chain
-     * pointed to by send_head holds data from sendnextseq to
-     * sendenddata below.
-     */
-    struct mbuf *send_head,                   /* start of send buffer */
-                *send_tail;                   /* end of send buffer */
-	
-	/*
-	 * The following 2 fields store the mbuf pointer and the offset
-	 * from the start of this mbuf to the start of send_head.
-	 * New data should be sent from somewhere in sendptr.
-	 * This avoid traversal of the entire send buffer every time.
-	 */
-	struct mbuf *sendptr;
-	uint32_t sendptroff;
-
-    /*
-     * The send window looks like the following:
-     *
-     * +-----------------+------------------------+----------------+
-     * | data sent but   |                        |                |
-     * |  unacknowledged | not sent yet           |                |
-     * |  by other end   |                        |                |
-     * +-----------------+------------------------+----------------+
-     *  ^                 ^          ^             ^                ^
-     *  |                 |          |             |                |
-     * sendleftwin       sendnextseq cwnd         sendrightwin     sendenddata
-     *
-     * Note that sendnextseq is pointing to the next octet of data to
-     * be sent, and sendrightwin is pointing to the first octet of
-     * data that will overflow the other end's receive window.
-     * sendnextseq is pointing somewhere inside the send_next mbuf.
-     *
-     * sendenddata is pointing one octet beyond the end of what the
-     * application is written to the send buffer.  If the application
-     * hasn't written enough data to fill up the other end's receive
-     * window, sendenddata can be at the left of sendrightwin.
-     */
-
-    tcp_seq	sendleftwin, sendrightwin;	/* current edges of window */
-    tcp_seq	sendnextseq;			/* next seq number to send */
-    tcp_seq	sendenddata;			/* end of app data */
-
-  /*
-   * The congestion window cwnd. The sender can transmit up to the 
-   * mininum of the congestion window and the receiver's advertised 
-   * window. The congestion window is flow control imposed by the 
-   * sender.
-   */
-        
-     uint32_t     cwnd;                         /* congestion window */
-
-  /*
-   * Slow start threshold. The slow start algorithm is used when
-   * cwnd < ssthresh
-   * Congestion Avoidance is used when     
-   * cwnd > ssthresh
-   */
-
-    uint32_t     ssthresh;                     /* Slow Start threshold */   
- 
-
-    tcp_seq	recovery_point;	       /* loss recovery point */
-
-    uint32_t silent_read_bytes;             /* bytes silently read out  */
-	/*for advance ACL*/
-	void *acl_data;
-	
-    /* for splicing */
-    click_splice_t splice_data;                /* splicing data */
-
-    /* for timers */
-    struct click_callout rexmt_callout;        /* retransmit timer     */
-    int            rexmt_time;                 /* retransmit wait time */
-    int            rexmt_count;                /* retransmit attempts  */
-
-    TIMER_ENTRY(clickpcb) da;		/* queue of delack_timeout entries */
-    int            delack_count;               /* number of pending acks */
-
-    TIMER_ENTRY(clickpcb) app_timer;	/* application timeout */
-
-    TIMER_ENTRY(clickpcb) wp;		/* window probe timer */
-    TIMER_ENTRY(clickpcb) retrans_next;		/* tcp retrans timer */
-    int            retrans_start_time;
-
-    TAILQ_ENTRY(clickpcb) ue;		       /* queue of pending user events */
-    TAILQ_ENTRY(clickpcb) se;		/* queue of pending stack events */
-
-    uint16_t reset_errorcode;
-    /* For shortest response time slb method. */
-    struct timeval pie_start_time;
-
-    struct timeval syn_timestamp;
-
-	/* slb client connection RTT (microsecond) */
-	struct timeval cl_start_time;
-	
-	/* Record the slb connection time */
-	int slb_conn_time;
-
-	int tcp_options_len;
-	void *tcp_options;
-	
-	union {
-		struct in_addr	ip4;
-		struct in6_addr	ip6;
-	} tcp_opt_sourceip;
-	uint16_t tcp_opt_sourceport;
-	uint8_t tcp_opt_source_ip_v6;
-	uint8_t tcp_opt_custom_kind;
-	uint8_t tcp_opt_source_port;
-	uint8_t tcp_opt_custom_kind_offset;
-	uint16_t ssli_dpi_dport;
-	union {
-		struct in_addr	pool4;
-		struct in6_addr pool6;
+#ifndef _CLICK_PCB_H
+#define _CLICK_PCB_H
+#include <click/kern/click_callout.h>
+#include <click/app/cm/sf_var.h>
+
+/* type of PCBs */
+#define PCB_TCP		1
+#define PCB_UDP		2
+#define PCB_PIPE	3
+#define PCB_ICMP	4
+#define CLICKPCB_RETRY 2
+
+#define PCB_SERVER_SIDE(pcb) (pcb->cp_rs)
+#define PCB_CLIENT_SIDE(pcb) (!pcb->cp_rs && pcb->cp_vs)
+
+
+#define PROTOCOL_ALL (PCB_TCP | PCB_UDP | PCB_ICMP)
+#define PROTOCOL_UNKNOWN 0
+
+#ifndef _KERNEL
+	#define MAX_SACK_BLKS	6	/* Max # SACK blocks stored at receiver side */
+	#define CLICKPCB_IPV6		0x00000200
+	#define CLICKPCB_ACL_DENY     0x00080000	
+	#define CLICKPCB_IS_IPV6(pcb) ((pcb)->cp_extflags & CLICKPCB_IPV6)
+	
+	struct eroute_info {
+		uint32_t rule_id;
+		struct eroute_rule *rule;
+	};
+
+#endif
+
+struct clickpcb;
+
+/*
+ * similar like struct sackhole
+ */
+struct click_sackhole {
+	tcp_seq start;		/* start seq no. of hole */
+	tcp_seq end;		/* end seq no. */
+	TAILQ_ENTRY(click_sackhole) scblink;	/* scoreboard linkage */
+};
+
+struct click_sackhint {
+	struct click_sackhole *nexthole;
+	int sack_bytes_rexmit;
+};
+
+
+typedef struct clickpcb2
+{
+    /* TCP Option: WS*/
+    u_char	snd_scale;		/* window scaling for send window */
+    u_char	rcv_scale;		/* window scaling for recv window */
+
+    /* SACK related state */
+	int	snd_numholes;		/* number of holes seen by sender */
+	TAILQ_HEAD(click_sackhole_head, click_sackhole) snd_holes;	/* sorted */
+	tcp_seq	snd_fack;		/* last seq number(+1) sack'd by rcv'r*/
+	tcp_seq	sack_nextrexmt;	/* the highest sequence number + 1
+							   which has been retransmitted during
+							   the current loss recovery phase,
+							   the next rexmt should start from this seq */
+	struct click_sackhint sackhint;
+
+    int	rcv_numsacks;		/* # distinct sack blks present */
+    struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */
+
+	/* support ts option */
+	uint32_t last_ack_sent;/*save the last ack from TM*/
+	uint32_t ts_recent;/* timestamp echo data */
+	uint32_t ts_recent_age;/* when last updated */
+
+	uint32_t t_srtt;/* smoothed round-trip time */
+	uint32_t t_rttvar;/* variance in round-trip time */
+	struct clickpcb *pcb;	/* coreference pcb */
+	TIMER_ENTRY(clickpcb2) ssf;		/* queue of pending ssf slow timeout events */
+	TAILQ_ENTRY(clickpcb2) ssf_send;	/* queue of store ssf send pending event */
+	TAILQ_ENTRY(clickpcb2) ssf_recv;	/* queue of store ssf receive pending event */
+	ssf_tcp_sync_head_t ssf_tcp_sync_head;	/* SSF standby store received SF_APP_TCP_SYNC app_id packet 
+						or SF_TCP_EVENT_SYNC_SEND event_type packet data which is sent by SSF active */
+	ssf_pcb_event_data_head_t ssf_pcb_ssl_event_head; /* SSF standby store SF_APP_SSL app_id event data which is sent by SSF active */					
+	ssf_pcb_event_data_head_t ssf_pcb_http_event_head; /* SSF standby store SF_APP_HTTP app_id event data which is sent by SSF active */
+	uint32_t	ssf_event_seq;
+	uint32_t	ssf_tcp_sync_pkt_num;
+}clickpcb2_t;
+
+/* fields common to all PCBs */
+typedef struct basic_clickpcb
+{
+	uint32_t   bcp_type;                          /* see above for values */
+	uint32_t   ncp_flags;                         /* flags */
+	uint64_t   ncp_extflags;                      /* bug 17757, qiuzj, 20071023 */
+	uint32_t   incarnation_id;                    /* unique per alloc */
+	uint32_t   incomp_conn_incarnation_id;        /* for incomplete conn*/
+	uint32_t   index;                             /* unique pcb index - uproxy */
+	void*      bcp_udata;                         /* application data */
+	int        (*bcp_app)(struct clickpcb *);     /* application handler */
+	int        (*bcp_app_close)(struct clickpcb *);     /* application close handler */
+	clickpcb2_t *bcp_pcb2;
+	TAILQ_ENTRY(basic_clickpcb) bcp_pe; /* queue of pending proxy events */
+	STAILQ_ENTRY(basic_clickpcb) bcp_dq; /* used for L7 uproxy delete queue */
+	/* flag values are defined separately for each PCB type */
+	
+	uint32_t bcp_segment_id;	/* the segment id */
+	uint32_t bcp_segment_inst;	/* the instance id for the segment */
+} basic_clickpcb_t;
+
+/* fields common to all network type PCBs, including TIME_WAIT */
+typedef struct basic_network_clickpcb
+{
+	basic_clickpcb_t bcp;
+	union {
+		struct in_addr   bnc_localip4;
+		struct in6_addr  bnc_localip6;
+	} bnc_local_ip;
+
+	union {
+		struct in_addr		bnc_remoteip4;
+		struct in6_addr	bnc_remoteip6; 
+	}bnc_remote_ip;
+	
+	uint16_t         bnc_localport, bnc_remoteport;
+	uint8_t          bnc_ip_p;                  /* IP protocol */
+	uint8_t          bnc_state;                 /* state for TCP/UDP */
+	uint8_t          bnc_realstate;	            /* real state of TCP */
+	uint8_t		sf_app_id;
+	struct click_hash_node *bnc_node;           /* pointer to container node */
+} basic_network_clickpcb_t;
+
+
+
+#define	bnc_localip bnc_local_ip.bnc_localip4
+#define	bnc_remoteip bnc_remote_ip.bnc_remoteip4
+#define	bnc_localip6 bnc_local_ip.bnc_localip6
+#define	bnc_remoteip6 bnc_remote_ip.bnc_remoteip6
+
+struct _tuxedo_data {
+	uint32_t member_id;
+	uint32_t wsh_port_offset;	
+};
+
+/* this is a vs pcb, and the client is a l4device, 
+ * record the l4device id and send response packet to the l4 device
+ */
+struct _orch_data {
+	uint32_t l4device_id;
+	uint32_t l4device_instance_id;
+};
+
+/* fields common to network type PCBs, not including TIME_WAIT */
+typedef struct network_clickpcb
+{
+	basic_network_clickpcb_t bnc;
+	
+	struct _slb_rs           *ncp_rs;       /* real server for this conn */
+	struct _nat_table        *ncp_nat_table; /* point to the nat item */
+
+	struct _slb_vs           *ncp_vs;       /* virtual server for this conn */
+                                            /* Note: In many cases, ncp_vs is NULL */
+	union {
+		struct _webagent_ws *ncp_ws;       /* webagent service for this conn */
+		void		 *ncp_doh;		/* doh server for this conn */
+	};
+
+	union {
+		struct _tuxedo_data      ncp_tuxedo;
+		struct _orch_data        orch_data;
+	};
+
+	uint32_t                 ncp_nat_inst;  /* for nat item*/
+	uint32_t                 ncp_rs_inst;	/* instance id for real */
+
+	uint32_t                 ncp_vs_inst;
+	
+	uint32_t                 ncp_ws_inst;
+	
+	struct eroute_info       ncp_eroute;    /* extended routing table entry, support both ipv4 and ipv6 */
+	
+/* bug54429,remove unused field of pcb.For ncp_fwif is annotationed by "#if 0" in other plases,so here follow it*/
+#if 0
+	/* Bug 13459, luozy, 20061107*/
+	struct ifnet * ncp_fwif;                /* webwall interface pointer */
+	/*Bug 13459, end*/
+	LIST_ENTRY (clickpcb) ncp_ddpcb; /* dd pcb list */
+#endif
+
+#ifdef _KERNEL	
+	app_timeout_head_t       *ncp_app_head; /* inactivity timer */
+#else
+	void                     *ncp_app_head; /* inactivity timer */
+#endif
+	u_int16_t                ncp_mss;       /* client max segment size */
+	struct ifnet *numa_ifp;
+} network_clickpcb_t;
+
+
+/* pseudo-struct for TIME_WAIT PCBs */
+typedef struct network_clickpcb_and_timewait
+{
+	basic_network_clickpcb_t bnc;
+	struct _slb_vs       *ncp_vs; /* add vs info for spcb */
+} network_clickpcb_and_timewait_t;
+
+/* pseudo-struct for non-network PCBs */
+typedef struct non_network_clickpcb
+{
+	struct {
+		basic_clickpcb_t bcp;
+	} bnc;
+} non_network_clickpcb_t;
+
+typedef struct clickpcb_timewait
+{
+    network_clickpcb_and_timewait_t ncp;
+
+    tcp_seq	recvnextseq;
+    TAILQ_ENTRY(clickpcb_timewait) tw;	        /* queue of TIME_WAIT entries */
+    int	time_wait_expire;               /* amount of time to wait */
+    int time_wait_timer_flag;
+} clickpcb_timewait_t;
+
+
+/* macros for easy access */
+#define cp_pcb2       ncp.bnc.bcp.bcp_pcb2
+#define cp_type       ncp.bnc.bcp.bcp_type
+#define cp_incid      ncp.bnc.bcp.incarnation_id
+#define cp_incomp_conn_incid ncp.bnc.bcp.incomp_conn_incarnation_id
+#define cp_udata      ncp.bnc.bcp.bcp_udata
+#define cp_index      ncp.bnc.bcp.index
+#define cp_app        ncp.bnc.bcp.bcp_app
+#define cp_app_close  ncp.bnc.bcp.bcp_app_close
+#define cp_flags      ncp.bnc.bcp.ncp_flags
+#define cp_extflags   ncp.bnc.bcp.ncp_extflags
+#define cp_localip    ncp.bnc.bnc_localip
+#define cp_remoteip   ncp.bnc.bnc_remoteip
+#define cp_localip6   ncp.bnc.bnc_localip6
+#define cp_remoteip6  ncp.bnc.bnc_remoteip6
+#define cp_localport  ncp.bnc.bnc_localport
+#define cp_remoteport ncp.bnc.bnc_remoteport
+#define cp_ip_p       ncp.bnc.bnc_ip_p
+#define cp_state      ncp.bnc.bnc_state
+#define cp_realstate  ncp.bnc.bnc_realstate
+#define cp_sf_app_id		ncp.bnc.sf_app_id
+#define cp_node       ncp.bnc.bnc_node
+#define cp_rs         ncp.ncp_rs
+#define cp_rs_inst    ncp.ncp_rs_inst
+#define cp_vs         ncp.ncp_vs
+#define cp_vs_inst    ncp.ncp_vs_inst
+#define cp_ws         ncp.ncp_ws
+#define cp_ws_inst    ncp.ncp_ws_inst
+#define cp_tuxedo     ncp.ncp_tuxedo
+#define cp_doh	      ncp.ncp_doh
+
+#define cp_eroute     ncp.ncp_eroute/* for both ipv4 and ipv6 */
+
+#if 0
+/* Bug 13459, luozy, 20061107*/
+#define cp_fwif       ncp.ncp_fwif
+/*Bug 13459, end*/
+#define cp_ddpcb      ncp.ncp_ddpcb
+#endif
+#define cp_app_head   ncp.ncp_app_head
+#define cp_mss        ncp.ncp_mss
+/* the following two are aliases for ICMP */
+#define cp_id         cp_localport
+#define cp_dummy      cp_remoteport
+#define cp_nat_table  ncp.ncp_nat_table
+#define cp_nat_inst   ncp.ncp_nat_inst
+#define cp_segment_id    ncp.bnc.bcp.bcp_segment_id
+#define cp_segment_inst  ncp.bnc.bcp.bcp_segment_inst
+
+/*
+ * Here are the groups of PCBs used in the description below.
+ *
+ *  network - TCP, UDP and ICMP (note this doesn't include TIME_WAIT)
+ *  SLB     - TCP and UDP
+ *
+ * PCB fields shared between structs and their actual use are as follows.
+ *
+ *  basic_clickpcb: all
+ *   type            all
+ *   udata           all
+ *   app             all
+ *   flags           all, but used for different meanings depending on type
+ *
+ *  basic_network_clickpcb: TCP, T_W TCP, UDP and ICMP
+ *   localip         network and T_W TCP
+ *   remoteip        network and T_W TCP
+ *   localport       network and T_W TCP
+ *   remoteport      network and T_W TCP
+ *   ip_p            network and T_W TCP
+ *   state           TCP, T_W TCP and UDP
+ *   realstate       TCP
+ *   node            network and T_W TCP
+ *
+ *  network_clickpcb: TCP, UDP and ICMP 
+ *   rs              SLB
+ *   rs_inst         SLB
+ *   eroute          network
+ *   app_head        TCP (and IP)
+ *   mss             TCP (and IP)
+ */
+
+typedef struct click_splice_data
+{
+    u_int32_t        seq_offset;  /* sequence number offset -
+				     add this to seq# flowing in this direction */
+    struct clickpcb *target;      /* pointer to target (client or server) pcb */
+#if 0
+    u_int16_t        cksum_patch; /* tcp checksum patch */
+    u_int16_t        ipsum_patch; /* ip checksum patch */
+#endif
+} click_splice_t;
+
+typedef struct clickpcb_ippcb
+{
+    network_clickpcb_t ncp;
+} clickpcb_ippcb_t;
+
+struct click_ipfrag {
+    TAILQ_ENTRY(click_ipfrag) next_pcb;
+    TAILQ_ENTRY(click_ipfrag) next_global;
+    struct clickpcb_udp *pcb;
+    int	           last_used;
+    struct in_addr remoteip;
+    struct in_addr localip;
+    struct mbuf	   *pkts; /* buffered packets */
+    uint32_t	   num_pkts; /* Number of buffered packets */
+    /* 32 bit to avoid someone playing with us */
+    uint32_t	   tot_len;
+    uint32_t	   cur_len;
+    uint16_t	   ip_id;
+};
+
+
+typedef struct clickpcb_udp
+{
+    network_clickpcb_t ncp;
+
+    struct mbuf    *packet;
+    struct clickpcb_udp *reverse; /*Other side of UDP connection */
+    /*for ddos slb dns*/
+    struct timeval *ddos_dns_start_time; /*DDOS_DNS_MAX*/
+	int ddos_dns_is_calcu_resptime;
+    /* for timers */
+    struct click_callout timeout_callout;      /* timeout timer     */
+    /* 
+     * Bug 16510, luozy, 20050515 
+     *
+     * "u_int16_t" is not enough 
+     * (65535/HZ = 655 seconds),
+     * change "u_int16_t" to "u_int32_t"
+     */
+    u_int32_t            timeout;              /* connection timeout time */
+    /* Bug 16510, end */
+    TAILQ_HEAD(frags, click_ipfrag) frags;
+    TAILQ_ENTRY(clickpcb_udp) next_server;
+    TAILQ_ENTRY(clickpcb_udp) dq;
+	uint16_t reset_errorcode;
+
+	/* Record slb connection time */
+	int slb_conn_time;
+} clickpcb_udp_t;
+
+
+typedef struct clickpcb_icmp
+{
+    network_clickpcb_t ncp;
+
+    struct mbuf    *packet;
+    struct clickpcb_icmp *reverse; /*Other side of ICMP connection */
+
+
+    /* the number of echorequest without echoreply */
+    int32_t        outstanding_requests;
+
+    /* for timers */
+    struct click_callout timeout_callout;	   /* timeout timer	*/
+    TAILQ_ENTRY(clickpcb_icmp) dq;
+    /* 
+     * Bug 16510, luozy, 20050515 
+     *
+     * "u_int16_t" is not enough 
+     * (65535/HZ = 655 seconds),
+     * change "u_int16_t" to "u_int32_t"
+     */
+    u_int32_t	     timeout;		   /* connection timeout time */
+    /* Bug 16510, end */
+} clickpcb_icmp_t;
+
+struct custom_tcp_opt {
+    TAILQ_ENTRY(custom_tcp_opt) next_opt;
+    u_int8_t opt_kind;
+    u_char *opt_value;
+    u_int32_t opt_len;
+};
+
+
+
+/*
+ * XXX IMPORTATANT >>>>>> Please read this before modifying clickpcb
+ *
+ * For now, since click_var.h cannot be included from userland, it is
+ * duplicated partially in uproxy_connapi.h
+ * Not all of clickpcb is useful to uproxy.. all its needs are for stuff
+ * above the splicing section of clickpcb. This part has been duplicated
+ * in userland.
+ * If you need to modify clickpcb:
+ *   - duplicate your changes in smp/uproxy/driver/uproxy_connapi.h
+ *   - make your changes just before the "for splicing" comment.. i.e
+ *     after "int rexmt_conseq"
+ * I realize that this is sub-optimal.. and bad. Eventually, we will
+ * separate out the clickpcb definition into its own self contained
+ * header which others can include.
+ */
+typedef struct clickpcb
+{
+    network_clickpcb_t ncp;
+
+    /* for receiving */
+    /*
+     * The receive buffer is one mbuf chain.  It doesn't have a packet
+     * header, as all the necessary information is in the pcb
+     * structure itself.  The m_nextpkt field should be NULL.
+     *
+     * As a slight optimization, there is a pointer (recv_tail) to the
+     * last mbuf in the chain as well.  Most of the time, incoming
+     * packets will be compared and linked directly to this item.
+     */
+    struct mbuf *recv_head,                    /* start of receive buffer    */
+                *recv_tail;                    /* last data before first gap */
+    /*
+     * The reassembly queue has multiple mbuf chains.  They are sorted
+     * in increasing order of sequence numbers and are linked together
+     * using the m_nextpkt field.
+     * 
+     * When the packet that fills the gap before the reassembly queue
+     * arrives, as many packets as possible are removed from the
+     * reassembly queue and linked together into one chain.  It is
+     * then appended to the end of the receive buffer after removing
+     * the TCP/IP headers.
+     */
+    struct mbuf	*reass_head, *reass_tail;      /* reassembly queue */
+    
+    /*
+     * The receive window looks like the following:
+     *
+     * +-----------------+------------------------+
+     * | data arrived    |                        |
+     * |  but unread     | no data yet            |
+     * |  by application |                        |
+     * +-----------------+------------------------+
+     *  ^                 ^                        ^
+     *  |                 |                        |
+     * recvleftwin       recvnextseq              recvrightwin
+     *
+     * Note that packets in the reassembly queue are in the "no data
+     * yet" area and don't show up here.  The value of recvnextseq
+     * will be sent out as an acknowledgment number for every outgoing
+     * packet.
+     *
+     * Also note that recvnextseq is pointing to the next octet of
+     * data expected, and recvrightwin is pointing to the first octet
+     * of data that will overflow our receive window.
+     */
+    tcp_seq	recvleftwin, recvrightwin;     /* current edges of window  */
+    tcp_seq	recvnextseq;		       /* next seq number expected */
+    tcp_seq	initseq;		       /* init seq number after the three handshake, for ddos*/
+
+    int		dupacks;	       /* number of consecutive duplicate acks */
+
+    /* for sending */
+    /*
+     * The send buffer is a simple mbuf chain.  The m_nextpkt fields
+     * should be NULL.  The first mbuf has a packet header.
+     *
+     * Note only unsent data is in the send buffer.  The mbuf chain
+     * pointed to by send_head holds data from sendnextseq to
+     * sendenddata below.
+     */
+    struct mbuf *send_head,                   /* start of send buffer */
+                *send_tail;                   /* end of send buffer */
+	
+	/*
+	 * The following 2 fields store the mbuf pointer and the offset
+	 * from the start of this mbuf to the start of send_head.
+	 * New data should be sent from somewhere in sendptr.
+	 * This avoid traversal of the entire send buffer every time.
+	 */
+	struct mbuf *sendptr;
+	uint32_t sendptroff;
+
+    /*
+     * The send window looks like the following:
+     *
+     * +-----------------+------------------------+----------------+
+     * | data sent but   |                        |                |
+     * |  unacknowledged | not sent yet           |                |
+     * |  by other end   |                        |                |
+     * +-----------------+------------------------+----------------+
+     *  ^                 ^          ^             ^                ^
+     *  |                 |          |             |                |
+     * sendleftwin       sendnextseq cwnd         sendrightwin     sendenddata
+     *
+     * Note that sendnextseq is pointing to the next octet of data to
+     * be sent, and sendrightwin is pointing to the first octet of
+     * data that will overflow the other end's receive window.
+     * sendnextseq is pointing somewhere inside the send_next mbuf.
+     *
+     * sendenddata is pointing one octet beyond the end of what the
+     * application is written to the send buffer.  If the application
+     * hasn't written enough data to fill up the other end's receive
+     * window, sendenddata can be at the left of sendrightwin.
+     */
+
+    tcp_seq	sendleftwin, sendrightwin;	/* current edges of window */
+    tcp_seq	sendnextseq;			/* next seq number to send */
+    tcp_seq	sendenddata;			/* end of app data */
+
+  /*
+   * The congestion window cwnd. The sender can transmit up to the 
+   * mininum of the congestion window and the receiver's advertised 
+   * window. The congestion window is flow control imposed by the 
+   * sender.
+   */
+        
+     uint32_t     cwnd;                         /* congestion window */
+
+  /*
+   * Slow start threshold. The slow start algorithm is used when
+   * cwnd < ssthresh
+   * Congestion Avoidance is used when     
+   * cwnd > ssthresh
+   */
+
+    uint32_t     ssthresh;                     /* Slow Start threshold */   
+ 
+
+    tcp_seq	recovery_point;	       /* loss recovery point */
+
+    uint32_t silent_read_bytes;             /* bytes silently read out  */
+	/*for advance ACL*/
+	void *acl_data;
+	
+    /* for splicing */
+    click_splice_t splice_data;                /* splicing data */
+
+    /* for timers */
+    struct click_callout rexmt_callout;        /* retransmit timer     */
+    int            rexmt_time;                 /* retransmit wait time */
+    int            rexmt_count;                /* retransmit attempts  */
+
+    TIMER_ENTRY(clickpcb) da;		/* queue of delack_timeout entries */
+    int            delack_count;               /* number of pending acks */
+
+    TIMER_ENTRY(clickpcb) app_timer;	/* application timeout */
+
+    TIMER_ENTRY(clickpcb) wp;		/* window probe timer */
+    TIMER_ENTRY(clickpcb) retrans_next;		/* tcp retrans timer */
+    int            retrans_start_time;
+
+    TAILQ_ENTRY(clickpcb) ue;		       /* queue of pending user events */
+    TAILQ_ENTRY(clickpcb) se;		/* queue of pending stack events */
+
+    uint16_t reset_errorcode;
+    /* For shortest response time slb method. */
+    struct timeval pie_start_time;
+
+    struct timeval syn_timestamp;
+
+	/* slb client connection RTT (microsecond) */
+	struct timeval cl_start_time;
+	
+	/* Record the slb connection time */
+	int slb_conn_time;
+
+	int tcp_options_len;
+	void *tcp_options;
+	
+	union {
+		struct in_addr	ip4;
+		struct in6_addr	ip6;
+	} tcp_opt_sourceip;
+	uint16_t tcp_opt_sourceport;
+	uint8_t tcp_opt_source_ip_v6;
+	uint8_t tcp_opt_custom_kind;
+	uint8_t tcp_opt_source_port;
+	uint8_t tcp_opt_custom_kind_offset;
+	uint16_t ssli_dpi_dport;
+	union {
+		struct in_addr	pool4;
+		struct in6_addr pool6;
 	} tcp_snat;
 	uint8_t tcp_snat_is_ipv6;
 
@@ -602,84 +604,84 @@
 	TAILQ_HEAD(custom_opt, custom_tcp_opt) custom_opt;
 } clickpcb_t;
 
-typedef struct clickpcb_pipe
-{
-    non_network_clickpcb_t ncp;
-
-    struct	clickpcb_ippcb ippcb;
-    struct	mbuf *recv_head, *recv_tail;
-    struct	clickpcb_pipe *target;
-    TAILQ_ENTRY(clickpcb_pipe) ue;	      /* queue of pending user events */
-    TAILQ_ENTRY(clickpcb_pipe) dq;	      /* queue of pipes to delete */
-    TIMER_ENTRY(clickpcb_pipe) pipe_timeout;  /* inactivity timer */
-#ifdef _KERNEL
-   pipe_app_timeout_head_t  *ncp_app_head; /* pipe inactivity timer */
-#else
-   void                     *ncp_app_head; /* pipe inactivity timer */
-#endif
-
-    tcp_seq	seq;                          /* next seq# to be sent from this side */
-
-	uint32_t sendenddata; /* init to 0 */
-	uint32_t sendrightwin; /* init to pipe_max_buffer */
-    uint32_t silent_read_bytes;           /* bytes silently read out */
-
-    uint16_t reset_errorcode;
-    /* For shortest response time slb method. */
-    struct timeval pie_start_time;
-	struct timeval cl_start_time;
-	/* for splicing */
-	click_splice_t splice_data;                /* splicing data */
-	clickpcb_t *lpcb;
-	TIMER_ENTRY(clickpcb_pipe) retrans_next;   /* pipe retrans timer */
-	int retrans_start_time;
-} clickpcb_pipe_t;
-
-enum {
-	VALID_ARG = 0,
-	INVALID_ARG
-};
-
-/*
- * arguments for clickpcb_uproxy_pcb_delete
- */
-typedef struct uproxy_pcb_delete_arg {
-	int atcpid;
-	uint32_t conn_tcp_total;	/* count for TCP pcb */
-	uint32_t conn_tcp_estab;	/* count for established connection */
-	uint32_t conn_tcp_timewait;	/* count for TIME_WAIT connection */
-} uproxy_pcb_delete_arg_t;
-
-typedef struct conn_oper_list {
-	struct clickpcb *pcb;
-	struct conn_oper_list *next;
-} conn_oper_list_t;
-
-typedef struct conn_oper_arg {
-	void *pcb;
-	uint8_t proto;
-	uint32_t src_ip;
-	uint32_t dst_ip;
-	uint16_t sport;
-	uint16_t dport;
-	uint32_t oper_count;
-	uint32_t tid;
-	conn_oper_list_t *pcb_list;
-} conn_oper_arg_t;
-/* bug 14005, end */
-typedef struct conn_oper_arg6 {
-	void *pcb;
-	uint8_t proto;
-	struct in6_addr src_ip;
-	struct in6_addr dst_ip;
-	uint16_t sport;
-	uint16_t dport;
-	uint32_t oper_count;
-	uint32_t tid;
-	conn_oper_list_t *pcb_list;
-} conn_oper_arg_t6;
-
-void set_pcb_client_option_flags(clickpcb_t *pcb);
-#endif
-
-
+typedef struct clickpcb_pipe
+{
+    non_network_clickpcb_t ncp;
+
+    struct	clickpcb_ippcb ippcb;
+    struct	mbuf *recv_head, *recv_tail;
+    struct	clickpcb_pipe *target;
+    TAILQ_ENTRY(clickpcb_pipe) ue;	      /* queue of pending user events */
+    TAILQ_ENTRY(clickpcb_pipe) dq;	      /* queue of pipes to delete */
+    TIMER_ENTRY(clickpcb_pipe) pipe_timeout;  /* inactivity timer */
+#ifdef _KERNEL
+   pipe_app_timeout_head_t  *ncp_app_head; /* pipe inactivity timer */
+#else
+   void                     *ncp_app_head; /* pipe inactivity timer */
+#endif
+
+    tcp_seq	seq;                          /* next seq# to be sent from this side */
+
+	uint32_t sendenddata; /* init to 0 */
+	uint32_t sendrightwin; /* init to pipe_max_buffer */
+    uint32_t silent_read_bytes;           /* bytes silently read out */
+
+    uint16_t reset_errorcode;
+    /* For shortest response time slb method. */
+    struct timeval pie_start_time;
+	struct timeval cl_start_time;
+	/* for splicing */
+	click_splice_t splice_data;                /* splicing data */
+	clickpcb_t *lpcb;
+	TIMER_ENTRY(clickpcb_pipe) retrans_next;   /* pipe retrans timer */
+	int retrans_start_time;
+} clickpcb_pipe_t;
+
+enum {
+	VALID_ARG = 0,
+	INVALID_ARG
+};
+
+/*
+ * arguments for clickpcb_uproxy_pcb_delete
+ */
+typedef struct uproxy_pcb_delete_arg {
+	int atcpid;
+	uint32_t conn_tcp_total;	/* count for TCP pcb */
+	uint32_t conn_tcp_estab;	/* count for established connection */
+	uint32_t conn_tcp_timewait;	/* count for TIME_WAIT connection */
+} uproxy_pcb_delete_arg_t;
+
+typedef struct conn_oper_list {
+	struct clickpcb *pcb;
+	struct conn_oper_list *next;
+} conn_oper_list_t;
+
+typedef struct conn_oper_arg {
+	void *pcb;
+	uint8_t proto;
+	uint32_t src_ip;
+	uint32_t dst_ip;
+	uint16_t sport;
+	uint16_t dport;
+	uint32_t oper_count;
+	uint32_t tid;
+	conn_oper_list_t *pcb_list;
+} conn_oper_arg_t;
+/* bug 14005, end */
+typedef struct conn_oper_arg6 {
+	void *pcb;
+	uint8_t proto;
+	struct in6_addr src_ip;
+	struct in6_addr dst_ip;
+	uint16_t sport;
+	uint16_t dport;
+	uint32_t oper_count;
+	uint32_t tid;
+	conn_oper_list_t *pcb_list;
+} conn_oper_arg_t6;
+
+void set_pcb_client_option_flags(clickpcb_t *pcb);
+#endif
+
+
