[][MAC80211][hnat][Move Netfilter Netlink Ftnl package to feed]

[Description]
Refactor Netfilter Netlink Ftnl patch.

If without this patch, this package might not be applied on the RDKB.

[Release-log]
N/A


Change-Id: Iefdfdea1e4480ac5fe9195b0f8b1b52706b76b05
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7217027
diff --git a/autobuild_mac80211_release/0005-add-netfilter-netlink-ftnl-package.patch b/autobuild_mac80211_release/0005-add-netfilter-netlink-ftnl-package.patch
index 4789e02..2283cac 100644
--- a/autobuild_mac80211_release/0005-add-netfilter-netlink-ftnl-package.patch
+++ b/autobuild_mac80211_release/0005-add-netfilter-netlink-ftnl-package.patch
@@ -16,358 +16,6 @@
 + 
 + #ifdef __KERNEL__
 + 
-diff --git a/package/mtk/applications/flowtable/Makefile b/package/mtk/applications/flowtable/Makefile
-new file mode 100755
-index 00000000..150a1a3b
---- /dev/null
-+++ b/package/mtk/applications/flowtable/Makefile
-@@ -0,0 +1,51 @@
-+#
-+# Copyright (C) 2009-2013 OpenWrt.org
-+#
-+# This is free software, licensed under the GNU General Public License v2.
-+# See /LICENSE for more information.
-+#
-+
-+include $(TOPDIR)/rules.mk
-+
-+PKG_NAME:=netfilter_flowtable
-+PKG_VERSION:=1.0
-+PKG_RELEASE:=1
-+
-+PKG_LICENSE:=GPL-2.0+
-+#PKG_INSTALL:=1
-+
-+include $(INCLUDE_DIR)/package.mk
-+
-+define Package/netfilter-flowtable
-+  SECTION:=MTK Properties
-+  CATEGORY:=MTK Properties
-+  DEPENDS:=+libnfnetlink +libmnl +kmod-nf-flow-netlink
-+  TITLE:=API to the in-kernel flow offload table
-+  SUBMENU:=Applications
-+endef
-+
-+define Package/netfilter-flowtable/description
-+  API to the in-kernel flow offload table
-+endef
-+
-+TARGET_CFLAGS += $(FPIC)
-+
-+TARGET_CPPFLAGS := \
-+	-D_GNU_SOURCE \
-+	-I$(LINUX_DIR)/user_headers/include \
-+	-I$(PKG_BUILD_DIR) \
-+	$(TARGET_CPPFLAGS) \
-+
-+define Build/Compile
-+	CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
-+	$(MAKE) -C $(PKG_BUILD_DIR) \
-+		$(TARGET_CONFIGURE_OPTS) \
-+		LIBS="$(TARGET_LDFLAGS) -lnfnetlink  -lm"
-+endef
-+
-+define Package/netfilter-flowtable/install
-+	$(INSTALL_DIR) $(1)/usr/bin
-+	$(CP) $(PKG_BUILD_DIR)/ftnl $(1)/usr/bin/
-+endef
-+
-+$(eval $(call BuildPackage,netfilter-flowtable))
-\ No newline at end of file
-diff --git a/package/mtk/applications/flowtable/src/Makefile b/package/mtk/applications/flowtable/src/Makefile
-new file mode 100644
-index 00000000..3f450ad2
---- /dev/null
-+++ b/package/mtk/applications/flowtable/src/Makefile
-@@ -0,0 +1,9 @@
-+EXEC = ftnl
-+SRC = api.c ftnl.c
-+
-+all:$(EXEC)
-+$(EXEC):$(SRC)
-+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) $(LDLIBS) $(LIBS)
-+
-+clean:
-+	-rm -f $(EXEC) *.elf *.gdb *.o
-diff --git a/package/mtk/applications/flowtable/src/api.c b/package/mtk/applications/flowtable/src/api.c
-new file mode 100644
-index 00000000..17b88b43
---- /dev/null
-+++ b/package/mtk/applications/flowtable/src/api.c
-@@ -0,0 +1,106 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include "netfilter_flowtable.h"
-+
-+static void attr_dump(struct nfattr *attr)
-+{
-+	char *data = nla_data(attr);
-+	int i = 0;
-+
-+	while (i < nal_len(attr)) {
-+		printf("%x ", *(data + i));
-+		i++;
-+		if (i % 16 == 0)
-+			printf("\n");
-+	}
-+	printf("\n");
-+}
-+
-+struct ftnl_handle* ftnl_open(void)
-+{
-+	struct ftnl_handle *h = NULL;
-+
-+	h = malloc(sizeof(struct ftnl_handle));
-+	if (!h)
-+		return NULL;
-+
-+	h->nfnlh = nfnl_open();
-+	if (!h->nfnlh) {
-+		printf("nfnl open fail\n");
-+		free(h);
-+		return NULL;
-+	}
-+
-+	h->ftnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_FLOWTABLE, 1, 0);
-+	if (!h->ftnlssh) {
-+		nfnl_close(h->nfnlh);
-+		printf("subsys open fail\n");
-+		free(h);
-+		return NULL;
-+	}
-+
-+	return h;
-+}
-+
-+void ftnl_close(struct ftnl_handle *h)
-+{
-+	nfnl_subsys_close(h->ftnlssh);
-+	nfnl_close(h->nfnlh);
-+	free(h);
-+}
-+
-+static void build_tuple(struct nlmsghdr *nlh,size_t size, struct flow_tuple *tuple)
-+{
-+	struct nfattr *nest_tuple, *nest_ip, *nest_proto;
-+
-+	nest_tuple = nfnl_nest(nlh, size, FTA_TUPLE);
-+
-+	nest_ip = nfnl_nest(nlh, size, FTA_TUPLE_IP);
-+	nfnl_addattr_l(nlh, size, FTA_IP_V4_SRC, &tuple->sip4, sizeof(uint32_t));
-+	nfnl_addattr_l(nlh, size, FTA_IP_V4_DST, &tuple->dip4, sizeof(uint32_t));
-+	nfnl_nest_end(nlh, nest_ip);
-+
-+	nest_proto = nfnl_nest(nlh, size, FTA_TUPLE_PROTO);
-+	nfnl_addattr_l(nlh, size, FTA_PROTO_NUM, &tuple->proto, sizeof(uint8_t));
-+	nfnl_addattr_l(nlh, size, FTA_PROTO_SPORT, &tuple->sport, sizeof(uint16_t));
-+	nfnl_addattr_l(nlh, size, FTA_PROTO_DPORT, &tuple->dport, sizeof(uint16_t));
-+	nfnl_nest_end(nlh, nest_proto);
-+
-+	nfnl_nest_end(nlh,nest_tuple);
-+//	attr_dump(nest_tuple);
-+}
-+
-+int ftnl_flush_table(struct ftnl_handle *h)
-+{
-+	struct nlmsghdr nlh;
-+	int ret;
-+
-+	/* construct msg */
-+	nfnl_fill_hdr(h->ftnlssh, &nlh, 0, AF_INET, 0,
-+		      FT_MSG_FLUSH, NLM_F_REQUEST | NLM_F_ACK);
-+
-+	/* send msg */
-+	ret = nfnl_send(h->nfnlh, &nlh);
-+	return ret;
-+}
-+
-+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple)
-+{
-+	const int size = 256;
-+	union {
-+		char buffer[size];
-+		struct nlmsghdr nlh;
-+	} u;
-+	int ret;
-+
-+	/* construct msg */
-+	nfnl_fill_hdr(h->ftnlssh, &u.nlh, 0, AF_INET, 0,
-+		      FT_MSG_DEL, NLM_F_REQUEST|NLM_F_ACK);
-+	build_tuple(&u.nlh, size, tuple);
-+
-+	/* send msg */
-+	ret = nfnl_send(h->nfnlh, &u.nlh);
-+
-+	return ret;
-+}
-diff --git a/package/mtk/applications/flowtable/src/ftnl.c b/package/mtk/applications/flowtable/src/ftnl.c
-new file mode 100644
-index 00000000..30352b29
---- /dev/null
-+++ b/package/mtk/applications/flowtable/src/ftnl.c
-@@ -0,0 +1,92 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <getopt.h>
-+
-+#include "netfilter_flowtable.h"
-+
-+void usage(void)
-+{
-+	printf("#########flush flow table\n");
-+	printf("ftnl -F\n");
-+	printf("#########del flow from offload table\n");
-+	printf("ftnl -D [sip] [dip] [proto] [sport] [dport]\n");
-+}
-+
-+int main (int argc, char *argv[])
-+{
-+	struct ftnl_handle *h;
-+	struct flow_tuple tuple = {0};
-+	int msg = -1;
-+	int c;
-+	int ret = -1;
-+	const char* optstring = "FD";
-+	struct option opts[] = {
-+		{"sip", required_argument, NULL, 's'},
-+		{"dip", required_argument, NULL, 'd'},
-+		{"proto", required_argument, NULL, 'p'},
-+		{"sport", required_argument, NULL, 'm'},
-+		{"dport", required_argument, NULL, 'n'}
-+	};
-+
-+	/* open netlink socket */
-+	h = ftnl_open();
-+	if (!h)
-+		return ret;
-+
-+	/* parse arg */
-+	while ((c = getopt_long(argc, argv, optstring, opts, NULL)) != -1) {
-+		switch (c) {
-+			case 'F':
-+				msg = FT_MSG_FLUSH;
-+				break;
-+			case 'D':
-+				msg = FT_MSG_DEL;
-+				break;
-+			case 's':
-+				inet_aton(optarg, &tuple.sip4);
-+				break;
-+			case 'd':
-+				inet_aton(optarg, &tuple.dip4);
-+				break;
-+			case 'p':
-+				if (!strcmp(optarg, "tcp"))
-+					tuple.proto = IPPROTO_TCP;
-+				else if (!strcmp(optarg, "udp"))
-+					tuple.proto = IPPROTO_UDP;
-+				else {
-+					printf("proto bad value "
-+					       "pls set proto to udp or tcp "
-+					       "arg : %s\n", optarg);
-+					goto out;
-+				}
-+				break;
-+			case 'm':
-+				tuple.sport = htons(atoi(optarg));
-+				break;
-+			case 'n':
-+				tuple.dport = htons(atoi(optarg));
-+				break;
-+			default:
-+				usage();
-+				goto out;
-+		}
-+	}
-+
-+	switch (msg) {
-+		case FT_MSG_FLUSH:
-+			ftnl_flush_table(h);
-+			break;
-+		case FT_MSG_DEL:
-+			ftnl_del_flow(h, &tuple);
-+			break;
-+		default:
-+			break;
-+	}
-+
-+out:
-+	ftnl_close(h);
-+	return ret;
-+}
-diff --git a/package/mtk/applications/flowtable/src/netfilter_flowtable.h b/package/mtk/applications/flowtable/src/netfilter_flowtable.h
-new file mode 100644
-index 00000000..3ea8916e
---- /dev/null
-+++ b/package/mtk/applications/flowtable/src/netfilter_flowtable.h
-@@ -0,0 +1,63 @@
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <libnfnetlink/libnfnetlink.h>
-+
-+struct ftnl_handle {
-+	struct nfnl_handle		*nfnlh;
-+	struct nfnl_subsys_handle	*ftnlssh;
-+};
-+
-+struct flow_tuple {
-+	struct in_addr sip4;
-+	struct in_addr dip4;
-+	unsigned char proto;
-+	unsigned short int sport;
-+	unsigned short int dport;
-+};
-+
-+enum ft_msg_types{
-+	FT_MSG_DEL,
-+	FT_MSG_ADD,	//not support now
-+	FT_MSG_FLUSH,
-+	FT_MSG_MAX
-+};
-+
-+enum ftattr_type {
-+	FTA_UNSPEC,
-+	FTA_TUPLE,
-+	__FTA_MAX
-+};
-+#define FTA_MAX (__FTA_MAX - 1)
-+
-+enum ftattr_tuple {
-+	FTA_TUPLE_UNSPEC,
-+	FTA_TUPLE_IP,
-+	FTA_TUPLE_PROTO,
-+	FTA_TUPLE_ZONE,
-+	__FTA_TUPLE_MAX
-+};
-+#define FTA_TUPLE_MAX (__FTA_TUPLE_MAX - 1)
-+
-+enum ftattr_ip {
-+	FTA_IP_UNSPEC,
-+	FTA_IP_V4_SRC,
-+	FTA_IP_V4_DST,
-+	FTA_IP_V6_SRC,
-+	FTA_IP_V6_DST,
-+	__FTA_IP_MAX
-+};
-+#define FTA_IP_MAX (__FTA_IP_MAX - 1)
-+
-+enum ftattr_l4proto {
-+	FTA_PROTO_UNSPEC,
-+	FTA_PROTO_NUM,
-+	FTA_PROTO_SPORT,
-+	FTA_PROTO_DPORT,
-+	__FTA_PROTO_MAX
-+};
-+#define FTA_PROTO_MAX (__FTA_PROTO_MAX - 1)
-+
-+struct ftnl_handle* ftnl_open(void);
-+void ftnl_close(struct ftnl_handle *h);
-+int ftnl_flush_table(struct ftnl_handle *h);
-+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple);
 diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk
 index 97153e5c..e30484b7 100644
 --- a/package/kernel/linux/modules/netfilter.mk
