[Feature] add GA346 baseline version

Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/extended/hw_nat/Makefile b/src/extended/hw_nat/Makefile
new file mode 100644
index 0000000..dc0f303
--- /dev/null
+++ b/src/extended/hw_nat/Makefile
@@ -0,0 +1,52 @@
+ifeq ($(CONFIG_SUPPORT_OPENWRT),y)
+EXEC = hwnat
+
+HWNAT_OBJS = hw_nat.o hwnat_api.o util.o
+
+all: $(EXEC)
+
+hwnat: $(HWNAT_OBJS) $(CONF_H)
+	$(CC) $(LDFLAGS) -o $@ $(HWNAT_OBJS) 
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
+
+else #CONFIG_SUPPORT_OPENWRT
+
+EXEC = hw_nat 
+
+HWNAT_OBJS = hw_nat.o hwnat_api.o util.o
+
+ifeq ($(CONFIG_GLIBC_2_20),y)
+
+ifneq ($(KERNEL_HEADERS),)
+CONF_H = $(ROOTDIR)/$(KERNEL_HEADERS)/include/linux/autoconf.h
+KERNEL_H = $(ROOTDIR)/$(KERNEL_HEADERS)/include
+else
+CONF_H = $(ROOTDIR)/$(LINUXDIR)/include/linux/autoconf.h
+KERNEL_H = $(ROOTDIR)/$(LINUXDIR)/include
+endif
+CFLAGS = -I$(KERNEL_H) -DRT3052_SUPPORT
+CFLAGS += -I$(ROOTDIR)/$(LINUXDIR)/net/nat/hw_nat 
+CFLAGS += -I$(ROOTDIR)/$(LINUXDIR)/drivers/net/ethernet/raeth
+else
+
+CONF_H  = $(ROOTDIR)/$(LINUXDIR)/include/linux/autoconf.h
+CFLAGS += -I$(ROOTDIR)/$(LINUXDIR)/net/nat/hw_nat
+CFLAGS += -I$(ROOTDIR)/$(LINUXDIR)/drivers/net/ethernet/raeth
+endif
+CFLAGS += -I$(ROOTDIR)/config/
+ccflags-y += -I../../../config/
+
+all: $(EXEC)
+
+hw_nat: $(HWNAT_OBJS) $(CONF_H)
+	$(CC) $(LDFLAGS) -o $@ $(HWNAT_OBJS) 
+
+romfs:
+	$(ROMFSINST) /bin/hw_nat
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
+endif #CONFIG_SUPPORT_OPENWRT
+
diff --git a/src/extended/hw_nat/ac.c b/src/extended/hw_nat/ac.c
new file mode 100644
index 0000000..607ccfe
--- /dev/null
+++ b/src/extended/hw_nat/ac.c
@@ -0,0 +1,260 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include "ac_ioctl.h"
+#include "ac_api.h"
+
+void show_usage(void)
+{
+
+    printf("Add Mac Upload Accounting Rule\n");
+    printf("ac -a -m [Mac] \n");
+
+    printf("Add Mac Download Accounting Rule\n");
+    printf("ac -b -m [Mac] \n");
+    
+    printf("Del Mac Upload Accounting Rule\n");
+    printf("ac -c -m [Mac]\n");
+    
+    printf("Del Mac download Accounting Rule\n");
+    printf("ac -d -m [Mac]\n");
+
+    printf("Add Vlan Upload Accounting Rule\n");
+    printf("ac -A -k [Vlan] \n");
+
+    printf("Add Vlan Download Accounting Rule\n");
+    printf("ac -B -k [Vlan] \n");
+    
+    printf("Del Vlan Upload Accounting Rule\n");
+    printf("ac -C -k [Vlan]\n");
+    
+    printf("Del Vlan download Accounting Rule\n");
+    printf("ac -D -k [Vlan]\n");
+    
+    printf("Add IP Upload Accounting Rule\n");
+    printf("ac -e -i [IpS] -j [IpE]\n");
+    
+    printf("Add IP Download Accounting Rule\n");
+    printf("ac -f -i [IpS] -j [IpE] \n");
+
+    printf("Del IP Upload Accounting Rule\n");
+    printf("ac -g -i [IpS] -j [IpE] \n");
+
+    printf("Del IP Download Accounting Rule\n");
+    printf("ac -h -i [IpS] -j [IpE]\n");
+
+    printf("Show Upload Packet Count of the Mac\n");
+    printf("ac -p -m [Mac] \n");
+    
+    printf("Show Download Packet Count of the Mac\n");
+    printf("ac -q -m [Mac]\n");
+    
+    printf("Show Upload Byte Count of the Mac\n");
+    printf("ac -r -m [Mac]\n");
+    
+    printf("Show Download Byte Count of the Mac\n");
+    printf("ac -s -m [Mac]\n");
+
+    printf("Show Upload Packet Count of the Vlan\n");
+    printf("ac -P -k [Vlan] \n");
+    
+    printf("Show Download Packet Count of the Vlan\n");
+    printf("ac -Q -k [Vlan]\n");
+    
+    printf("Show Upload Byte Count of the Vlan\n");
+    printf("ac -R -k [Vlan]\n");
+    
+    printf("Show Download Byte Count of the Vlan\n");
+    printf("ac -S -k [Vlan]\n");
+
+    printf("Show Upload Packet Count of the IP\n");
+    printf("ac -t -i [IpS] -j [IpE]\n");
+    
+    printf("Show Download Packet Count of the IP\n");
+    printf("ac -u -i [IpS] -j [IpE]\n");
+    
+    printf("Show Upload Byte Count of the IP\n");
+    printf("ac -v -i [IpS] -j [IpE]\n");
+    
+    printf("Show Download Byte Count of the IP\n");
+    printf("ac -w -i [IpS] -j [IpE]\n");
+
+    printf("Clear Ac Table\n");
+    printf("ac -z\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+    int opt;
+    char options[] = "ABCDabcdefghPQRSpqrstuvwz?m:i:j:k:";
+    int fd;
+    int method=-1;
+    struct ac_args args;
+    int result;
+
+
+    fd = open("/dev/"AC_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"AC_DEVNAME);
+	return 0;
+    }
+
+    if(argc < 2) {
+	show_usage();
+        close(fd);
+	return 0;
+    }
+
+    while ((opt = getopt (argc, argv, options)) != -1) {
+	switch (opt) {
+	case 'a':  
+	    method=AC_ADD_MAC_UL_ENTRY;
+	    break;
+	case 'b':  
+	    method=AC_ADD_MAC_DL_ENTRY;
+	    break;
+	case 'c': 
+	    method=AC_DEL_MAC_UL_ENTRY;
+	    break;
+	case 'd': 
+	    method=AC_DEL_MAC_DL_ENTRY;
+	    break;
+	case 'e': 
+	    method=AC_ADD_IP_UL_ENTRY;
+	    break;
+	case 'f': 
+	    method=AC_ADD_IP_DL_ENTRY;
+	    break;
+	case 'g': 
+	    method=AC_DEL_IP_UL_ENTRY;
+	    break;
+	case 'h': 
+	    method=AC_DEL_IP_DL_ENTRY;
+	    break;
+	case 'A':  
+	    method=AC_ADD_VLAN_UL_ENTRY;
+	    break;
+	case 'B':  
+	    method=AC_ADD_VLAN_DL_ENTRY;
+	    break;
+	case 'C': 
+	    method=AC_DEL_VLAN_UL_ENTRY;
+	    break;
+	case 'D': 
+	    method=AC_DEL_VLAN_DL_ENTRY;
+	    break;
+	case 'p': 
+	    method=AC_GET_MAC_UL_PKT_CNT;
+	    break;
+	case 'q': 
+	    method=AC_GET_MAC_DL_PKT_CNT;
+	    break;
+	case 'r': 
+	    method=AC_GET_MAC_UL_BYTE_CNT;
+	    break;
+	case 's': 
+	    method=AC_GET_MAC_DL_BYTE_CNT;
+	    break;
+	case 't': 
+	    method=AC_GET_IP_UL_PKT_CNT;
+	    break;
+	case 'u': 
+	    method=AC_GET_IP_DL_PKT_CNT;
+	    break;
+	case 'v': 
+	    method=AC_GET_IP_UL_BYTE_CNT;
+	    break;
+	case 'w': 
+	    method=AC_GET_IP_DL_BYTE_CNT;
+	    break;
+	case 'P': 
+	    method=AC_GET_VLAN_UL_PKT_CNT;
+	    break;
+	case 'Q': 
+	    method=AC_GET_VLAN_DL_PKT_CNT;
+	    break;
+	case 'R': 
+	    method=AC_GET_VLAN_UL_BYTE_CNT;
+	    break;
+	case 'S': 
+	    method=AC_GET_VLAN_DL_BYTE_CNT;
+	    break;
+	case 'z': /* CleanTbl */
+	    method=AC_CLEAN_TBL;
+	    break;
+	case 'm': /* Mac */
+	    str_to_mac(args.mac, optarg);
+	    break;
+	case 'i': /* IP */
+	    str_to_ip(&args.ip_s, optarg);
+	    break;
+	case 'j':
+	    str_to_ip(&args.ip_e, optarg);
+	    break;
+	case 'k':
+	    args.vid = strtoll(optarg, NULL, 10);
+	    break;
+
+	case '?': /* Help */
+	    show_usage();
+	    break;
+	}
+    } 
+
+
+    switch(method) {
+    case AC_ADD_VLAN_UL_ENTRY:
+    case AC_ADD_VLAN_DL_ENTRY:
+    case AC_ADD_MAC_UL_ENTRY:
+    case AC_ADD_MAC_DL_ENTRY:
+    case AC_ADD_IP_UL_ENTRY:
+    case AC_ADD_IP_DL_ENTRY:
+    case AC_CLEAN_TBL:
+	    SetAcEntry(&args, method);
+	    result = args.result;
+	    break;
+    case AC_DEL_VLAN_UL_ENTRY:
+    case AC_DEL_VLAN_DL_ENTRY:
+    case AC_DEL_MAC_UL_ENTRY:
+    case AC_DEL_MAC_DL_ENTRY:
+    case AC_DEL_IP_UL_ENTRY:
+    case AC_DEL_IP_DL_ENTRY:
+	    SetAcEntry(&args, method);
+	    result = args.result;
+	    break;
+    case AC_GET_VLAN_UL_PKT_CNT:
+    case AC_GET_VLAN_DL_PKT_CNT: 
+    case AC_GET_MAC_UL_PKT_CNT:
+    case AC_GET_MAC_DL_PKT_CNT: 
+    case AC_GET_IP_UL_PKT_CNT:
+    case AC_GET_IP_DL_PKT_CNT:
+    case AC_GET_VLAN_UL_BYTE_CNT:
+    case AC_GET_VLAN_DL_BYTE_CNT:
+    case AC_GET_MAC_UL_BYTE_CNT:
+    case AC_GET_MAC_DL_BYTE_CNT:
+    case AC_GET_IP_UL_BYTE_CNT: 
+    case AC_GET_IP_DL_BYTE_CNT:  
+	    result = GetAcEntry(&args, method);
+	    printf("Count=%lld\n",args.cnt);
+	    break;
+    default:
+         result = AC_FAIL;
+    }
+
+    if(result == AC_SUCCESS) {
+	printf("done\n");
+    }else if (result ==  AC_TBL_FULL) {
+	printf("table full\n");
+    } else {
+	printf("fail\n");
+    }
+    
+    close(fd);
+    return 0;
+}
diff --git a/src/extended/hw_nat/ac_api.c b/src/extended/hw_nat/ac_api.c
new file mode 100644
index 0000000..2f448b9
--- /dev/null
+++ b/src/extended/hw_nat/ac_api.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include "ac_ioctl.h"
+
+int SetAcEntry(struct ac_args *opt, unsigned int cmd)
+{
+    int fd;
+
+    fd = open("/dev/"AC_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+        printf("Open %s pseudo device failed\n","/dev/"AC_DEVNAME);
+        return AC_FAIL;
+    }
+
+    if(ioctl(fd, cmd, opt)<0) {
+        printf("AC_API: ioctl error\n");
+        close(fd);
+        return AC_FAIL;
+    }
+
+    close(fd);
+    return AC_SUCCESS;
+}
+
+
+int GetAcEntry(struct ac_args *opt, unsigned int cmd)
+{
+    int fd;
+
+    fd = open("/dev/"AC_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"AC_DEVNAME);
+	return AC_FAIL;
+    }
+
+    if(ioctl(fd, cmd, opt)<0) {
+	printf("AC_API: ioctl error\n");
+	close(fd);
+	return AC_FAIL;
+    }
+
+    close(fd);
+    return AC_SUCCESS;
+}
diff --git a/src/extended/hw_nat/ac_api.h b/src/extended/hw_nat/ac_api.h
new file mode 100644
index 0000000..dd5a40f
--- /dev/null
+++ b/src/extended/hw_nat/ac_api.h
@@ -0,0 +1,6 @@
+#ifndef __AC_API
+#define __AC_API
+
+int SetAcEntry(struct ac_args *opt, unsigned int cmd);
+int GetAcEntry(struct ac_args *opt, unsigned int cmd);
+#endif
diff --git a/src/extended/hw_nat/acl.c b/src/extended/hw_nat/acl.c
new file mode 100644
index 0000000..e6683d3
--- /dev/null
+++ b/src/extended/hw_nat/acl.c
@@ -0,0 +1,341 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include "acl_ioctl.h"
+#include "acl_api.h"
+
+void show_usage(void)
+{
+    printf("Add SDMAC  Entry for Any Protocol\n");
+    printf("acl -A -n [SDMAC] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -A -n 00:11:22:33:44:55  -u Deny \n\n");
+    printf("Ex: acl -A -n 00:11:22:33:44:55  -U 3 -u FP \n\n");
+
+    printf("Add SMAC to DIP Entry for Any Protocol\n");
+    printf("acl -a -n [SMAC] -q [DipS] -r [DipE] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -a -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -u Deny \n\n");
+    printf("Ex: acl -a -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -U 3 -u FP \n\n");
+
+    printf("Add SMAC to DIP Entry for Tcp Protocol\n");
+    printf("acl -b  -n [SMAC] -q [DipS] -r [DipE] -s [DpS] -t [DpE] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -b -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -s 1 -t 1024 -u Deny\n\n");
+   
+    printf("SMAC to DIP Entry for Udp Protocol\n");
+    printf("acl -c  -n [SMAC] -q [DipS] -r [DipE] -s [DpS] -t [DpE] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -c -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -s 1 -t 1024 -u Deny\n\n");
+  
+    printf("Del SDMAC  Entry for Any Protocol\n");
+    printf("acl -D -n [SMAC]\n");
+    printf("Ex: acl -D -n 00:11:22:33:44:55 \n\n");
+
+    printf("Del SMAC to DIP Entry for Any Protocol\n");
+    printf("acl -d -n [SMAC] -q [DipS] -r [DipE]\n");
+    printf("Ex: acl -d -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5\n\n");
+   
+    printf("Del SMAC to DIP Entry for Tcp Protocol\n");
+    printf("acl -e  -n [SMAC] -q [DipS] -r [DipE] -s [DpS] -t [DpE]\n");
+    printf("Ex: acl -e -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -s 1 -t 1024\n\n");
+   
+    printf("Del SMAC to DIP Entry for Udp Protocol\n");
+    printf("acl -f  -n [SMAC] -q [DipS] -r [DipE] -s [DpS] -t [DpE]\n");
+    printf("Ex: acl -f -n 00:11:22:33:44:55 -q 10.10.10.3 -r 10.10.10.5 -s 1 -t 1024\n\n");
+
+    printf("Add SIP to DIP Entry for Any Protocol\n");
+    printf("acl -H  -o [SipS] -p [SipE] -q [DipS] -r [DipE] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -H -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -u Deny\n\n");
+   
+
+    printf("Add SIP to DIP Entry for Tcp Protocol\n");
+    printf("acl -h  -o [SipS] -p [SipE] -q [DipS] -r [DipE] -s [DpS] -t [DpE] -U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -h -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024 -u Deny\n\n");
+   
+
+    printf("Add SIP to DIP Entry for Udp Protocol\n");
+    printf("acl -i  -o [SipS] -p [SipE] -q [DipS] -r [DipE] -s [DpS] -t [DpE]-U[UP] -u [Allow/Deny/FP]\n");
+    printf("Ex: acl -i -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024 -u Deny\n\n");
+    
+    printf("Del SIP to DIP Entry for Any Protocol\n");
+    printf("acl -j  -o [SipS] -p [SipE] -q [DipS] -r [DipE]\n");
+    printf("Ex: acl -j -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3\n\n");
+   
+
+    printf("Del SIP to DIP Entry for Tcp Protocol\n");
+    printf("acl -k  -o [SipS] -p [SipE] -q [DipS] -r [DipE] -s [DpS] -t [DpE]\n");
+    printf("Ex: acl -k -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024\n\n");
+   
+
+    printf("Del SIP to DIP Entry for Udp Protocol\n");
+    printf("acl -l  -o [SipS] -p [SipE] -q [DipS] -r [DipE] -s [DpS] -t [DpE]\n");
+    printf("Ex: acl -l -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024\n\n");
+    printf("Del All Entries\n");
+    printf("acl -m\n\n");
+
+    printf("Add S/DMAC ETYPE VID PROTOCOL SIP DIP SP DP Entry\n");
+    printf("acl -E -n[SMAC] -N[DMAC] -P[ESW Port] -Z[Ethertype] -S[Protocol] -o[SipS] -p[SipE] -q[DipS] -r[DipE] -s[DpS] -t[DpE] -v[SpS] -x[SpE] -y[TosS] -z[TosE] -F[TCP/UDP/ANY] -V[VID] -u[Allow/Deny/FP]\n");
+    printf("Ex: acl -E  -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024 -F UDP -u Deny\n\n");
+   
+
+    printf("Del S/DMAC ETYPE  VID PROTOCOL SIP DIP SP DP Entry\n");
+    printf("acl -G -n[SMAC] -N[DMAC] -P[ESW Port] -Z[Ethertype] -S[Protocol] -o[SipS] -p[SipE] -q[DipS] -r[DipE] -s[DpS] -t[DpE] -v[SpS] -x[SpE] -y[TosS] -z[TosE] -F[TCP/UDP/ANY] -V[VID] \n");
+    printf("Ex: acl -G  -o 10.10.10.3 -p 10.10.10.5 -q 10.10.20.3 -r 10.10.20.3 -s 1 -t 1024 -F UDP\n\n");
+
+    printf("Show All ACL Entry\n");
+    printf("Ex: acl -g\n\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+    int opt;
+    char options[] = "AabcDdEefGgHhijklm?F:n:N:o:P:p:q:r:s:S:t:u:U:v:x:y:V:z:Z:";
+    int fd;
+    struct acl_args args;
+    struct acl_list_args *args2;
+    int method=-1;
+    int result;
+    int i;
+
+    memset(&args, 0, sizeof(struct acl_args));
+    args.pn = 7; /* Default do not care*/
+    /* Max 511 acl entries */
+    args2=malloc(sizeof(struct acl_list_args) + sizeof(struct acl_args)*511);
+    if (NULL == args2)
+    {
+	    printf(" Allocate memory for acl_list_args and acl_args failed.\n");
+	    return 0;
+    }
+    fd = open("/dev/"ACL_DEVNAME, O_RDONLY);
+
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"ACL_DEVNAME);
+        free(args2);
+	return 0;
+    }
+
+    if(argc < 2) {
+	show_usage();
+        free(args2);
+        close(fd);
+	return 0;
+    }
+
+    while ((opt = getopt (argc, argv, options)) != -1) {
+	switch (opt) {
+	case 'A': 
+		method=ACL_ADD_SDMAC_ANY;
+		break;
+	case 'a': 
+		method=ACL_ADD_SMAC_DIP_ANY;
+		break;
+	case 'b':
+		method=ACL_ADD_SMAC_DIP_TCP;
+		break;
+	case 'c':
+		method=ACL_ADD_SMAC_DIP_UDP;
+		break;
+	case 'D': 
+		method=ACL_DEL_SDMAC_ANY;
+		break;
+	case 'd': 
+		method=ACL_DEL_SMAC_DIP_ANY;
+		break;
+	case 'e':
+		method=ACL_DEL_SMAC_DIP_TCP;
+		break;
+	case 'E':
+		method=ACL_ADD_SMAC_DMAC_ETYPE_VID_SIP_DIP_TOS_PORT;
+		break;
+	case 'F':
+                if(strcasecmp(optarg,"TCP")==0){
+                            args.L4=ACL_PROTO_TCP;
+	                }else if(strcasecmp(optarg,"UDP")==0){
+	                        args.L4=ACL_PROTO_UDP;
+	                    }else if(strcasecmp(optarg,"ANY")==0){
+	                        args.L4=ACL_PROTO_ANY;
+	                }else{
+                            printf("Error: -t TCP or UDP or ANY\n");
+			    free(args2);
+			    close(fd);
+			    return 0;
+                }
+
+		break;
+	case 'G':
+		method=ACL_DEL_SMAC_DMAC_ETYPE_VID_SIP_DIP_TOS_PORT;
+		break;
+	case 'f':
+		method=ACL_DEL_SMAC_DIP_UDP;
+		break;
+	case 'H':
+		method=ACL_ADD_SIP_DIP_ANY;
+		break;
+        case 'g':
+                method = ACL_GET_ALL_ENTRIES;
+		break;
+	case 'h':
+		method=ACL_ADD_SIP_DIP_TCP;
+		break;
+	case 'i':
+		method=ACL_ADD_SIP_DIP_UDP;
+		break;
+	case 'j':
+		method=ACL_DEL_SIP_DIP_ANY;
+		break;
+	case 'k':
+		method=ACL_DEL_SIP_DIP_TCP;
+		break;
+	case 'l':
+		method=ACL_DEL_SIP_DIP_UDP;
+		break;
+	case 'm':
+		method=ACL_CLEAN_TBL;
+		break;
+	case 'n': /* source mac address */
+		str_to_mac(args.mac, optarg);
+		break;
+	case 'N': /* destination mac address */
+		str_to_mac(args.dmac, optarg);
+		break;
+	case 'o': /* start of sip */
+		str_to_ip(&args.sip_s, optarg);
+		break;
+	case 'p': /* end of sip */
+		str_to_ip(&args.sip_e, optarg);
+		break;
+	case 'P': /* Port Number */
+		args.pn=strtoll(optarg, NULL, 10);
+		break;
+	case 'q': /* start of dip */
+		str_to_ip(&args.dip_s, optarg);
+		break;
+	case 'r': /* end of dip */
+		str_to_ip(&args.dip_e, optarg);
+		break;
+	case 's': /* start of dp */
+		args.dp_s=strtoll(optarg, NULL, 10);
+		break;
+	case 't': /* end of dp */
+		args.dp_e=strtoll(optarg, NULL, 10);
+		break;
+	case 'S': /* Protocol */
+		args.protocol=strtoll(optarg, NULL, 10);
+		break;
+
+	case 'v': /* start of sp */
+		args.sp_s=strtoll(optarg, NULL, 10);
+		break;
+	case 'x': /* end of sp */
+		args.sp_e=strtoll(optarg, NULL, 10);
+		break;
+	case 'y': /* start of tos */
+		args.tos_s=strtoll(optarg, NULL, 10);
+		break;
+	case 'z': /* end of tos */
+		args.tos_e=strtoll(optarg, NULL, 10);
+		break;
+	case 'Z': /* ethertype */
+		args.ethertype=strtoll(optarg, NULL, 16);
+		break;
+	case 'V': /* VID */
+		args.vid=strtoll(optarg, NULL, 10);
+		break;
+	case 'u': /* Deny/Allow */
+		if(strcasecmp(optarg,"Deny")==0){
+			args.method=ACL_DENY_RULE;
+		}else if(strcasecmp(optarg,"Allow")==0){
+			args.method=ACL_ALLOW_RULE;
+		}else if(strcasecmp(optarg,"FP")==0){
+			args.method=ACL_PRIORITY_RULE;
+		}else{
+			printf("Error: -t Deny or Allow\n");
+			free(args2);
+			close(fd);
+			return 0;
+		}
+		break;
+	case 'U': /* User Priority */
+		args.up=strtoll(optarg, NULL, 10);
+		break;
+	case '?':
+	default:
+	    show_usage();
+	    free(args2);
+	    close(fd);
+            return 0;
+	}
+    } 
+    switch(method) {
+    case ACL_ADD_SDMAC_ANY:
+    case ACL_ADD_ETYPE_ANY:	
+    case ACL_ADD_SMAC_DIP_ANY:
+    case ACL_ADD_SMAC_DIP_TCP:
+    case ACL_ADD_SMAC_DIP_UDP:
+    case ACL_DEL_SDMAC_ANY:
+    case ACL_DEL_ETYPE_ANY:
+    case ACL_DEL_SMAC_DIP_ANY:
+    case ACL_DEL_SMAC_DIP_TCP:
+    case ACL_DEL_SMAC_DIP_UDP:
+    case ACL_ADD_SIP_DIP_ANY:
+    case ACL_ADD_SIP_DIP_TCP:
+    case ACL_ADD_SIP_DIP_UDP:
+    case ACL_ADD_SMAC_DMAC_ETYPE_VID_SIP_DIP_TOS_PORT:	
+    case ACL_DEL_SIP_DIP_ANY:
+    case ACL_DEL_SIP_DIP_TCP:
+    case ACL_DEL_SIP_DIP_UDP:
+    case ACL_DEL_SMAC_DMAC_ETYPE_VID_SIP_DIP_TOS_PORT:
+    case ACL_CLEAN_TBL:
+	      SetAclEntry(&args, method);
+	      result = args.result;
+	      break;
+    case ACL_GET_ALL_ENTRIES:
+	      AclGetAllEntries(args2);
+	      result = args2->result;
+
+	      printf("Total Entry Count = %d\n",args2->num_of_entries);
+	      for(i=0;i<args2->num_of_entries;i++){
+		  printf("#%d :SMAC=%02X:%02X:%02X:%02X:%02X:%02X => DMAC=%02X:%02X:%02X:%02X:%02X:%02X PROTOCOL=0x%2x\n", \
+			  i, args2->entries[i].mac[0], args2->entries[i].mac[1], args2->entries[i].mac[2], \
+			  args2->entries[i].mac[3], args2->entries[i].mac[4], args2->entries[i].mac[5], \
+			  args2->entries[i].dmac[0], args2->entries[i].dmac[1],args2->entries[i].dmac[2], \
+			  args2->entries[i].dmac[3], args2->entries[i].dmac[4],args2->entries[i].dmac[5], \
+			  args2->entries[i].protocol);
+
+		  printf("   :SIP %u.%u.%u.%u->%u.%u.%u.%u=>DIP %u.%u.%u.%u->%u.%u.%u.%u  SP %d->%d=>DP %d->%d TOS:0x%2x->0x%2x VID:%d ETYPE=0x%4x TCP_UDP=0/TCP=1/UDP=2:%d PN:%d\n\r", \
+			  NIPQUAD(args2->entries[i].sip_s), \
+			  NIPQUAD(args2->entries[i].sip_e), \
+			  NIPQUAD(args2->entries[i].dip_s), \
+			  NIPQUAD(args2->entries[i].dip_e), \
+			  args2->entries[i].sp_s, \
+			  args2->entries[i].sp_e, \
+			  args2->entries[i].dp_s, \
+			  args2->entries[i].dp_e, \
+			  args2->entries[i].tos_s, \
+		    args2->entries[i].tos_e, \
+		    args2->entries[i].vid, \
+		    args2->entries[i].ethertype, \
+		    args2->entries[i].L4, \
+		    args2->entries[i].pn);
+	      }
+	      break;
+    default:
+	      result = ACL_FAIL;
+    }
+
+
+    if(result == ACL_SUCCESS) {
+	printf("done\n");
+    }else if (result ==  ACL_TBL_FULL) {
+	printf("table full\n");
+    } else {
+	printf("fail\n");
+    }
+    
+    free(args2);
+    close(fd);
+    return 0;
+}
diff --git a/src/extended/hw_nat/acl_api.c b/src/extended/hw_nat/acl_api.c
new file mode 100644
index 0000000..3ee3fae
--- /dev/null
+++ b/src/extended/hw_nat/acl_api.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include "acl_ioctl.h"
+
+int SetAclEntry(struct acl_args *opt, unsigned int cmd)
+{
+    int fd;
+
+    fd = open("/dev/"ACL_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"ACL_DEVNAME);
+	return ACL_FAIL;
+    }
+
+    if(ioctl(fd, cmd, opt)<0) {
+	printf("ACL_API: ioctl error\n");
+	close(fd);
+	return ACL_FAIL;
+    }
+
+    close(fd);
+    return ACL_SUCCESS;
+}
+int AclGetAllEntries(struct acl_list_args *opt)
+{
+    int fd=0;
+
+    fd = open("/dev/"ACL_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"ACL_DEVNAME);
+	return ACL_FAIL;
+    }
+
+    if(ioctl(fd, ACL_GET_ALL_ENTRIES, opt)<0) {
+	printf("ACL_API: ioctl error\n");
+	close(fd);
+	return ACL_FAIL;
+    }
+
+    close(fd);
+    
+    return ACL_SUCCESS;
+
+}
diff --git a/src/extended/hw_nat/acl_api.h b/src/extended/hw_nat/acl_api.h
new file mode 100644
index 0000000..9b6f574
--- /dev/null
+++ b/src/extended/hw_nat/acl_api.h
@@ -0,0 +1,16 @@
+#ifndef __ACL_API
+#define __ACL_API
+
+#define NIPQUAD(addr) \
+        ((unsigned char *)&addr)[3], \
+        ((unsigned char *)&addr)[2], \
+        ((unsigned char *)&addr)[1], \
+        ((unsigned char *)&addr)[0]
+#define NIPHALF(addr) \
+        ((unsigned short *)&addr)[0], \
+        ((unsigned short *)&addr)[1]
+
+int SetAclEntry(struct acl_args *opt, unsigned int cmd);
+int AclGetAllEntries(struct acl_list_args *opt);
+
+#endif
diff --git a/src/extended/hw_nat/hw_nat.c b/src/extended/hw_nat/hw_nat.c
new file mode 100644
index 0000000..555d451
--- /dev/null
+++ b/src/extended/hw_nat/hw_nat.c
@@ -0,0 +1,847 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <strings.h>
+#include <unistd.h>
+#ifndef CONFIG_SUPPORT_OPENWRT
+#include <linux/autoconf.h>
+#endif
+
+#if defined CONFIG_COLGIN_SUPPORT
+#include "hnat_ioctl.h"
+#else
+#include "hwnat_ioctl.h"
+#endif
+#include "hwnat_api.h"
+#include "util.h"
+
+void show_usage(void)
+{
+    printf("Add Static Entry\n");
+    printf("hw_nat -a -h [SMAC] -i [DMAC] -1 [type:hnapt(0)/ipv6_rout(5)]-j [Sip] -2 [Dip] -l [Sp] -3 [Dp]\n");
+    printf("	   -n [New_Sip] -o [New_Dip] -p [New_Sp] -q [New_Dp] -4 [Vlan_layer] -5 [dscp]\n");
+    printf("	   -s [VLAN1_ID] -S [VLAN2_ID] -v [Tcp/Udp] -w [OutIf:CPU/GE1/GE2]\n");
+    printf("Ex(ipv4): hw_nat -a -h 00:0C:43:28:80:11 -i E0:18:77:BD:D5:18 -1 0 -j 10.10.10.3 -2 10.10.20.3\n");
+    printf("-l 1000 -3 2000 -n 10.10.20.254 -o 10.10.20.3 -p 1000 -q 2000 -4 1 -s 1 -v Tcp -w GE2 -5 32\n\n");
+
+    printf("Ex(ipv6): hw_nat -a -h 00:0C:43:28:02:14 -i 00:1B:21:00:9B:03 -1 5 -6 2001:1111:2222:3333:0000:0000:0000:2\n");
+    printf("-7 2001:aaa:6401:101:8000:0000:0000:2 -l 3000 -3 2000 -4 0 -v Tcp -w GE1 -5 32\n\n");
+
+    printf("Del Static Entry\n");
+    printf("hw_nat -b -1 [type:hnapt(0)/ipv6_rout(5)] -j [Sip] -2 [Dip] -l [Sp] -3 [Dp] -v [Tcp/Udp] \n");
+    printf("Ex: hw_nat -b -j 10.10.10.3 -k 10.10.20.3 -l 30 -m 40 -v Tcp\n\n");
+#if defined (CONFIG_HW_NAT_SEMI_AUTO_MODE)
+    printf("Add semi-auto Entry\n");
+    printf("hw_nat -a -1 [type:hnapt(0)/ipv6_rout(5)]-j [Sip] -2 [Dip] -l [Sp] -m [Dp]\n");
+    printf("hw_nat -a -1 0 -j 10.10.10.3 -2 10.10.20.3 -l 1000 -3 2000 \n");
+    printf("hw_nat -a -1 5 -j 2001:1111:2222:3333:0000:0000:0000:2 -2 2001:aaa:6401:101:8000:0000:0000:2 -l 3000 -3 2000\n");
+    printf("Delete semi-auto Entry\n");
+    printf("hw_nat -b -1 0 -j 10.10.10.3 -2 10.10.20.3 -l 1000 -3 2000\n");
+    printf("hw_nat -b -1 5 -j 2001:1111:2222:3333:0000:0000:0000:2 -2 2001:aaa:6401:101:8000:0000:0000:2 -l 3000 -3 2000\n");
+#endif
+    printf("Show Foe Entry\n");
+    printf("hw_nat -c [entry_num]\n");
+    printf("Ex: hw_nat -c 1234\n\n");
+
+    printf("Set Debug Level (0:disable) \n");
+    printf("hw_nat -d [0~7]\n");
+    printf("Ex: hw_nat -d \n\n");
+
+    printf("Show All Foe Invalid Entry\n");
+    printf("Ex: hw_nat -e\n\n");
+
+    printf("Show All Foe Unbinded Entry\n");
+    printf("Ex: hw_nat -f\n\n");
+
+    printf("Show All Foe Binded Entry\n");
+    printf("Ex: hw_nat -g\n\n");
+
+    printf("Unbind Foe Entry\n");
+    printf("hw_nat -x [entry_num]\n");
+    printf("Ex: hw_nat -x 1234\n\n");
+
+    printf("Set Foe Entry to PacketDrop\n");
+    printf("hw_nat -k [entry_num]\n");
+    printf("Ex: hw_nat -k 1234\n\n");
+
+
+#if defined (CONFIG_PPE_MCAST)
+    printf("Add member port in multicast entry\n");
+    printf("Ex: hw_nat -B [vid] [mac] [px_en] [px_qos_en] [mc_qos_qid]\n\n");
+
+    printf("Del member port multicast entry\n");
+    printf("Ex: hw_nat -C [vid] [mac] [px_en] [px_qos_en] [mc_qos_qid]\n\n");
+
+    printf("Dump all multicast entry\n");
+    printf("Ex: hw_nat -D\n\n");
+#endif
+
+    printf("Set PPE Cofigurations:\n");
+    printf("Set HNAT binding threshold per second (d=30)\n");
+    printf("Ex: hw_nat -N [1~65535]\n\n");
+
+
+    printf("Set HNAT TCP/UDP keepalive interval (d=1, 1)(unit:4sec)\n");
+    printf("Ex: hw_nat -Q [1~255][1~255]\n\n");
+
+    printf("Disable Hook API (hook_id: 0=ETH, 1=MD, 2=WIFI, 3=RNDIS, 4=EXT)\n");
+    printf("Ex: hw_nat -O <hook_id>, hwnat -O [0/1/2/3/4]\n\n");
+
+    printf("Restore Hook API (hook_id: 0=ETH, 1=MD, 2=WIFI, 3=RNDIS, 4=EXT)\n");
+    printf("Ex: hw_nat -T <hook_id>, hwnat -T [0/1/2/3/4]\n\n");
+
+    printf("Disable Hook API on specific direction (hook_id: 0=ETH, 1=MD, 2=WIFI, 3=RNDIS, 4=EXT) (dir: 1:rx, 2:tx)\n");
+    printf("Ex: hw_nat -O <hook_id> -P <dir_id>, hwnat -O [0/1/2/3/4] -P[1/2]\n\n");
+
+    printf("Restore Hook API on specific direction (hook_id: 0=ETH, 1=MD, 2=WIFI, 3=RNDIS, 4=EXT) (dir: 1:rx, 2:tx)\n");
+    printf("Ex: hw_nat -T <hook_id> -P <dir_id>, hwnat -T [0/1/2/3/4] -P[1/2]\n\n");
+
+    printf("Set HNAT Life time of Binded TCP/UDP/FIN entry(d=5, 5, 5)(unit:1Sec) \n");
+    printf("Ex: hw_nat -U [1~65535][1~65535][1~65535]\n\n");
+
+    printf("Set LAN/WAN port VLAN ID\n");
+    printf("Ex: hw_nat -V [LAN_VID] [WAN_VID]\n\n");
+    printf("Ex: hw_nat -V 1 2\n\n");
+
+    printf("Only Speed UP (0=Upstream, 1=Downstream, 2=Bi-Direction) flow \n");
+    printf("Ex: hw_nat -Z 1\n\n");
+
+#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+    printf("Switch Ds-Lite and Map-E(0=Ds-Lite, 1=Map-E,(d=0)):\n");
+    printf("Ex: hw_nat -W [0/1]\n\n");
+#endif
+#if defined (CONFIG_PPE_MIB)
+    printf("Get ppe entry mib counter\n");
+    printf("hw_nat -M -1 [type:hnapt(0)/ipv6_rout(5)]-j [Sip] -2 [Dip] -l [Sp] -m [Dp]\n");
+    printf("hw_nat -M -1 0 -j 10.10.10.3 -2 10.10.20.3 -l 1000 -3 2000 \n");
+    printf("hw_nat -M -1 5 -j 2001:1111:2222:3333:0000:0000:0000:2 -2 2001:aaa:6401:101:8000:0000:0000:2 -l 3000 -3 2000\n");
+    printf("Get ppe entry all mib counter sort by IP\n");
+    printf("hw_nat -X\n");
+#endif
+#if defined (CONFIG_HW_NAT_IPI)
+    printf("Set HNAT IPI control from extif:\n");
+    printf("EX: hw_nat -G [ipi_enable] [queue_thresh] [drop_pkt] [ipi_cnt_mod]\n\n");
+    printf("Set HNAT IPI control from ppehit:\n");
+    printf("EX: hw_nat -L [ipi_enable] [queue_thresh] [drop_pkt] [ipi_cnt_mod]\n\n");
+    printf("hw_nat -G 1 1000 20000 5\n");
+    printf("hw_nat -L 1 1000 20000 44\n");
+#endif
+}
+#if defined CONFIG_COLGIN_SUPPORT
+static void dump_all_ip_cnt(struct hwnat_mib_all_ip_args *args)
+{
+	int i;
+	if(args->entry_num > 0)
+		printf("IP            tx_packets     tx_bytes     rx_packets     rx_bytes\n");
+	for(i=0; i<args->entry_num; i++) {
+		if(args->entries[i].is_ipv4) { //IPV4_NAPT
+			printf("%8x	%10ld  %10ld  %10ld  %10ld\n",
+			args->entries[i].ip.ipv4_addr,
+			args->entries[i].tx_packets,
+			args->entries[i].tx_bytes,
+			args->entries[i].rx_packets,
+			args->entries[i].rx_bytes);
+		} else { //IPV6_5T_ROUTE
+			printf(" %4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x	%10ld  %10ld  %10ld  %10ld\n",
+				NIPHALF(args->entries[i].ip.ipv6_addr[0]),
+				NIPHALF(args->entries[i].ip.ipv6_addr[1]),
+				NIPHALF(args->entries[i].ip.ipv6_addr[2]),
+				NIPHALF(args->entries[i].ip.ipv6_addr[3]),
+				args->entries[i].tx_packets,
+				args->entries[i].tx_bytes,
+				args->entries[i].rx_packets,
+				args->entries[i].rx_bytes);
+		}
+	}
+}
+#endif
+int main(int argc, char *argv[])
+{
+    int opt;
+
+    //char options[] = "aefgy?c:x:k:d:A:B:C:DN:O:P:Q:T:U:V:Z:";
+    char options[] = "abefgyzMD?c:m:r:A:B:C:G:I:J:K:L:S:d:h:i:j:1:k:2:l:3:n:o:p:q:4:s:P:t:u:v:w:5:x:y:N:O:Q:T:U:Z:L:7:8:9:E:F:H:R:6:X";
+
+    int fd, method = -1;
+    int i=0;
+    unsigned int entry_num;
+    unsigned int debug;
+    unsigned int type;
+    struct hwnat_args *args;
+    struct hwnat_tuple args2 = {0};
+    struct hwnat_ac_args args3;
+    struct hwnat_config_args args4;
+#if defined (CONFIG_HW_NAT_IPI)
+    struct hwnat_ipi_args args6;
+    struct hwnat_ipi_args args7;
+#endif
+
+#if defined (CONFIG_PPE_MCAST)
+    struct hwnat_mcast_args args5;
+    unsigned char mac[6];
+#endif
+#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+	unsigned int swit;
+#endif
+    int	   result;
+#if defined CONFIG_COLGIN_SUPPORT
+	int org_tot_len = 1362;
+	int org_id = 0;
+	int org_frag =0;
+	int chksum_tmp, tot_len_tmp, id_tmp, frag_tmp;
+	int chksum_base = 0;
+	struct hwnat_mib_all_ip_args *args8;
+#endif
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return 0;
+    }
+
+    if(argc < 2) {
+	show_usage();
+        close(fd);
+	return 0;
+    }
+
+    /* Max table size is 16K */
+    args=malloc(sizeof(struct hwnat_args)+sizeof(struct hwnat_tuple)*1024*16);
+    if (NULL == args)
+    {
+	    printf(" Allocate memory for hwnat_args and hwnat_tuple failed.\n");
+            close(fd);
+	    return 0;
+    }
+
+    while ((opt = getopt (argc, argv, options)) != -1) {
+	switch (opt) {
+	case 'h':
+		 str_to_mac(args2.smac, optarg);
+		 break;
+	case 'i':
+		 str_to_mac(args2.dmac, optarg);
+		 break;
+	case '1':
+		 type = strtoll(optarg, NULL, 10);
+		 args2.pkt_type = type;
+		 break;
+	case 'j':
+		if ((type == 0) || (type == 7)) {
+			str_to_ip(&args2.ing_sipv4, optarg);
+		} else if((type == 5) || (type == 3)) {
+			str_to_ipv6(&args2.ing_sipv6_0, optarg, 0);
+			str_to_ipv6(&args2.ing_sipv6_1, optarg, 1);
+			str_to_ipv6(&args2.ing_sipv6_2, optarg, 2);
+			str_to_ipv6(&args2.ing_sipv6_3, optarg, 3);
+		} else {
+			printf("hwnat type error\n");
+			free(args);
+			close(fd);
+			return 0;
+		}
+		 break;
+	case '2':
+		if ((type == 0) || (type == 7)) {
+			str_to_ip(&args2.ing_dipv4, optarg);
+		} else if((type == 5) || (type == 3)) {
+			str_to_ipv6(&args2.ing_dipv6_0, optarg, 0);
+			str_to_ipv6(&args2.ing_dipv6_1, optarg, 1);
+			str_to_ipv6(&args2.ing_dipv6_2, optarg, 2);
+			str_to_ipv6(&args2.ing_dipv6_3, optarg, 3);
+		} else {
+			printf("hwnat type error\n");
+			free(args);
+			close(fd);
+			return 0;
+		}
+		 break;
+	case 'l':
+		 args2.ing_sp = strtoll(optarg, NULL, 10);
+		 break;
+	case '3':
+		 args2.ing_dp = strtoll(optarg, NULL, 10);
+		 break;
+	case 'n':
+		 str_to_ip(&args2.eg_sipv4, optarg);
+		 break;
+	case 'o':
+		 str_to_ip(&args2.eg_dipv4, optarg);
+		 break;
+	case 'p':
+		 args2.eg_sp = strtoll(optarg, NULL, 10);
+		 break;
+	case 'q':
+		 args2.eg_dp = strtoll(optarg, NULL, 10);
+		 break;
+	case '4':
+		 args2.vlan_layer = strtoll(optarg, NULL, 10);
+		 break;
+	case 's':
+		 args2.vlan1 = strtoll(optarg, NULL, 10);
+                 break;
+	case 'S':
+		 args2.vlan2 = strtoll(optarg, NULL, 10);
+		 break;
+#if defined CONFIG_COLGIN_SUPPORT
+	case 'P':
+		args2.etype = strtoll(optarg, NULL, 16);
+		break;
+#endif
+	case 't':
+		 if(strcasecmp(optarg,"Ins")==0){
+			 args2.pppoe_act=1;
+		 }else if(strcasecmp(optarg,"Del")==0){
+			 args2.pppoe_act=0;
+		 }else{
+			 printf("Error: -t No/Mod/Ins/Del\n");
+			 free(args);
+			 close(fd);
+			 return 0;
+		 }
+		 break;
+	case 'u':
+		 args2.pppoe_id = strtoll(optarg, NULL, 10);
+		 break;
+	case 'v':
+		 if(strcasecmp(optarg,"Tcp")==0){
+			 args2.is_udp=0;
+		 }else if(strcasecmp(optarg,"Udp")==0){
+			 args2.is_udp=1;
+		 }else {
+			 printf("Error: -v Tcp/Udp\n");
+			 free(args);
+			 close(fd);
+			 return 0;
+		 }
+		 break;
+	case 'w':
+		 if(strcasecmp(optarg,"CPU")==0){
+			 args2.dst_port=0;
+		 }else if(strcasecmp(optarg,"GE1")==0){
+			 args2.dst_port=1;
+		 }else if(strcasecmp(optarg,"GE2")==0){
+			 args2.dst_port=2;
+		 }else if(strcasecmp(optarg,"P9")==0){
+			 args2.dst_port=9;
+		 }else if(strcasecmp(optarg,"P8")==0){
+			 args2.dst_port=8;
+		 }else if(strcasecmp(optarg,"p10")==0){
+			 args2.dst_port=10;
+		 }else if(strcasecmp(optarg,"p11")==0){
+			 args2.dst_port=11;
+		 }else if(strcasecmp(optarg,"p12")==0){
+			 args2.dst_port=12;
+		 }else {
+			printf("Error: -w CPU/GE1/GE2\n");
+			free(args);
+			close(fd);
+			return 0;
+		 }
+		 break;
+	case '5':
+		 args2.dscp = strtoll(optarg, NULL, 10);
+		 break;
+	case '7':
+		str_to_ipv6(&args2.ing_sipv6_0, optarg, 0);
+		str_to_ipv6(&args2.ing_sipv6_1, optarg, 1);
+		str_to_ipv6(&args2.ing_sipv6_2, optarg, 2);
+		str_to_ipv6(&args2.ing_sipv6_3, optarg, 3);
+		break;
+	case '8':
+		str_to_ipv6(&args2.ing_dipv6_0, optarg, 0);
+		str_to_ipv6(&args2.ing_dipv6_1, optarg, 1);
+		str_to_ipv6(&args2.ing_dipv6_2, optarg, 2);
+		str_to_ipv6(&args2.ing_dipv6_3, optarg, 3);
+		break;
+#if defined CONFIG_COLGIN_SUPPORT
+	case '9':
+		args2.rmt = strtoll(optarg, NULL, 10);
+		break;
+#endif
+	case 'E':
+		args2.hash_index = strtoll(optarg, NULL, 10);
+		break;
+#if defined CONFIG_COLGIN_SUPPORT
+	case 'F':
+		args2.frag = strtoll(optarg, NULL, 10);
+		break;
+	case 'H':
+		chksum_tmp = strtoll(optarg, NULL, 16);
+		chksum_tmp = (0xffff-chksum_tmp);
+		chksum_tmp = (chksum_tmp - org_tot_len - org_id);
+		chksum_base = chksum_tmp & 0xFFFF;
+		printf("chksum_base = %x\n", chksum_base);
+		args2.checksum = chksum_base;
+		break;
+	case 'R':
+		args2.ttl = strtoll(optarg, NULL, 10);
+		break;
+#endif
+	case 'a':
+		method = HW_NAT_ADD_ENTRY;
+		break;
+
+	case 'b':
+		method = HW_NAT_DEL_ENTRY;
+		break;
+	case 'z':
+		method = HW_NAT_DUMP_CACHE_ENTRY;
+		break;
+	case 'c':
+		method = HW_NAT_DUMP_ENTRY;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'I':
+		method = HW_NAT_INVALID_ENTRY;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'x':
+		method = HW_NAT_UNBIND_ENTRY;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'k':
+		method = HW_NAT_DROP_ENTRY;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'd':
+		method = HW_NAT_DEBUG;
+		debug = strtoll(optarg, NULL, 10);
+		break;
+#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+	case 'W':
+		method = HW_NAT_SWITCH_DSL_MAPE;
+		swit = strtoll(optarg, NULL, 10);
+		break;
+#endif
+	case 'e':
+		method = HW_NAT_GET_ALL_ENTRIES;
+		args->entry_state=0; /* invalid entry */
+		break;
+	case 'f':
+		method = HW_NAT_GET_ALL_ENTRIES;
+		args->entry_state=1; /* unbinded entry */
+		break;
+	case 'g':
+		method = HW_NAT_GET_ALL_ENTRIES;
+		args->entry_state=2; /* binded entry */
+		break;
+	case 'y':
+		method = HW_NAT_TBL_CLEAR;
+		break;
+	case 'A':
+		method = HW_NAT_GET_AC_CNT;
+		args3.ag_index = strtoll(optarg, NULL, 10);
+		break;
+#if defined (CONFIG_PPE_MCAST)
+	case 'B':
+		method = HW_NAT_MCAST_INS;
+		args5.mc_vid = strtoll(argv[2], NULL, 10);
+		str_to_mac(mac, argv[3]);
+		memcpy(args5.dst_mac, mac, sizeof(mac));
+		args5.mc_px_en = strtoll(argv[4], NULL, 10);
+		args5.mc_px_qos_en = strtoll(argv[5], NULL, 10);
+		args5.mc_qos_qid = strtoll(argv[6], NULL, 10);
+		break;
+	case 'C':
+		method = HW_NAT_MCAST_DEL;
+		args5.mc_vid = strtoll(argv[2], NULL, 10);
+		str_to_mac(mac, argv[3]);
+		memcpy(args5.dst_mac, mac, sizeof(mac));
+		memcpy(args5.dst_mac, mac, sizeof(mac));
+		args5.mc_px_en = strtoll(argv[4], NULL, 10);
+		args5.mc_px_qos_en = strtoll(argv[5], NULL, 10);
+		args5.mc_qos_qid = strtoll(argv[6], NULL, 10);
+		break;
+	case 'D':
+		method = HW_NAT_MCAST_DUMP;
+		break;
+#endif
+#if defined (CONFIG_PPE_MIB)
+	case 'm':
+		method = HW_NAT_MIB_DUMP;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'r':
+		method = HW_NAT_MIB_DRAM_DUMP;
+		entry_num = strtoll(optarg, NULL, 10);
+		break;
+	case 'M':
+		method = HW_NAT_MIB_GET;
+		break;
+#if defined CONFIG_COLGIN_SUPPORT
+	case 'X':
+		method = HW_NAT_MIB_GET_ALL_IP;
+		break;
+#endif
+#endif
+	case 'N':
+		method = HW_NAT_BIND_THRESHOLD;
+		args4.bind_threshold = strtoll(argv[2], NULL, 10);
+		break;
+	case 'Q':
+		method = HW_NAT_KA_INTERVAL;
+		args4.foe_tcp_ka = strtoll(argv[2], NULL, 10);
+		args4.foe_udp_ka = strtoll(argv[3], NULL, 10);
+		break;
+	case 'U':
+		method = HW_NAT_BIND_LIFETIME;
+		args4.foe_tcp_dlta = strtoll(argv[2], NULL, 10);
+		args4.foe_udp_dlta = strtoll(argv[3], NULL, 10);
+		args4.foe_fin_dlta = strtoll(argv[4], NULL, 10);
+		break;
+	case 'V':
+		method = HW_NAT_VLAN_ID;
+		args4.lan_vid = strtoll(argv[2], NULL, 10);
+		args4.wan_vid = strtoll(argv[3], NULL, 10);
+		break;
+	case 'Z':
+		method = HW_NAT_BIND_DIRECTION;
+		args4.bind_dir = strtoll(optarg, NULL, 10);
+		break;
+#if defined (CONFIG_HW_NAT_IPI)
+	case 'G': /*FIXME..........................*/
+		method = HW_NAT_IPI_CTRL_FROM_EXTIF;
+		args6.hnat_ipi_enable = strtoll(argv[2], NULL, 10);
+		args6.queue_thresh = strtoll(argv[3], NULL, 10);
+		args6.drop_pkt = strtoll(argv[4], NULL, 10);
+		args6.ipi_cnt_mod = strtoll(argv[5], NULL, 10);
+		//printf("##### hnat_ipi_enable=%d, queue_thresh=%d, drop_pkt=%d #####\n",
+		//		args6.hnat_ipi_enable, args6.queue_thresh, args6.drop_pkt);
+		break;
+	case 'L': /*FIXME..........................*/
+		method = HW_NAT_IPI_CTRL_FROM_PPEHIT;
+		args7.hnat_ipi_enable = strtoll(argv[2], NULL, 10);
+		args7.queue_thresh = strtoll(argv[3], NULL, 10);
+		args7.drop_pkt = strtoll(argv[4], NULL, 10);
+		args7.ipi_cnt_mod = strtoll(argv[5], NULL, 10);
+		//printf("##### hnat_ipi_enable2=%d, queue_thresh2=%d, drop_pkt2=%d #####\n",
+		//		args7.hnat_ipi_enable2, args7.queue_thresh2, args7.drop_pkt);
+		break;
+#endif
+	case '6':
+		method = HW_NAT_DPORT;
+		break;
+	case 'O':
+		method = HW_NAT_CLEAR_HOOK;
+		args2.dst_port = strtoll(optarg, NULL, 10);
+		break;
+	case 'T':
+		method = HW_NAT_RESTORE_HOOK;
+		args2.dst_port = strtoll(optarg, NULL, 10);
+		break;
+	case '?':
+		show_usage();
+
+	}
+    }
+
+    switch(method){
+//#if defined (CONFIG_HW_NAT_MANUAL_MODE) || defined (CONFIG_HW_NAT_SEMI_AUTO_MODE)
+    case HW_NAT_ADD_ENTRY:
+	    result = HwNatAddEntry(&args2);
+	    break;
+    case HW_NAT_DEL_ENTRY:
+	    result = HwNatDelEntry(&args2);
+	    break;
+//#endif
+    case HW_NAT_GET_ALL_ENTRIES:
+	    HwNatGetAllEntries(args);
+
+	    printf("Total Entry Count = %d\n",args->num_of_entries);
+	    for(i=0;i<args->num_of_entries;i++){
+		if(args->entries[i].pkt_type==0) { //IPV4_NAPT
+		    	printf("IPv4_NAPT=%d : %u.%u.%u.%u:%d->%u.%u.%u.%u:%d => %u.%u.%u.%u:%d->%u.%u.%u.%u:%d (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPQUAD(args->entries[i].ing_sipv4),
+				args->entries[i].ing_sp,
+				NIPQUAD(args->entries[i].ing_dipv4),
+				args->entries[i].ing_dp,
+				NIPQUAD(args->entries[i].eg_sipv4),
+				args->entries[i].eg_sp,
+				NIPQUAD(args->entries[i].eg_dipv4),
+				args->entries[i].eg_dp,
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		} else if(args->entries[i].pkt_type==1) { //IPV4_NAT
+			printf("IPv4_NAT=%d : %u.%u.%u.%u->%u.%u.%u.%u => %u.%u.%u.%u->%u.%u.%u.%u (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPQUAD(args->entries[i].ing_sipv4),
+				NIPQUAD(args->entries[i].ing_dipv4),
+				NIPQUAD(args->entries[i].eg_sipv4),
+				NIPQUAD(args->entries[i].eg_dipv4),
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		} else if(args->entries[i].pkt_type==2) { //IPV6_ROUTING
+			printf("IPv6_1T= %d /DIP: %x:%x:%x:%x:%x:%x:%x:%x (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		} else if(args->entries[i].pkt_type==3) { //IPV4_DSLITE
+		    	printf("DS-Lite= %d : %u.%u.%u.%u:%d->%u.%u.%u.%u:%d (%x:%x:%x:%x:%x:%x:%x:%x -> %x:%x:%x:%x:%x:%x:%x:%x)(RX=%d FP=%d FQOS=%d QID=%d)\n", \
+				args->entries[i].hash_index,
+				NIPQUAD(args->entries[i].ing_sipv4),
+				args->entries[i].ing_sp,
+				NIPQUAD(args->entries[i].ing_dipv4),
+				args->entries[i].ing_dp,
+				NIPHALF(args->entries[i].eg_sipv6_0),
+				NIPHALF(args->entries[i].eg_sipv6_1),
+				NIPHALF(args->entries[i].eg_sipv6_2),
+				NIPHALF(args->entries[i].eg_sipv6_3),
+				NIPHALF(args->entries[i].eg_dipv6_0),
+				NIPHALF(args->entries[i].eg_dipv6_1),
+				NIPHALF(args->entries[i].eg_dipv6_2),
+				NIPHALF(args->entries[i].eg_dipv6_3),
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		} else if(args->entries[i].pkt_type==4) { //IPV6_3T_ROUTE
+			printf("IPv6_3T= %d SIP: %x:%x:%x:%x:%x:%x:%x:%x DIP: %x:%x:%x:%x:%x:%x:%x:%x (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPHALF(args->entries[i].ing_sipv6_0),
+				NIPHALF(args->entries[i].ing_sipv6_1),
+				NIPHALF(args->entries[i].ing_sipv6_2),
+				NIPHALF(args->entries[i].ing_sipv6_3),
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		} else if(args->entries[i].pkt_type==5) { //IPV6_5T_ROUTE
+		    if(args->entries[i].ipv6_flowlabel==1) {
+			printf("IPv6_5T= %d SIP: %x:%x:%x:%x:%x:%x:%x:%x DIP: %x:%x:%x:%x:%x:%x:%x:%x (Flow Label=%x) (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPHALF(args->entries[i].ing_sipv6_0),
+				NIPHALF(args->entries[i].ing_sipv6_1),
+				NIPHALF(args->entries[i].ing_sipv6_2),
+				NIPHALF(args->entries[i].ing_sipv6_3),
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				((args->entries[i].ing_sp << 16) | (args->entries[i].ing_dp))&0xFFFFF,
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+
+		    }else {
+			printf("IPv6_5T= %d SIP: %x:%x:%x:%x:%x:%x:%x:%x %d DIP: %x:%x:%x:%x:%x:%x:%x:%x %d (RX=%d FP=%d FQOS=%d QID=%d)\n",
+				args->entries[i].hash_index,
+				NIPHALF(args->entries[i].ing_sipv6_0),
+				NIPHALF(args->entries[i].ing_sipv6_1),
+				NIPHALF(args->entries[i].ing_sipv6_2),
+				NIPHALF(args->entries[i].ing_sipv6_3),
+				args->entries[i].ing_sp,
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				args->entries[i].ing_dp,
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+		    }
+
+		} else if(args->entries[i].pkt_type==7) { //IPV6_6RD
+		    if(args->entries[i].ipv6_flowlabel==1) {
+			printf("6RD= %d %x:%x:%x:%x:%x:%x:%x:%x->%x:%x:%x:%x:%x:%x:%x:%x [Flow Label=%x]\n",
+				args->entries[i].hash_index, \
+				NIPHALF(args->entries[i].ing_sipv6_0),
+				NIPHALF(args->entries[i].ing_sipv6_1),
+				NIPHALF(args->entries[i].ing_sipv6_2),
+				NIPHALF(args->entries[i].ing_sipv6_3),
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				((args->entries[i].ing_sp << 16) | (args->entries[i].ing_dp))&0xFFFFF);
+				printf("(%u.%u.%u.%u->%u.%u.%u.%u)(RX=%d FP=%d FQOS=%d QID=%d)\n",
+					NIPQUAD(args->entries[i].eg_sipv4),
+					NIPQUAD(args->entries[i].eg_dipv4),
+					args->entries[i].rxif_idx,
+					args->entries[i].fport,
+					args->entries[i].fqos,
+					args->entries[i].qid);
+		    }else {
+			printf("6RD= %d /SIP: %x:%x:%x:%x:%x:%x:%x:%x [SP:%d] /DIP: %x:%x:%x:%x:%x:%x:%x:%x [DP=%d]",
+				args->entries[i].hash_index,
+				NIPHALF(args->entries[i].ing_sipv6_0),
+				NIPHALF(args->entries[i].ing_sipv6_1),
+				NIPHALF(args->entries[i].ing_sipv6_2),
+				NIPHALF(args->entries[i].ing_sipv6_3),
+				args->entries[i].ing_sp,
+				NIPHALF(args->entries[i].ing_dipv6_0),
+				NIPHALF(args->entries[i].ing_dipv6_1),
+				NIPHALF(args->entries[i].ing_dipv6_2),
+				NIPHALF(args->entries[i].ing_dipv6_3),
+				args->entries[i].ing_dp);
+			printf("(%u.%u.%u.%u->%u.%u.%u.%u)(RX=%d FP=%d FQOS=%d QID=%d)\n",
+				NIPQUAD(args->entries[i].eg_sipv4),
+				NIPQUAD(args->entries[i].eg_dipv4),
+				args->entries[i].rxif_idx,
+				args->entries[i].fport,
+				args->entries[i].fqos,
+				args->entries[i].qid);
+		    }
+		} else{
+		    printf("unknown packet type! (pkt_type=%d) \n", args->entries[i].pkt_type);
+		}
+	    }
+	    result = args->result;
+	    break;
+    case HW_NAT_DUMP_CACHE_ENTRY:
+	    result = HwNatCacheDumpEntry();
+	    break;
+    case HW_NAT_DUMP_ENTRY:
+	    result = HwNatDumpEntry(entry_num);
+	    break;
+    case HW_NAT_UNBIND_ENTRY:
+	    result = HwNatUnBindEntry(entry_num);
+	    break;
+    case HW_NAT_DROP_ENTRY:
+	    result = HwNatDropEntry(entry_num);
+	    break;
+    case HW_NAT_DEBUG:
+	    result = HwNatDebug(debug);
+	    break;
+#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+	case HW_NAT_SWITCH_DSL_MAPE:
+	    result = HwNatSwitchDsliteMape(swit);
+	    break;
+#endif
+    case HW_NAT_GET_AC_CNT:
+	    HwNatGetAGCnt(&args3);
+	    printf("Byte cnt=%llu\n", args3.ag_byte_cnt);
+	    printf("Pkt cnt=%llu\n", args3.ag_pkt_cnt);
+	    result = args3.result;
+	    break;
+
+    case HW_NAT_BIND_THRESHOLD:
+	    result = HwNatSetBindThreshold(&args4);
+	    break;
+    case HW_NAT_MAX_ENTRY_LMT:
+	    HwNatSetMaxEntryRateLimit(&args4);
+	    result = args4.result;
+	    break;
+    case HW_NAT_RULE_SIZE:
+	    HwNatSetRuleSize(&args4);
+	    result = args4.result;
+	    break;
+    case HW_NAT_KA_INTERVAL:
+	    HwNatSetKaInterval(&args4);
+	    result = args4.result;
+	    break;
+    case HW_NAT_UB_LIFETIME:
+	    HwNatSetUnbindLifeTime(&args4);
+	    result = args4.result;
+	    break;
+    case HW_NAT_BIND_LIFETIME:
+	    result = HwNatSetBindLifeTime(&args4);
+	    break;
+    case HW_NAT_VLAN_ID:
+	    result = HwNatSetVID(&args4);
+	    break;
+    case HW_NAT_BIND_DIRECTION:
+	    result = HwNatSetBindDir(&args4);
+	    break;
+#if defined (CONFIG_PPE_MCAST)
+    case HW_NAT_MCAST_INS:
+	    result = HwNatMcastIns(&args5);
+	    break;
+    case HW_NAT_MCAST_DEL:
+	    result = HwNatMcastDel(&args5);
+	    break;
+    case HW_NAT_MCAST_DUMP:
+	    result = HwNatMcastDump();
+	    break;
+#endif
+#if defined (CONFIG_PPE_MIB)
+    case HW_NAT_MIB_DUMP:
+	    result = HwNatMibDumpEntry(entry_num);
+	    break;
+    case HW_NAT_MIB_DRAM_DUMP:
+	    result = HwNatMibDramDumpEntry(entry_num);
+	    break;
+    case HW_NAT_MIB_GET:
+	    result = HwNatMibGet(&args2);
+	    break;
+#if defined CONFIG_COLGIN_SUPPORT
+	case HW_NAT_MIB_GET_ALL_IP:
+		args8=malloc(sizeof(struct hwnat_mib_all_ip_args));
+		if (NULL == args8)
+		{
+			printf(" Allocate memory for hwnat_mib_all_ip_args failed.\n");
+			close(fd);
+			return 0;
+		}
+		memset(args8, 0, sizeof(struct hwnat_mib_all_ip_args));
+		result = HwNatMibGetAllIP(args8);
+        dump_all_ip_cnt(args8);
+        free(args8);
+	    break;
+#endif
+#endif
+    case HW_NAT_TBL_CLEAR:
+            result = HwNatTblClear();
+            break;
+#if defined (CONFIG_HW_NAT_IPI)
+    case HW_NAT_IPI_CTRL_FROM_EXTIF:
+	    result = HwNatIPICtrlFromExtIf(&args6);
+	    break;
+    case HW_NAT_IPI_CTRL_FROM_PPEHIT:
+	    result = HwNatIPICtrlFromPPEHit(&args7);
+	    break;
+#endif
+    case HW_NAT_DPORT:
+    	    result = HwNatDumpDport();
+    	    break;
+    case HW_NAT_INVALID_ENTRY:
+	    result = HwNatInvalEntry(entry_num);
+	    break;
+    case HW_NAT_CLEAR_HOOK:
+    	    result = HwNatHookModify(&args2, 1);
+    	    break;
+    case HW_NAT_RESTORE_HOOK:
+    	    result = HwNatHookModify(&args2, 0);
+    	    break;
+    default:
+	    result = HWNAT_FAIL;
+
+    }
+
+    if(result==HWNAT_SUCCESS){
+	printf("done\n");
+    }else if(result==HWNAT_ENTRY_NOT_FOUND) {
+	printf("entry not found\n");
+    }else {
+	printf("fail\n");
+    }
+
+    free(args);
+    close(fd);
+    return 0;
+}
diff --git a/src/extended/hw_nat/hwnat_api.c b/src/extended/hw_nat/hwnat_api.c
new file mode 100644
index 0000000..1ce5b24
--- /dev/null
+++ b/src/extended/hw_nat/hwnat_api.c
@@ -0,0 +1,764 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#ifndef CONFIG_SUPPORT_OPENWRT
+#include <linux/autoconf.h>
+#endif
+#if defined CONFIG_COLGIN_SUPPORT
+#include "hnat_ioctl.h"
+#else
+#include "hwnat_ioctl.h"
+#endif
+
+int HwNatInvalEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_INVALID_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatDumpDport(void)
+{
+    int fd;
+    struct hwnat_args opt;
+  
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+    if(ioctl(fd, HW_NAT_DPORT, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+#if defined (CONFIG_HW_NAT_IPI)
+int HwNatIPICtrlFromExtIf(struct hwnat_ipi_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_IPI_CTRL_FROM_EXTIF, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatIPICtrlFromPPEHit(struct hwnat_ipi_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_IPI_CTRL_FROM_PPEHIT, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+#endif
+
+int HwNatDelEntry(struct hwnat_tuple *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+    if(ioctl(fd, HW_NAT_DEL_ENTRY, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatAddEntry(struct hwnat_tuple *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_ADD_ENTRY, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatHookModify(struct hwnat_tuple *opt, int clear)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+    if(ioctl(fd, (clear == 1) ? HW_NAT_CLEAR_HOOK : HW_NAT_RESTORE_HOOK, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+
+
+#if defined (CONFIG_PPE_MIB)
+int HwNatMibDumpEntry(unsigned int entry_num)
+{
+    struct hwnat_mib_args opt;
+    int fd;
+    opt.entry_num=entry_num;
+    printf("!!!!!!!!HwNatMibDumpEntry\n");
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MIB_DUMP, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+int HwNatMibDramDumpEntry(unsigned int entry_num)
+{
+    struct hwnat_mib_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MIB_DRAM_DUMP, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatMibGet(struct hwnat_tuple *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MIB_GET, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+#if defined CONFIG_COLGIN_SUPPORT
+int HwNatMibGetAllIP(struct hwnat_mib_all_ip_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+        printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+        return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MIB_GET_ALL_IP, opt)<0) {
+        printf("HW_NAT_API: ioctl error\n");
+        close(fd);
+        return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+#endif
+#endif
+
+int HwNatTblClear(void)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_TBL_CLEAR, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatDumpEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_DUMP_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatBindEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_BIND_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatUnBindEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_UNBIND_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return  HWNAT_FAIL;
+    }
+
+    close(fd);
+    return  HWNAT_SUCCESS;
+}
+
+int HwNatDropEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_DROP_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return  HWNAT_FAIL;
+    }
+
+    close(fd);
+    return  HWNAT_SUCCESS;
+}
+
+
+
+int HwNatInvalidEntry(unsigned int entry_num)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.entry_num=entry_num;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_INVALID_ENTRY, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatCacheDumpEntry(void)
+{
+
+    struct hwnat_args opt;
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+    if(ioctl(fd, HW_NAT_DUMP_CACHE_ENTRY, &opt)<0) {
+
+
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatGetAGCnt(struct hwnat_ac_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_GET_AC_CNT, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetBindThreshold(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_BIND_THRESHOLD, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetMaxEntryRateLimit(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MAX_ENTRY_LMT, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+
+int HwNatSetRuleSize(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_RULE_SIZE, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetKaInterval(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_KA_INTERVAL, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetUnbindLifeTime(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_UB_LIFETIME, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetBindLifeTime(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_BIND_LIFETIME, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatSetVID(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_VLAN_ID, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatSetBindDir(struct hwnat_config_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_BIND_DIRECTION, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatGetAllEntries(struct hwnat_args *opt)
+{
+    int fd=0;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_GET_ALL_ENTRIES, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    
+
+    return HWNAT_SUCCESS;
+
+}
+
+int HwNatDebug(unsigned int debug)
+{
+    struct hwnat_args opt;
+    int fd;
+
+    opt.debug=debug;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_DEBUG, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
+int HwNatSwitchDsliteMape(unsigned int swit)
+{
+	struct hwnat_args opt;
+    int fd;
+
+    opt.swit=swit;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_SWITCH_DSL_MAPE, &opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+#endif
+
+#ifdef CONFIG_PPE_MCAST
+int HwNatMcastIns(struct hwnat_mcast_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MCAST_INS, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatMcastDel(struct hwnat_mcast_args *opt)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MCAST_DEL, opt)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+
+int HwNatMcastDump(void)
+{
+    int fd;
+
+    fd = open("/dev/"HW_NAT_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"HW_NAT_DEVNAME);
+	return HWNAT_FAIL;
+    }
+
+    if(ioctl(fd, HW_NAT_MCAST_DUMP, NULL)<0) {
+	printf("HW_NAT_API: ioctl error\n");
+	close(fd);
+	return HWNAT_FAIL;
+    }
+
+    close(fd);
+    return HWNAT_SUCCESS;
+}
+#endif
diff --git a/src/extended/hw_nat/hwnat_api.h b/src/extended/hw_nat/hwnat_api.h
new file mode 100644
index 0000000..c816be4
--- /dev/null
+++ b/src/extended/hw_nat/hwnat_api.h
@@ -0,0 +1,62 @@
+#ifndef __HW_NAT_API
+#define __HW_NAT_API
+
+#define NIPQUAD(addr) \
+	((unsigned char *)&addr)[3], \
+        ((unsigned char *)&addr)[2], \
+        ((unsigned char *)&addr)[1], \
+        ((unsigned char *)&addr)[0]
+#define NIPHALF(addr) \
+        ((unsigned short *)&addr)[1], \
+        ((unsigned short *)&addr)[0]
+
+int HwNatAddEntry(struct hwnat_tuple *opt);
+int HwNatDelEntry(struct hwnat_tuple *opt);
+int HwNatDumpEntry(unsigned int entry_num);
+int HwNatBindEntry(unsigned int entry_num);
+int HwNatUnBindEntry(unsigned int entry_num);
+int HwNatDropEntry(unsigned int entry_num);
+int HwNatInvalidEntry(unsigned int entry_num);
+int HwNatDscpRemarkEbl(struct hwnat_qos_args *opt);
+int HwNatVpriRemarkEbl(struct hwnat_qos_args *opt);
+int HwNatSetFoeWeight(struct hwnat_qos_args *opt);
+int HwNatSetAclWeight(struct hwnat_qos_args *opt);
+int HwNatSetDscpWeight(struct hwnat_qos_args *opt);
+int HwNatSetVpriWeight(struct hwnat_qos_args *opt);
+int HwNatSetDscp_Up(struct hwnat_qos_args *opt);
+int HwNatSetUp_InDscp(struct hwnat_qos_args *opt);
+int HwNatSetUp_OutDscp(struct hwnat_qos_args *opt);
+int HwNatSetUp_Vpri(struct hwnat_qos_args *opt);
+int HwNatSetUp_Ac(struct hwnat_qos_args *opt);
+int HwNatSetSchMode(struct hwnat_qos_args *opt);
+int HwNatSetSchWeight(struct hwnat_qos_args *opt);
+int HwNatSetBindThreshold(struct hwnat_config_args *opt);
+int HwNatSetMaxEntryRateLimit(struct hwnat_config_args *opt);
+int HwNatSetRuleSize(struct hwnat_config_args *opt);
+int HwNatSetKaInterval(struct hwnat_config_args *opt);
+int HwNatSetUnbindLifeTime(struct hwnat_config_args *opt);
+int HwNatSetBindLifeTime(struct hwnat_config_args *opt);
+int HwNatSetVID(struct hwnat_config_args *opt);
+int HwNatSetBindDir(struct hwnat_config_args *opt);
+int HwNatGetAllEntries(struct hwnat_args *opt);
+int HwNatDebug(unsigned int debug);
+int HwNatGetAGCnt(struct hwnat_ac_args *opt);
+#if defined (CONFIG_PPE_MCAST)
+int HwNatMcastIns(struct hwnat_mcast_args *opt);
+int HwNatMcastDel(struct hwnat_mcast_args *opt);
+int HwNatMcastDump(void);
+#endif
+#if defined (CONFIG_PPE_MIB)
+int HwNatMibDumpEntry(unsigned int entry_num);
+int HwNatMibGet(struct hwnat_tuple *opt);
+int HwNatMibDramDumpEntry(unsigned int entry_num);
+#if defined CONFIG_COLGIN_SUPPORT
+int HwNatMibGetAllIP(struct hwnat_mib_all_ip_args *opt);
+#endif
+#endif
+int HwNatTblClear(void);
+int HwNatCacheDumpEntry(void);
+int HwNatDumpDport(void);
+int HwNatInvalEntry(unsigned int entry_num);
+int HwNatHookModify(struct hwnat_tuple *opt, int clear);
+#endif
diff --git a/src/extended/hw_nat/mtr.c b/src/extended/hw_nat/mtr.c
new file mode 100644
index 0000000..089320e
--- /dev/null
+++ b/src/extended/hw_nat/mtr.c
@@ -0,0 +1,283 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef CONFIG_SUPPORT_OPENWRT
+#include "linux/autoconf.h"
+#endif
+#include "mtr_ioctl.h"
+#include "mtr_api.h"
+
+
+void show_usage(void)
+{
+
+    printf("Add Mac Upload Meter Rule\n");
+    printf("mtr -a -m [Mac] -t [KB/s] -s [BucketSize:4K/8K/16K/32K or 0~127]\n");
+    printf("    -u [MtrIntval:1ms/10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms] -v [Base:Byte/Pkt]\n");
+    printf("ByteBase:mtr -a -m 00:11:22:33:44:55 -t 10 -s 8K -v Byte\n\n");
+    printf("PktBase:mtr -a -m 00:11:22:33:44:55 -s 100 -u 1ms -v Pkt\n\n");
+
+    printf("Add Mac Download Meter Rule\n");
+    printf("mtr -b -m [Mac] -t [KB/s] -s [BucketSize:4K/8K/16K/32K or 0~127]\n");
+    printf("    -u [MtrIntval:1ms/10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms] -v [Base:Byte/Pkt]\n");
+    printf("ByteBase: mtr -b -m 00:11:22:33:44:55 -t 10 -s 8K -v Byte\n\n");
+    printf("PktBase: mtr -b -m 00:11:22:33:44:55 -s 100 -u 1ms -v Pkt\n\n");
+    printf("Del Mac Upload Meter Rule\n");
+    printf("mtr -c -m [Mac]\n");
+    printf("Ex: mtr -c -m 00:11:22:33:44:55\n\n");
+    
+    printf("Del Mac download Meter Rule\n");
+    printf("mtr -d -m [Mac]\n");
+    printf("Ex: mtr -d -m 00:11:22:33:44:55\n\n");
+   
+
+    printf("Add IP Upload Meter Rule\n");
+    printf("mtr -e -i [IpS] -j [IpE] -t [KB/s] -s [BucketSize:4K/8K/16K/32K or 0~127]\n");
+    printf("    -u [MtrIntval:1ms/10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms] -v [Base:Byte/Pkt]\n");
+    printf("ByteBase: mtr -e -i 10.10.10.3 -j 10.10.10.3 -t 10 -s 8K -v Byte\n\n");
+    printf("PktBase: mtr -e -i 10.10.10.3 -j 10.10.10.3 -s 100 -u 1ms -v Pkt\n\n");
+    
+    printf("Add IP Download Meter Rule\n");
+    printf("mtr -f -i [IpS] -j [IpE] -t [KB/s] -s [BucketSize:4K/8K/16K/32K or 0~127] \n");
+    printf("    -u [MtrIntval:1ms/10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms] -v [Base:Byte/Pkt]\n");
+    printf("ByteBase: mtr -f -i 10.10.10.3 -t 10 -s 8K -v Byte\n\n");
+    printf("PktBase: mtr -f -i 10.10.10.3 -j 10.10.10.3 -s 100 -u 50ms -v Pkt\n\n");
+
+    printf("Del IP Upload Meter Rule\n");
+    printf("mtr -g -i [IpS] -j [IpE]\n");
+    printf("mtr -g -i 10.10.10.3 -j 10.10.10.3\n\n");
+
+    printf("Del IP Download Meter Rule\n");
+    printf("mtr -h -i [IpS] -j [IpE]\n");
+    printf("mtr -h -i 10.10.10.3 -j 10.10.10.3\n\n");
+
+    printf("Clear Meter Table\n");
+    printf("mtr -z\n\n");
+
+    printf("Add SYN  Meter Rule: mtr -k\n");
+    printf("Add FIN  Meter Rule: mtr -l\n");
+    printf("Add UDP  Meter Rule: mtr -n\n");
+    printf("Add ICMP Meter Rule: -o\n");
+    printf(" -t [KB/s] -s [BucketSize:4K/8K/16K/32K or 0~127]\n");
+    printf(" -u [MtrIntval:1ms/10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms] -v [Base:Byte/Pkt]\n\n");
+    printf("Del SYN  Meter Rule:mtr -p\n");
+    printf("Del FIN  Meter Rule:mtr -q\n");
+    printf("Del UDP  Meter Rule:mtr -r\n");
+    printf("Del ICMP Meter Rule:mtr -y\n\n");
+
+    printf("Get All Mtr Entries: mtr -w\n");
+}
+
+int main(int argc, char *argv[])
+{
+    int opt;
+    char options[] = "abcdefghklnopqryz?m:i:j:t:s:u:v:w";
+
+    int fd;
+    int method=-1;
+    struct mtr_args args;
+    struct mtr_list_args *args2;
+    int result;
+    int i;
+
+    args2=malloc(sizeof(struct mtr_list_args) + sizeof(struct mtr_args)*511);
+    if (NULL == args2)
+    {
+	    printf(" allocate memory for mtr_list_args and mtr_args failed.\n");
+	    return 0;
+    }
+    fd = open("/dev/"MTR_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"MTR_DEVNAME);
+        free(args2);
+	return 0;
+    }
+
+    if(argc < 2) {
+	show_usage();
+        free(args2);
+        close(fd);
+	return 0;
+    }
+
+
+    while ((opt = getopt (argc, argv, options)) != -1) {
+	switch (opt) {
+	case 'a':  
+	    method=MTR_ADD_MAC_UL_ENTRY;
+	    break;
+	case 'b':  
+	    method=MTR_ADD_MAC_DL_ENTRY;
+	    break;
+	case 'c': 
+	    method=MTR_DEL_MAC_UL_ENTRY;
+	    break;
+	case 'd': 
+	    method=MTR_DEL_MAC_DL_ENTRY;
+	    break;
+	case 'e': 
+	    method=MTR_ADD_IP_UL_ENTRY;
+	    break;
+	case 'f': 
+	    method=MTR_ADD_IP_DL_ENTRY;
+	    break;
+	case 'g': 
+	    method=MTR_DEL_IP_UL_ENTRY;
+	    break;
+	case 'h': 
+	    method=MTR_DEL_IP_DL_ENTRY;
+	    break;
+	case 'k': 
+	    method=MTR_ADD_SYN_ENTRY;
+	    break;
+	case 'l': 
+	    method=MTR_ADD_FIN_ENTRY;
+	    break;
+	case 'n': 
+	    method=MTR_ADD_UDP_ENTRY;
+	    break;
+ 	case 'o': 
+	    method=MTR_ADD_ICMP_ENTRY;
+	    break;
+	case 'p': 
+	    method=MTR_DEL_SYN_ENTRY;
+	    break;
+	case 'q': 
+	    method=MTR_DEL_FIN_ENTRY;
+	    break;
+	case 'r': 
+	    method=MTR_DEL_UDP_ENTRY;
+	    break;
+	case 'y': 
+	    method=MTR_DEL_ICMP_ENTRY;
+	    break;
+	case 'z': /* CleanTbl */
+	    method=MTR_CLEAN_TBL;
+	    break;
+	case 'm': /* Mac */
+	    str_to_mac(args.mac, optarg);
+	    break;
+	case 'i': /* IpS */
+	    str_to_ip(&args.ip_s, optarg);
+	    break;
+	case 'j': /* IpE */
+	    str_to_ip(&args.ip_e, optarg);
+	    break;
+	case 't': /* TokenRate */
+	    args.token_rate=strtoll(optarg, NULL, 10);
+	    break;
+	case 's': /* Bucket Size */
+	    if(strcasecmp(optarg,"4K")==0){
+		args.bk_size=0;
+	    }else if(strcasecmp(optarg,"8K")==0){
+		args.bk_size=1;
+	    }else if(strcasecmp(optarg,"16K")==0){
+		args.bk_size=2;
+	    }else if(strcasecmp(optarg,"32K")==0){
+		args.bk_size=3;
+	    }else {
+		args.bk_size=strtoll(optarg, NULL, 10);
+	    }
+	    break;
+	case 'u':
+	    if(strcasecmp(optarg,"1ms")==0){
+		args.mtr_intval=_1MS;
+	    }else if(strcasecmp(optarg,"10ms")==0){
+		args.mtr_intval=_10MS;
+	    }else if(strcasecmp(optarg,"50ms")==0){
+		args.mtr_intval=_50MS;
+	    }else if(strcasecmp(optarg,"100ms")==0){
+		args.mtr_intval=_100MS;
+	    }else if(strcasecmp(optarg,"500ms")==0){
+		args.mtr_intval=_500MS;
+	    }else if(strcasecmp(optarg,"1000ms")==0){
+		args.mtr_intval=_1000MS;
+	    }else if(strcasecmp(optarg,"5000ms")==0){
+		args.mtr_intval=_5000MS;
+	    }else if(strcasecmp(optarg,"10000ms")==0){
+		args.mtr_intval=_10000MS;
+	    }else {
+		printf("Error: -u 10ms/50ms/100ms/500ms/1000ms/5000ms/10000ms\n");
+                free(args2);
+                close(fd);
+		return 0;
+	    }
+	    break;
+	case 'v':
+	    if(strcasecmp(optarg,"Byte")==0){
+		args.mtr_mode=0;
+	    }else if(strcasecmp(optarg,"Pkt")==0){
+		args.mtr_mode=1;
+	    }else {
+		printf("Error: -v Byte/Pkt\n");
+                free(args2);
+                close(fd);
+		return 0;
+	    }
+	    break;
+	case 'w':
+	    method=MTR_GET_ALL_ENTRIES;
+	    break;
+	case '?': /* Help */
+	    show_usage();
+	    break;
+	}
+    } 
+
+    switch(method) 
+    {
+    case MTR_ADD_MAC_UL_ENTRY:
+    case MTR_ADD_MAC_DL_ENTRY:
+    case MTR_DEL_MAC_UL_ENTRY:
+    case MTR_DEL_MAC_DL_ENTRY:
+    case MTR_ADD_IP_UL_ENTRY:
+    case MTR_ADD_IP_DL_ENTRY:
+    case MTR_DEL_IP_UL_ENTRY:
+    case MTR_DEL_IP_DL_ENTRY:
+    case MTR_CLEAN_TBL:
+    case MTR_ADD_SYN_ENTRY:
+    case MTR_ADD_FIN_ENTRY:
+    case MTR_ADD_UDP_ENTRY:
+    case MTR_ADD_ICMP_ENTRY:
+    case MTR_DEL_SYN_ENTRY:
+    case MTR_DEL_FIN_ENTRY:
+    case MTR_DEL_UDP_ENTRY:
+    case MTR_DEL_ICMP_ENTRY:
+	    SetMtrEntry(&args, method);
+	    result = args.result;
+	    break;
+    case MTR_GET_ALL_ENTRIES:
+	    MtrGetAllEntries(args2);
+	    result = args2->result;
+
+	    printf("Total Entry Count = %d\n",args2->num_of_entries);
+	    for(i=0;i<args2->num_of_entries;i++){
+		printf("#%d :MAC=%02X:%02X:%02X:%02X:%02X:%02X\n", \
+			i, args2->entries[i].mac[0], args2->entries[i].mac[1], args2->entries[i].mac[2], \
+			args2->entries[i].mac[3], args2->entries[i].mac[4], args2->entries[i].mac[5]);
+		printf("   :SIP %u.%u.%u.%u->%u.%u.%u.%u\n\r", NIPQUAD(args2->entries[i].ip_s), NIPQUAD(args2->entries[i].ip_e));
+		printf("   :BucketSize=%d Token_Rate:%d MtrInterval=%d\n", args2->entries[i].bk_size, args2->entries[i].token_rate, args2->entries[i].mtr_intval);
+	    }
+	    break;
+    default:
+	    result = MTR_FAIL;
+    }
+
+
+    if(result == MTR_TBL_FULL) {
+	printf("table full\n");
+    }else if(result == MTR_FAIL){
+	printf("fail\n");
+    }else{
+	printf("done\n");
+    }
+
+    free(args2);
+    close(fd);
+    return 0;
+}
diff --git a/src/extended/hw_nat/mtr_api.c b/src/extended/hw_nat/mtr_api.c
new file mode 100644
index 0000000..7923018
--- /dev/null
+++ b/src/extended/hw_nat/mtr_api.c
@@ -0,0 +1,52 @@
+#include <stdlib.h>             
+#include <stdio.h>             
+#include <string.h>           
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include "mtr_ioctl.h"
+
+int SetMtrEntry(struct mtr_args *opt, unsigned int cmd)
+{
+    int fd;
+
+    fd = open("/dev/"MTR_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+	printf("Open %s pseudo device failed\n","/dev/"MTR_DEVNAME);
+	return MTR_FAIL;
+    }
+
+    if(ioctl(fd, cmd, opt)<0) {
+	printf("MTR_API: ioctl error\n");
+	close(fd);
+	return MTR_FAIL;
+    }
+
+    close(fd);
+    return MTR_SUCCESS;
+}
+
+int MtrGetAllEntries(struct mtr_list_args *opt)
+{
+    int fd=0;
+
+    fd = open("/dev/"MTR_DEVNAME, O_RDONLY);
+    if (fd < 0)
+    {
+        printf("Open %s pseudo device failed\n","/dev/"MTR_DEVNAME);
+        return MTR_FAIL;
+    }
+
+    if(ioctl(fd, MTR_GET_ALL_ENTRIES, opt)<0) {
+        printf("MTR_API: ioctl error\n");
+        close(fd);
+        return MTR_FAIL;
+    }
+
+    close(fd);
+
+    return MTR_SUCCESS;
+
+}
+
diff --git a/src/extended/hw_nat/mtr_api.h b/src/extended/hw_nat/mtr_api.h
new file mode 100644
index 0000000..dd3fbb9
--- /dev/null
+++ b/src/extended/hw_nat/mtr_api.h
@@ -0,0 +1,16 @@
+#ifndef __MTR_API
+#define __MTR_API
+
+#define NIPQUAD(addr) \
+            ((unsigned char *)&addr)[3], \
+        ((unsigned char *)&addr)[2], \
+        ((unsigned char *)&addr)[1], \
+        ((unsigned char *)&addr)[0]
+#define NIPHALF(addr) \
+            ((unsigned short *)&addr)[1], \
+        ((unsigned short *)&addr)[0]
+
+int SetMtrEntry(struct mtr_args *opt, unsigned int cmd);
+int MtrGetAllEntries(struct mtr_list_args *opt);
+
+#endif
diff --git a/src/extended/hw_nat/util.c b/src/extended/hw_nat/util.c
new file mode 100644
index 0000000..921b3a4
--- /dev/null
+++ b/src/extended/hw_nat/util.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+int
+getnext (
+        char *  src,
+        int     separator,
+        char *  dest
+        )
+{
+        char *  c;
+        int     len;
+
+        if ( (src == NULL) || (dest == NULL) ) {
+                return -1;
+        }
+
+        c = strchr(src, separator);
+        if (c == NULL) {
+                return -1;
+        }
+        len = c - src;
+        strncpy(dest, src, len);
+        dest[len] = '\0';
+        return len + 1;
+}
+
+int
+str_to_mac (
+        unsigned char * mac,
+        char *          str
+        )
+{
+        int             len;
+        char *          ptr = str;
+        char            buf[128];
+        int             i;
+
+        for (i = 0; i < 5; i++) {
+                if ((len = getnext(ptr, ':', buf)) == -1) {
+                        return 1; /* parse error */
+                }
+                mac[i] = strtol(buf, NULL, 16);
+                ptr += len;
+        }
+        mac[5] = strtol(ptr, NULL, 16);
+
+        return 0;
+}
+
+int
+str_to_ip (
+        unsigned int * ip,
+        char *          str
+        )
+{
+        int             len;
+        char *          ptr = str;
+        char            buf[128];
+        unsigned char   c[4];
+        int             i;
+
+        for (i = 0; i < 3; ++i) {
+                if ((len = getnext(ptr, '.', buf)) == -1) {
+                        return 1; /* parse error */
+                }
+                c[i] = atoi(buf);
+                ptr += len;
+        }
+        c[3] = atoi(ptr);
+        *ip = (c[0]<<24) + (c[1]<<16) + (c[2]<<8) + c[3];
+        return 0;
+}
+
+int
+str_to_ipv6 (
+        unsigned int * ipv6,
+        char *          str,
+        unsigned int byte)
+{
+        int             len;
+        char *          ptr = str;
+        char            buf[128];
+        unsigned short  c[8];
+        int             i;
+        for (i = 0; i < 7; i++) {
+		
+                if ((len = getnext(ptr, ':', buf)) == -1) {
+                        return 1; /* parse error */
+                }
+                c[i] = strtoul(buf, NULL, 16);
+                ptr += len;
+                //printf("len=%d, c[%d]=%x\n",len, i, c[i]);
+                
+        }
+        c[7] = atoi(ptr);
+        *ipv6 = (c[2*byte] <<16) + (c[2*byte + 1]);
+        return 0;
+}
+
diff --git a/src/extended/hw_nat/util.h b/src/extended/hw_nat/util.h
new file mode 100644
index 0000000..aa57d19
--- /dev/null
+++ b/src/extended/hw_nat/util.h
@@ -0,0 +1,3 @@
+int str_to_mac (unsigned char *mac, char *str);
+int str_to_ip (unsigned int *ip, char *str);
+int str_to_ipv6 ( unsigned int * ipv6, char *str, unsigned int byte);