Index: /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/CA-SNMP-MIB.txt
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/CA-SNMP-MIB.txt	(revision 38995)
+++ /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/CA-SNMP-MIB.txt	(working copy)
@@ -5214,37 +5214,38 @@
 
 -- End of ha MIB
 
---- 
---- The information of beijingArrayNetworks's LLB MIB. 
---- 
-llb   OBJECT IDENTIFIER ::= { beijingArrayNetworks 34 } 
---llbGeneral		OBJECT IDENTIFIER ::= { llb 1 } 
-llbStats		OBJECT IDENTIFIER ::= { llb 2 } 
+---
+--- The information of beijingArrayNetworks's LLB MIB.
+---
+llb   OBJECT IDENTIFIER ::= { beijingArrayNetworks 34 }
+--llbGeneral		OBJECT IDENTIFIER ::= { llb 1 }
+llbStats		OBJECT IDENTIFIER ::= { llb 2 }
 linkStats		OBJECT IDENTIFIER ::= { llbStats 1 }
+natStats		OBJECT IDENTIFIER ::= { llbStats 2 }
 
-linkCount	OBJECT-TYPE 
-		SYNTAX		Integer32 	
+linkCount	OBJECT-TYPE
+		SYNTAX		Integer32
 		MAX-ACCESS	read-only
 		STATUS		current
-		DESCRIPTION "The number of link route." 
-		::= { linkStats 1 } 
-linkStatsTable	OBJECT-TYPE 
+		DESCRIPTION "The number of link route."
+		::= { linkStats 1 }
+linkStatsTable	OBJECT-TYPE
 		SYNTAX		SEQUENCE OF LinkStatsEntry
 		MAX-ACCESS	not-accessible
 		STATUS          current
-		DESCRIPTION "Link route status table." 
-		::= { linkStats 2 } 
-linkStatsEntry  OBJECT-TYPE 
+		DESCRIPTION "Link route status table."
+		::= { linkStats 2 }
+linkStatsEntry  OBJECT-TYPE
 		SYNTAX		LinkStatsEntry
 		MAX-ACCESS	not-accessible
 		STATUS		current
-		DESCRIPTION "A linkStatsTable entry containing status for one link." 
-		INDEX  { linkIndex }	
-		::= { linkStatsTable 1 } 
-LinkStatsEntry       ::= SEQUENCE { 
+		DESCRIPTION "A linkStatsTable entry containing status for one link."
+		INDEX  { linkIndex }
+		::= { linkStatsTable 1 }
+LinkStatsEntry       ::= SEQUENCE {
 		linkIndex       Integer32,
 		linkName        DisplayString,
-		linkGateway     DisplayString,		
+		linkGateway     DisplayString,
 		linkStatus      DisplayString,
 		linkRespTime	DisplayString,
 		linkUpTime	DisplayString,
@@ -5257,7 +5258,7 @@
 		linkConn	Integer32,
 		linkUsage	Integer32,
 		linkDownEvent	DisplayString} 
-linkIndex	OBJECT-TYPE 
+linkIndex	OBJECT-TYPE
 		SYNTAX	       Integer32
 		MAX-ACCESS     read-only
 		STATUS	       current
@@ -5347,6 +5348,84 @@
 		STATUS	       current
 		DESCRIPTION "Link route usage."
 		::= { linkStatsEntry 15 }
+
+natStatsCount	OBJECT-TYPE
+		SYNTAX		Integer32
+		MAX-ACCESS	read-only
+		STATUS		current
+		DESCRIPTION "The number of natted connections."
+		::= { natStats 1 }
+natStatsTable	OBJECT-TYPE
+		SYNTAX		SEQUENCE OF natStatsEntry
+		MAX-ACCESS	not-accessible
+		STATUS          current
+		DESCRIPTION "NAT connection table."
+		::= { natStats 2 }
+natStatsEntry  OBJECT-TYPE
+		SYNTAX		natStatsEntry
+		MAX-ACCESS	not-accessible
+		STATUS		current
+		DESCRIPTION "A natStatsTable entry containing information for one natted connection."
+		INDEX  { natIndex }
+		::= { natStatsTable 1 }
+natStatsEntry       ::= SEQUENCE {
+		natIndex       Integer32,
+		natSourceIP    DisplayString,
+		natLocalIP     DisplayString,
+		natTargetIP    DisplayString,
+                natSourcePort  INTEGER,
+                natLocalPort   INTEGER,
+                natTargetPort  INTEGER}
+
+natIndex	OBJECT-TYPE
+		SYNTAX	       Integer32
+		MAX-ACCESS     read-only
+		STATUS	       current
+		DESCRIPTION "A unique value for each natted connection."
+                ::= { natStatsEntry 1 }
+
+natSourceIP     OBJECT-TYPE
+                SYNTAX         DisplayString
+                MAX-ACCESS     read-only
+                STATUS         current
+                DESCRIPTION "Source IP of this connection to be natted"
+                ::= { natStatsEntry 2 }
+
+natLocalIP      OBJECT-TYPE
+                SYNTAX         DisplayString
+                MAX-ACCESS     read-only
+                STATUS         current
+                DESCRIPTION "NAT IP of this connection"
+                ::= { natStatsEntry 3 }
+
+natTargetIP     OBJECT-TYPE
+                SYNTAX         DisplayString
+                MAX-ACCESS     read-only
+                STATUS         current
+                DESCRIPTION "Destination IP of this connection"
+                ::= { natStatsEntry 4 }
+
+natSourcePort   OBJECT-TYPE
+                SYNTAX              INTEGER(0..65535)
+                MAX-ACCESS          read-only
+                STATUS              current
+                DESCRIPTION "Source port of this connection to be natted"
+                ::= { natStatsEntry 5 }
+
+natLocalPort    OBJECT-TYPE
+                SYNTAX              INTEGER(0..65535)
+                MAX-ACCESS          read-only
+                STATUS              current
+                DESCRIPTION "NAT port of this connection"
+                ::= { natStatsEntry 6 }
+
+natTargetPort   OBJECT-TYPE
+                SYNTAX              INTEGER(0..65535)
+                MAX-ACCESS          read-only
+                STATUS              current
+                DESCRIPTION "Destination port of this connection"
+                ::= { natStatsEntry 7 }
+
 -- End of LLB MIB
 
 ---
Index: /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.h
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.h	(revision 38995)
+++ /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.h	(working copy)
@@ -9,6 +9,7 @@
 void init_llbMIB(void);
 FindVarMethod var_llbMIB;
 FindVarMethod var_linkStatusTable;
-
+FindVarMethod var_natTableCount;
+FindVarMethod var_natTable;
 #endif /* LLBMIB_H */
 
Index: /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.c	(revision 38995)
+++ /branches/rel_apv_10_7/usr/click/lib/libca_snmp_mib/llbMIB.c	(working copy)
@@ -14,6 +14,7 @@
 #include <netinet/tcp_fsm.h>
 #include <click/app/kernelapi/kernelapi.h>
 #include <click/netinet/click_utils.h>
+#include <click/netinet/click_pcb.h>
 #include "netsnmp_common.h"
 #include "llb_snmp.h"
 
@@ -86,6 +87,30 @@
 #define LKUSAGE		15
 {LKUSAGE,  ASN_INTEGER,  NETSNMP_OLDAPI_RONLY,
  var_linkStatusTable, 5,  { 2,1,2,1,15 }},
+#define NATTABLECOUNT 1
+{NATTABLECOUNT, ASN_INTEGER,  NETSNMP_OLDAPI_RONLY,
+var_natTableCount, 3, {2,2,1}},
+#define NATINDEX        1
+{NATINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,1}},
+#define NATSRCIP        2
+{NATSRCIP, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,2}},
+#define NATLOCALIP      3
+{NATLOCALIP, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,3}},
+#define NATTARGETIP     4
+{NATTARGETIP, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,4}},
+#define NATSRCPORT      5
+{NATSRCPORT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,5}},
+#define NATLOCALPORT    6
+{NATLOCALPORT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,6}},
+#define NATTARGETPORT   7
+{NATTARGETPORT, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+var_natTable,5,{2,2,2,1,7}},
 };
 
 /** Initializes the llbMIB module */
@@ -101,6 +126,28 @@
 
     /* place any other initialization junk you need here */
 }
+unsigned char *
+var_natTableCount(struct variable *vp,
+                oid     *name,
+                size_t  *length,
+                int     exact,
+                size_t  *var_len,
+                WriteMethod **write_method)
+{
+    /* variables we may use later */
+    static long long_ret;
+    if (header_generic(vp,name,length,exact,var_len,write_method)
+                                  == MATCH_FAILED )
+       return NULL;
+    switch(vp->magic) {
+    case NATTABLECOUNT:
+        long_ret = clickpcb_show_nat_count();
+        return (u_char *)&long_ret;
+    default:
+        ERROR_MSG("");
+    }
+    return NULL;
+}
 
 /*
  * var_llbMIB():
@@ -260,5 +307,103 @@
     return NULL;
 }
 
+unsigned char *
+var_natTable(struct variable *vp,
+            oid     *name,
+            size_t  *length,
+            int     exact,
+            size_t  *var_len,
+            WriteMethod **write_method)
+{
+    /* variables we may use later */
+    static long long_ret;
+    static unsigned char result[SPRINT_MAX_LEN];
+    int idx, nat_table_count;
+    char *ipadrs = NULL;
+    int *port_ptr = NULL;
+    static int port;
+    uint32_t buflen;
+    nat_table_count = clickpcb_show_nat_count();
+    if (header_simple_table(vp,name,length,exact,var_len,write_method,nat_table_count)
+                                                == MATCH_FAILED )
+    return NULL;
+
+    idx = name[*length - 1];
+
+    /* this is where we do the value assignments for the mib results.*/
+    switch(vp->magic) {
+    case NATINDEX:
+        long_ret = idx;
+        return (u_char *)&long_ret;
+    case NATSRCIP:
+        clickpcb_get_nat_details(idx, NAT_SRC_IP, &ipadrs, (int32_t *) var_len);
+        if (ipadrs == NULL) {
+            result[0] = '\0';
+            *var_len = 0;
+        } else {
+            strlcpy(result, ipadrs, SPRINT_MAX_LEN);
+            free(ipadrs);
+            ipadrs = NULL;
+        }
+        return (u_char *)result;
+    case NATLOCALIP:
+        clickpcb_get_nat_details(idx, NAT_LOCAL_IP, &ipadrs, (int32_t *) var_len);
+        if (ipadrs == NULL) {
+            result[0] = '\0';
+            *var_len = 0;
+        } else {
+            strlcpy(result, ipadrs, SPRINT_MAX_LEN);
+            free(ipadrs);
+            ipadrs = NULL;
+        }
+        return (u_char *)result;
+
+    case NATTARGETIP:
+        clickpcb_get_nat_details(idx, NAT_TARGET_IP, &ipadrs, (int32_t *) var_len);
+        if (ipadrs == NULL) {
+            result[0] = '\0';
+            *var_len = 0;
+        } else {
+            strlcpy(result, ipadrs, SPRINT_MAX_LEN);
+            free(ipadrs);
+            ipadrs = NULL;
+        }
+        return (u_char *)result;
+
+    case NATSRCPORT:
+        clickpcb_get_nat_details(idx, NAT_SRC_PORT, (void **)&port_ptr, &buflen);
+        if (port_ptr == NULL) {
+            return (u_char*)0;
+        } else {
+            port = *port_ptr;
+            free(port_ptr);
+            port_ptr = NULL;
+            return (u_char*)&port;
+        }
+    case NATLOCALPORT:
+        clickpcb_get_nat_details(idx, NAT_LOCAL_PORT,(void **)&port_ptr, &buflen);
+        if (port_ptr == NULL) {
+            return (u_char*)0;
+        } else {
+            port = *port_ptr;
+            free(port_ptr);
+            port_ptr = NULL;
+            return (u_char*)&port;
+        }
+    case NATTARGETPORT:
+        clickpcb_get_nat_details(idx, NAT_TARGET_PORT, (void **)&port_ptr, &buflen);
+        if (port_ptr == NULL) {
+            return (u_char*)0;
+        } else {
+            port = *port_ptr;
+            free(port_ptr);
+            port_ptr = NULL;
+            return (u_char*)&port;
+        }
+    default:
+        ERROR_MSG("");
+    }
+    return NULL;
+}
 
 
Index: /branches/rel_apv_10_7/usr/click/lib/libkernelapi/addCommands.pm
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libkernelapi/addCommands.pm	(revision 38995)
+++ /branches/rel_apv_10_7/usr/click/lib/libkernelapi/addCommands.pm	(working copy)
@@ -12485,7 +12485,24 @@
 		function_args => [ 
             {type => "OUTDATA"}, 
         ],
-	}
+	},
+         {
+                cmd_attribute => "CMD_KERN_API|CMD_KAPI_NOLOCK",
+                function_name => "clickpcb_get_nat_details",
+                function_args => [
+                        {type => "U32"},
+                        {type => "U32"},
+                        {type => "OUTDATA"},
+        ],
+        },
+        {
+                cmd_attribute => "CMD_KERN_API|CMD_KAPI_NOLOCK",
+                function_name => "clickpcb_show_nat_count",
+                function_args => [
+        ],
+        }
+
+
 );
 
 # This method is required to expost the command table to the caller.
Index: /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.h
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.h	(revision 38995)
+++ /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.h	(working copy)
@@ -680,6 +680,16 @@
 } conn_oper_arg_t6;
 
 void set_pcb_client_option_flags(clickpcb_t *pcb);
+
+typedef enum {
+        NAT_SRC_IP,
+        NAT_LOCAL_IP,
+        NAT_TARGET_IP,
+        NAT_SRC_PORT,
+        NAT_LOCAL_PORT,
+        NAT_TARGET_PORT
+} nat_attr_e;
+
 #endif
 
 
Index: /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.c
===================================================================
--- /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.c	(revision 38995)
+++ /branches/rel_apv_10_7/usr/src/sys/click/netinet/click_pcb.c	(working copy)
@@ -7150,6 +7150,277 @@
 	
 	return(0);
 }
+static uint32_t max_foreachPCB_stack = 2048;
+SYSCTL_INT(_net_inet_clicktcp, OID_AUTO, max_foreachPCB_stack, CTLFLAG_RW,
+           &max_foreachPCB_stack, 0, "click_foreachTreeIndex: max stack");
+
+int
+get_nat_table_details(clickpcb_t *pcb, uint32_t idx, uint32_t nat_attr_type, int *count_ptr, void **buf, int* len)
+{
+    int isipv6;
+    clickpcb_t *tpcb;
+    int expire_time = 0;
+    char *ipadrs = NULL;
+    int *port = NULL;
+    if (!pcb || !((pcb->cp_flags & CLICKPCB_STATIC_NAT) || (pcb->cp_extflags & CLICKPCB_PORT_NAT)))
+        return 0;
+    if (pcb->cp_flags & CLICKPCB_SPLICE_CLIENT) {
+        if (pcb->cp_flags & CLICKPCB_TIMEWAIT) {
+            return 0;
+        }
+        tpcb = pcb->splice_data.target;
+        if (pcb->cp_app_head) {
+            expire_time = TIMER_EXPIRES_IN(pcb, pcb->cp_app_head, app_timer)/hz;
+        } else if (tpcb->cp_app_head) {
+            expire_time = TIMER_EXPIRES_IN(tpcb, tpcb->cp_app_head, app_timer)/hz;
+        }
+    } else if ((pcb->cp_type == PCB_UDP) && pcb->cp_flags & CLICKPCB_UDP_CLIENT) {
+        tpcb = (clickpcb_t*)((clickpcb_udp_t*)pcb)->reverse;
+        expire_time = (((clickpcb_udp_t *)pcb)->timeout_callout.c_time - ticks)/hz;
+    } else if ((pcb->cp_type == PCB_ICMP) && pcb->cp_flags & CLICKPCB_ICMP_CLIENT) {
+        tpcb = (clickpcb_t*)((clickpcb_icmp_t*)pcb)->reverse;
+        expire_time = (((clickpcb_icmp_t *)pcb)->timeout_callout.c_time - ticks)/hz;
+    } else {
+        return 0;
+    }
+    if (!tpcb) {
+        return 0;
+    }
+    if (expire_time < 0) {
+        expire_time = 0;
+    }
+
+    (*count_ptr)++;
+    if (*count_ptr < idx) {
+        return 0;
+    }
+    /*current index is the required pcb index. Based on nat attribute type, update buffer with corresponding nat detail*/
+    isipv6 = pcb->cp_extflags & CLICKPCB_IPV6;
+    if (nat_attr_type == NAT_SRC_IP) {
+        MALLOC(ipadrs, char *, INET6_ADDRSTRLEN, M_TEMP, M_NOWAIT | M_ZERO);
+        if (ipadrs == NULL) {
+            return 0;
+        }
+        if (isipv6) {
+            inet_ntop(AF_INET6, &pcb->cp_remoteip6, ipadrs, INET6_ADDRSTRLEN);
+        } else {
+            inet_ntop(AF_INET, &pcb->cp_remoteip, ipadrs, INET6_ADDRSTRLEN);
+        }
+        *buf = ipadrs;
+        *len = snprintf(NULL, 0, "%s", ipadrs);
+    } else if (nat_attr_type == NAT_LOCAL_IP) {
+        MALLOC(ipadrs, char *, INET6_ADDRSTRLEN, M_TEMP, M_NOWAIT | M_ZERO);
+        if (ipadrs == NULL) {
+            return 0;
+        }
+        if (isipv6) {
+            inet_ntop(AF_INET6, &tpcb->cp_localip6, ipadrs, INET6_ADDRSTRLEN);
+        } else {
+            inet_ntop(AF_INET, &tpcb->cp_localip, ipadrs, INET6_ADDRSTRLEN);
+        }
+        *buf = ipadrs;
+        *len = snprintf(NULL, 0, "%s", ipadrs);
+    } else if (nat_attr_type == NAT_TARGET_IP) {
+        MALLOC(ipadrs, char *, INET6_ADDRSTRLEN, M_TEMP, M_NOWAIT | M_ZERO);
+        if (ipadrs == NULL) {
+            return 0;
+        }
+        if (isipv6) {
+             inet_ntop(AF_INET6, &tpcb->cp_remoteip6, ipadrs, INET6_ADDRSTRLEN);
+        } else {
+             inet_ntop(AF_INET, &tpcb->cp_remoteip, ipadrs, INET6_ADDRSTRLEN);
+        }
+        *buf = ipadrs;
+        *len = snprintf(NULL, 0, "%s", ipadrs);
+    } else if (nat_attr_type == NAT_SRC_PORT) {
+       MALLOC(port, int *, sizeof(int), M_TEMP, M_NOWAIT|M_ZERO);
+       if (port == NULL) {
+            return 0;
+       }
+       *port = pcb->cp_remoteport;
+       *buf = port;
+       *len = sizeof(int);
+    } else if (nat_attr_type == NAT_LOCAL_PORT) {
+       MALLOC(port, int *, sizeof(int), M_TEMP, M_NOWAIT|M_ZERO);
+       if (port == NULL) {
+            return 0;
+       }
+       *port = (pcb->cp_type == PCB_ICMP) ? ntohs(tpcb->cp_localport) : tpcb->cp_localport;
+       *buf = port;
+       *len = sizeof(int);
+    } else if (nat_attr_type == NAT_TARGET_PORT) {
+       MALLOC(port, int *, sizeof(int), M_TEMP, M_NOWAIT|M_ZERO);
+       if (port == NULL) {
+            return 0;
+       }
+       *port = tpcb->cp_remoteport;
+       *buf = port;
+       *len = sizeof(int);
+    } else {
+       return 0;
+    }
+    return 1;
+}
+int
+getdetail_for_each_index(click_hash_node_t *node, uint32_t idx, uint32_t nat_attr_type, int *count_ptr, void **buf, int *len){
+        click_hash_node_t *temp_node, **node_list ;
+        int max_ns, i;
+        int count;
+        max_ns = max_foreachPCB_stack;
+        MALLOC(node_list, click_hash_node_t **, sizeof(click_hash_node_t *)*max_ns, M_TEMP, M_NOWAIT);
+        if (node_list == NULL) {
+            printf("getdetail_for_each_index: Malloc [%d] fail\n", max_ns);
+            return 0;
+        }
+
+        i = 0;
+        temp_node = node;
+        do {
+            while (temp_node != NULL) {
+                if (i == max_ns) {
+                    break;
+                }
+                node_list[i++] = temp_node;
+                temp_node = temp_node->left;
+            }
+
+            if (i > 0) {
+                temp_node = node_list[--i];
+                if (get_nat_table_details(temp_node->pcb, idx, nat_attr_type, count_ptr, buf, len)) {
+                    FREE(node_list, M_TEMP);
+                    return 1;
+                }
+                temp_node = temp_node->right;
+            }
+        } while (i > 0 || temp_node);
+
+        FREE(node_list, M_TEMP);
+        return 0;
+}
+
+void
+update_nat_table_count(clickpcb_t *pcb,int *count_ptr)
+{
+        int isipv6;
+        clickpcb_t *tpcb;
+        int expire_time = 0;
+        if (!pcb || !((pcb->cp_flags & CLICKPCB_STATIC_NAT) || (pcb->cp_extflags & CLICKPCB_PORT_NAT)))
+            return ;
+        if (pcb->cp_flags & CLICKPCB_SPLICE_CLIENT) {
+            if (pcb->cp_flags & CLICKPCB_TIMEWAIT) {
+                return ;
+            }
+            tpcb = pcb->splice_data.target;
+            if (pcb->cp_app_head) {
+                expire_time = TIMER_EXPIRES_IN(pcb, pcb->cp_app_head, app_timer)/hz;
+            } else if (tpcb->cp_app_head) {
+                expire_time = TIMER_EXPIRES_IN(tpcb, tpcb->cp_app_head, app_timer)/hz;
+            }
+        } else if ((pcb->cp_type == PCB_UDP) && pcb->cp_flags & CLICKPCB_UDP_CLIENT) {
+            tpcb = (clickpcb_t*)((clickpcb_udp_t*)pcb)->reverse;
+            expire_time = (((clickpcb_udp_t *)pcb)->timeout_callout.c_time - ticks)/hz;
+        } else if ((pcb->cp_type == PCB_ICMP) && pcb->cp_flags & CLICKPCB_ICMP_CLIENT) {
+            tpcb = (clickpcb_t*)((clickpcb_icmp_t*)pcb)->reverse;
+            expire_time = (((clickpcb_icmp_t *)pcb)->timeout_callout.c_time - ticks)/hz;
+        } else {
+            return ;
+        }
+        if (!tpcb) {
+            return ;
+        }
+        if (expire_time < 0) {
+            expire_time = 0;
+        }
+        (*count_ptr)++;
+}
+int
+updatecount_for_eachindex(click_hash_node_t *node, int *count_ptr)
+{
+            click_hash_node_t *temp_node, **node_list;
+            int max_ns, i;
+            max_ns = max_foreachPCB_stack;
+            MALLOC(node_list, click_hash_node_t **, sizeof(click_hash_node_t *)*max_ns, M_TEMP, M_NOWAIT);
+            if (node_list == NULL) {
+                printf("updatecount_for_eachindex: Malloc [%d] fail\n", max_ns);
+                return 0;
+            }
+            i = 0;
+            temp_node = node;
+            do {
+                while (temp_node != NULL) {
+                    if (i == max_ns) {
+                        break;
+                    }
+                    node_list[i++] = temp_node;
+                    temp_node = temp_node->left;
+                }
+                if (i > 0) {
+                    temp_node = node_list[--i];
+                    /* update count for each node*/
+                    update_nat_table_count(temp_node->pcb, count_ptr);
+                    temp_node = temp_node->right;
+                }
+            } while (i > 0 || temp_node);
+            FREE(node_list, M_TEMP);
+            return 0;
+}
+
+int
+clickpcb_show_nat_count(void *cp)
+{
+        int thread;
+        int curr_ind = 0;
+        /* update count for ipv4 connections */
+        for (thread = 0; thread < atcp_nthreads; thread++) {
+            click_hash_key_t index;
+            for (index = 0; index < CLICK_HASH_TABLE_SIZE; index++) {
+                if (atcp_adapter_array[thread]->atcp_click_conn_table[index].root) {
+                    updatecount_for_eachindex(atcp_adapter_array[thread]->atcp_click_conn_table[index].root, &curr_ind);
+                 }
+            }
+        }
+        /* update count for ipv6 connections */
+        for (thread = 0; thread < atcp_nthreads; thread++) {
+            click_hash_key_t index;
+            for (index = 0; index < CLICK_HASH_TABLE_SIZE; index++) {
+                if (atcp_adapter_array[thread]->atcp_click6_conn_table[index].root) {
+                    updatecount_for_eachindex(atcp_adapter_array[thread]->atcp_click6_conn_table[index].root, &curr_ind);
+                 }
+            }
+        }
+        return curr_ind;
+}
+int
+clickpcb_get_nat_details(void *pcb, uint32_t idx, uint32_t nat_attr_type, void **buf, int *len)
+{
+        *buf = NULL;
+        *len = 0;
+        int thread;
+        int curr_ind = 0;
+        /* get nat details for ipv4 connections */
+        for (thread = 0; thread < atcp_nthreads; thread++) {
+            click_hash_key_t index;
+            for (index = 0; index < CLICK_HASH_TABLE_SIZE; index++) {
+                if (atcp_adapter_array[thread]->atcp_click_conn_table[index].root) {
+                      if (getdetail_for_each_index(atcp_adapter_array[thread]->atcp_click_conn_table[index].root, idx, nat_attr_type, &curr_ind, buf, len)) {
+                           return 1;
+                      }
+                }
+           }
+        }
+        /* get nat details for ipv6 connections */
+        for (thread = 0; thread < atcp_nthreads; thread++) {
+            click_hash_key_t index;
+            for (index = 0; index < CLICK_HASH_TABLE_SIZE; index++) {
+                if (atcp_adapter_array[thread]->atcp_click6_conn_table[index].root) {
+                      if (getdetail_for_each_index(atcp_adapter_array[thread]->atcp_click6_conn_table[index].root, idx, nat_attr_type, &curr_ind, buf, len)) {
+                           return 1;
+                      }
+                }
+           }
+        }
+        return 0;
+}
 
 void
 fasttcp_show_conn_detail(void *n, void *arg)