diff --git a/feed/flowtable/Makefile b/feed/flowtable/Makefile
new file mode 100644
index 0000000..150a1a3
--- /dev/null
+++ b/feed/flowtable/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=netfilter_flowtable
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+
+PKG_LICENSE:=GPL-2.0+
+#PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/netfilter-flowtable
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  DEPENDS:=+libnfnetlink +libmnl +kmod-nf-flow-netlink
+  TITLE:=API to the in-kernel flow offload table
+  SUBMENU:=Applications
+endef
+
+define Package/netfilter-flowtable/description
+  API to the in-kernel flow offload table
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+TARGET_CPPFLAGS := \
+	-D_GNU_SOURCE \
+	-I$(LINUX_DIR)/user_headers/include \
+	-I$(PKG_BUILD_DIR) \
+	$(TARGET_CPPFLAGS) \
+
+define Build/Compile
+	CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		$(TARGET_CONFIGURE_OPTS) \
+		LIBS="$(TARGET_LDFLAGS) -lnfnetlink  -lm"
+endef
+
+define Package/netfilter-flowtable/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(PKG_BUILD_DIR)/ftnl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,netfilter-flowtable))
\ No newline at end of file
diff --git a/feed/flowtable/src/Makefile b/feed/flowtable/src/Makefile
new file mode 100644
index 0000000..3f450ad
--- /dev/null
+++ b/feed/flowtable/src/Makefile
@@ -0,0 +1,9 @@
+EXEC = ftnl
+SRC = api.c ftnl.c
+
+all:$(EXEC)
+$(EXEC):$(SRC)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) $(LDLIBS) $(LIBS)
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
diff --git a/feed/flowtable/src/api.c b/feed/flowtable/src/api.c
new file mode 100644
index 0000000..64bbbfe
--- /dev/null
+++ b/feed/flowtable/src/api.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netfilter_flowtable.h"
+
+static void attr_dump(struct nfattr *attr)
+{
+	char *data = nla_data(attr);
+	int i = 0;
+
+	while (i < nal_len(attr)) {
+		printf("%x ", *(data + i));
+		i++;
+		if (i % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+struct ftnl_handle *ftnl_open(void)
+{
+	struct ftnl_handle *h = NULL;
+
+	h = malloc(sizeof(struct ftnl_handle));
+	if (!h)
+		return NULL;
+
+	h->nfnlh = nfnl_open();
+	if (!h->nfnlh) {
+		printf("nfnl open fail\n");
+		free(h);
+		return NULL;
+	}
+
+	h->ftnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_FLOWTABLE, 1, 0);
+	if (!h->ftnlssh) {
+		nfnl_close(h->nfnlh);
+		printf("subsys open fail\n");
+		free(h);
+		return NULL;
+	}
+
+	return h;
+}
+
+void ftnl_close(struct ftnl_handle *h)
+{
+	nfnl_subsys_close(h->ftnlssh);
+	nfnl_close(h->nfnlh);
+	free(h);
+}
+
+static void build_tuple(struct nlmsghdr *nlh, size_t size,
+			struct flow_tuple *tuple)
+{
+	struct nfattr *nest_tuple, *nest_ip, *nest_proto;
+
+	nest_tuple = nfnl_nest(nlh, size, FTA_TUPLE);
+
+	nest_ip = nfnl_nest(nlh, size, FTA_TUPLE_IP);
+	nfnl_addattr_l(nlh, size, FTA_IP_V4_SRC,
+		       &tuple->sip4, sizeof(uint32_t));
+	nfnl_addattr_l(nlh, size, FTA_IP_V4_DST,
+		       &tuple->dip4, sizeof(uint32_t));
+	nfnl_nest_end(nlh, nest_ip);
+
+	nest_proto = nfnl_nest(nlh, size, FTA_TUPLE_PROTO);
+	nfnl_addattr_l(nlh, size, FTA_PROTO_NUM,
+		       &tuple->proto, sizeof(uint8_t));
+	nfnl_addattr_l(nlh, size, FTA_PROTO_SPORT,
+		       &tuple->sport, sizeof(uint16_t));
+	nfnl_addattr_l(nlh, size, FTA_PROTO_DPORT,
+		       &tuple->dport, sizeof(uint16_t));
+	nfnl_nest_end(nlh, nest_proto);
+
+	nfnl_nest_end(nlh, nest_tuple);
+//	attr_dump(nest_tuple);
+}
+
+int ftnl_flush_table(struct ftnl_handle *h)
+{
+	struct nlmsghdr nlh;
+	int ret;
+
+	/* construct msg */
+	nfnl_fill_hdr(h->ftnlssh, &nlh, 0, AF_INET, 0,
+		      FT_MSG_FLUSH, NLM_F_REQUEST | NLM_F_ACK);
+
+	/* send msg */
+	ret = nfnl_send(h->nfnlh, &nlh);
+	return ret;
+}
+
+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple)
+{
+	const int size = 256;
+	union {
+		char buffer[size];
+		struct nlmsghdr nlh;
+	} u;
+	int ret;
+
+	/* construct msg */
+	nfnl_fill_hdr(h->ftnlssh, &u.nlh, 0, AF_INET, 0,
+		      FT_MSG_DEL, NLM_F_REQUEST|NLM_F_ACK);
+	build_tuple(&u.nlh, size, tuple);
+
+	/* send msg */
+	ret = nfnl_send(h->nfnlh, &u.nlh);
+
+	return ret;
+}
diff --git a/feed/flowtable/src/ftnl.c b/feed/flowtable/src/ftnl.c
new file mode 100644
index 0000000..d021bb3
--- /dev/null
+++ b/feed/flowtable/src/ftnl.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "netfilter_flowtable.h"
+
+void usage(void)
+{
+	printf("#########flush flow table\n");
+	printf("ftnl -F\n");
+	printf("#########del flow from offload table\n");
+	printf("ftnl -D [sip] [dip] [proto] [sport] [dport]\n");
+}
+
+int main(int argc, char *argv[])
+{
+	struct ftnl_handle *h;
+	struct flow_tuple tuple = {0};
+	int msg = -1;
+	int c;
+	int ret = -1;
+	const char *optstring = "FD";
+	struct option opts[] = {
+		{"sip", required_argument, NULL, 's'},
+		{"dip", required_argument, NULL, 'd'},
+		{"proto", required_argument, NULL, 'p'},
+		{"sport", required_argument, NULL, 'm'},
+		{"dport", required_argument, NULL, 'n'}
+	};
+
+	/* open netlink socket */
+	h = ftnl_open();
+	if (!h)
+		return ret;
+
+	/* parse arg */
+	while ((c = getopt_long(argc, argv, optstring, opts, NULL)) != -1) {
+		switch (c) {
+		case 'F':
+			msg = FT_MSG_FLUSH;
+			break;
+		case 'D':
+			msg = FT_MSG_DEL;
+			break;
+		case 's':
+			inet_aton(optarg, &tuple.sip4);
+			break;
+		case 'd':
+			inet_aton(optarg, &tuple.dip4);
+			break;
+		case 'p':
+			if (!strcmp(optarg, "tcp"))
+				tuple.proto = IPPROTO_TCP;
+			else if (!strcmp(optarg, "udp"))
+				tuple.proto = IPPROTO_UDP;
+			else {
+				printf("proto bad value...\n");
+				printf("pls set proto to udp or tcp arg : %s\n",
+				       optarg);
+				goto out;
+			}
+			break;
+		case 'm':
+			tuple.sport = htons(atoi(optarg));
+			break;
+		case 'n':
+			tuple.dport = htons(atoi(optarg));
+			break;
+		default:
+			usage();
+			goto out;
+		}
+	}
+
+	switch (msg) {
+	case FT_MSG_FLUSH:
+		ftnl_flush_table(h);
+		break;
+	case FT_MSG_DEL:
+		ftnl_del_flow(h, &tuple);
+		break;
+	default:
+		break;
+	}
+
+out:
+	ftnl_close(h);
+	return ret;
+}
diff --git a/feed/flowtable/src/netfilter_flowtable.h b/feed/flowtable/src/netfilter_flowtable.h
new file mode 100644
index 0000000..6a50300
--- /dev/null
+++ b/feed/flowtable/src/netfilter_flowtable.h
@@ -0,0 +1,63 @@
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libnfnetlink/libnfnetlink.h>
+
+struct ftnl_handle {
+	struct nfnl_handle		*nfnlh;
+	struct nfnl_subsys_handle	*ftnlssh;
+};
+
+struct flow_tuple {
+	struct in_addr sip4;
+	struct in_addr dip4;
+	unsigned char proto;
+	unsigned short int sport;
+	unsigned short int dport;
+};
+
+enum ft_msg_types {
+	FT_MSG_DEL,
+	FT_MSG_ADD,	//not support now
+	FT_MSG_FLUSH,
+	FT_MSG_MAX
+};
+
+enum ftattr_type {
+	FTA_UNSPEC,
+	FTA_TUPLE,
+	__FTA_MAX
+};
+#define FTA_MAX (__FTA_MAX - 1)
+
+enum ftattr_tuple {
+	FTA_TUPLE_UNSPEC,
+	FTA_TUPLE_IP,
+	FTA_TUPLE_PROTO,
+	FTA_TUPLE_ZONE,
+	__FTA_TUPLE_MAX
+};
+#define FTA_TUPLE_MAX (__FTA_TUPLE_MAX - 1)
+
+enum ftattr_ip {
+	FTA_IP_UNSPEC,
+	FTA_IP_V4_SRC,
+	FTA_IP_V4_DST,
+	FTA_IP_V6_SRC,
+	FTA_IP_V6_DST,
+	__FTA_IP_MAX
+};
+#define FTA_IP_MAX (__FTA_IP_MAX - 1)
+
+enum ftattr_l4proto {
+	FTA_PROTO_UNSPEC,
+	FTA_PROTO_NUM,
+	FTA_PROTO_SPORT,
+	FTA_PROTO_DPORT,
+	__FTA_PROTO_MAX
+};
+#define FTA_PROTO_MAX (__FTA_PROTO_MAX - 1)
+
+struct ftnl_handle *ftnl_open(void);
+void ftnl_close(struct ftnl_handle *h);
+int ftnl_flush_table(struct ftnl_handle *h);
+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple);