blob: 3bb7e7ab173ef6c60356cfd2f82df30bdbb49578 [file] [log] [blame]
developer58aa0682023-09-18 14:02:26 +08001From 6bda18f107acbf04f01c18ad5964be6f7404d3cf Mon Sep 17 00:00:00 2001
2From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
3Date: Mon, 18 Sep 2023 13:14:08 +0800
4Subject: [PATCH 19/22] flow-offload-add-mtkhnat-netlink
5
6---
7 include/net/netfilter/nf_flow_table.h | 1 +
8 include/uapi/linux/netfilter/nfnetlink.h | 3 +-
9 net/netfilter/Kconfig | 9 +
10 net/netfilter/Makefile | 1 +
11 net/netfilter/nf_flow_table_core.c | 23 +++
12 net/netfilter/nf_flow_table_netlink.c | 239 +++++++++++++++++++++++
13 6 files changed, 275 insertions(+), 1 deletion(-)
14 create mode 100644 net/netfilter/nf_flow_table_netlink.c
15
developereed1a952023-03-01 14:30:18 +080016diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
developer58aa0682023-09-18 14:02:26 +080017index 97a277d..3490d90 100644
developereed1a952023-03-01 14:30:18 +080018--- a/include/net/netfilter/nf_flow_table.h
19+++ b/include/net/netfilter/nf_flow_table.h
developer58aa0682023-09-18 14:02:26 +080020@@ -277,6 +277,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
developereed1a952023-03-01 14:30:18 +080021 void nf_flow_table_free(struct nf_flowtable *flow_table);
22
23 void flow_offload_teardown(struct flow_offload *flow);
24+void flow_offload_teardown_by_tuple(struct flow_offload_tuple *tuple);
25
26 int nf_flow_table_iterate(struct nf_flowtable *flow_table,
27 void (*iter)(struct flow_offload *flow, void *data),
28diff --git a/include/uapi/linux/netfilter/nfnetlink.h b/include/uapi/linux/netfilter/nfnetlink.h
29index 5bc960f..603d9c0 100644
30--- a/include/uapi/linux/netfilter/nfnetlink.h
31+++ b/include/uapi/linux/netfilter/nfnetlink.h
32@@ -60,7 +60,8 @@ struct nfgenmsg {
33 #define NFNL_SUBSYS_CTHELPER 9
34 #define NFNL_SUBSYS_NFTABLES 10
35 #define NFNL_SUBSYS_NFT_COMPAT 11
36-#define NFNL_SUBSYS_COUNT 12
37+#define NFNL_SUBSYS_FLOWTABLE 12
38+#define NFNL_SUBSYS_COUNT 13
39
40 /* Reserved control nfnetlink messages */
41 #define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE
42diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
43index 5d690ab..8ec87aa 100644
44--- a/net/netfilter/Kconfig
45+++ b/net/netfilter/Kconfig
46@@ -708,6 +708,15 @@ config NF_FLOW_TABLE
47
48 To compile it as a module, choose M here.
49
50+config NF_FLOW_TABLE_NETLINK
51+ tristate "Netfilter flow table netlink module"
52+ depends on NETFILTER_INGRESS
53+ depends on NF_CONNTRACK
54+ help
55+ This option adds the flow table core infrastructure.
56+
57+ To compile it as a module, choose M here.
58+
59 config NETFILTER_XTABLES
60 tristate "Netfilter Xtables support (required for ip_tables)"
61 default m if NETFILTER_ADVANCED=n
62diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
63index d93a121..fa6ffb1 100644
64--- a/net/netfilter/Makefile
65+++ b/net/netfilter/Makefile
66@@ -124,6 +124,7 @@ nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o \
67 nf_flow_table_offload.o
68
69 obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o
70+obj-$(CONFIG_NF_FLOW_TABLE_NETLINK) += nf_flow_table_netlink.o
71
72 # generic X tables
73 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
74diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
developer58aa0682023-09-18 14:02:26 +080075index c3054af..fb06755 100644
developereed1a952023-03-01 14:30:18 +080076--- a/net/netfilter/nf_flow_table_core.c
77+++ b/net/netfilter/nf_flow_table_core.c
developeree39bcf2023-06-16 08:03:30 +080078@@ -373,6 +373,29 @@ void flow_offload_teardown(struct flow_offload *flow)
developereed1a952023-03-01 14:30:18 +080079 }
80 EXPORT_SYMBOL_GPL(flow_offload_teardown);
81
82+void flow_offload_teardown_by_tuple(struct flow_offload_tuple *tuple)
83+{
84+ struct net_device *netdev;
85+ struct nf_flowtable *flowtable;
86+ struct flow_offload_tuple_rhash *tuplehash;
87+ struct flow_offload *flow;
88+ int dir;
89+
90+ list_for_each_entry(flowtable, &flowtables, list) {
91+ for_each_netdev(&init_net, netdev) {
92+ tuple->iifidx = netdev->ifindex;
93+ tuplehash = flow_offload_lookup(flowtable, tuple);
94+ if (!tuplehash)
95+ continue;
96+
97+ dir = tuplehash->tuple.dir;
98+ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
99+ flow_offload_teardown(flow);
100+ }
101+ };
102+}
103+EXPORT_SYMBOL_GPL(flow_offload_teardown_by_tuple);
104+
105 struct flow_offload_tuple_rhash *
106 flow_offload_lookup(struct nf_flowtable *flow_table,
107 struct flow_offload_tuple *tuple)
108diff --git a/net/netfilter/nf_flow_table_netlink.c b/net/netfilter/nf_flow_table_netlink.c
109new file mode 100644
110index 0000000..f05f29e
111--- /dev/null
112+++ b/net/netfilter/nf_flow_table_netlink.c
113@@ -0,0 +1,239 @@
114+#include <linux/types.h>
115+#include <linux/kernel.h>
116+#include <linux/init.h>
117+#include <linux/module.h>
118+#include <linux/netfilter.h>
119+#include <linux/netlink.h>
120+#include <net/netlink.h>
121+#include <net/ip.h>
122+#include <linux/netfilter/nfnetlink.h>
123+#include <net/netfilter/nf_flow_table.h>
124+
125+enum ft_netlink_msg_types {
126+ FT_MSG_DEL,
127+ FT_MSG_ADD,
128+ FT_MSG_FLUSH,
129+ FT_MSG_MAX
130+};
131+
132+enum ftattr_type {
133+ FTA_UNSPEC,
134+ FTA_TUPLE,
135+ __FTA_MAX
136+};
137+#define FTA_MAX (__FTA_MAX - 1)
138+
139+enum ftattr_tuple {
140+ FTA_TUPLE_UNSPEC,
141+ FTA_TUPLE_IP,
142+ FTA_TUPLE_PROTO,
143+ FTA_TUPLE_ZONE,
144+ __FTA_TUPLE_MAX
145+};
146+#define FTA_TUPLE_MAX (__FTA_TUPLE_MAX - 1)
147+
148+enum ftattr_ip {
149+ FTA_IP_UNSPEC,
150+ FTA_IP_V4_SRC,
151+ FTA_IP_V4_DST,
152+ __FTA_IP_MAX
153+};
154+#define FTA_IP_MAX (__FTA_IP_MAX - 1)
155+
156+enum ftattr_l4proto {
157+ FTA_PROTO_UNSPEC,
158+ FTA_PROTO_NUM,
159+ FTA_PROTO_SPORT,
160+ FTA_PROTO_DPORT,
161+ __FTA_PROTO_MAX
162+};
163+#define FTA_PROTO_MAX (__FTA_PROTO_MAX - 1)
164+
165+static const struct nla_policy tuple_nla_policy[FTA_TUPLE_MAX + 1] = {
166+ [FTA_TUPLE_IP] = { .type = NLA_NESTED },
167+ [FTA_TUPLE_PROTO] = { .type = NLA_NESTED },
168+ [FTA_TUPLE_ZONE] = { .type = NLA_U16 },
169+};
170+
171+static const struct nla_policy ip_nla_policy[FTA_IP_MAX + 1] = {
172+ [FTA_IP_V4_SRC] = { .type = NLA_U32 },
173+ [FTA_IP_V4_DST] = { .type = NLA_U32 },
174+};
175+
176+static const struct nla_policy l4proto_nla_policy[FTA_PROTO_MAX + 1] = {
177+ [FTA_PROTO_NUM] = { .type = NLA_U8 },
178+ [FTA_PROTO_SPORT] = {.type = NLA_U16},
179+ [FTA_PROTO_DPORT] = {.type = NLA_U16},
180+};
181+
182+static inline int ftnetlink_parse_tuple_ip(struct nlattr *attr,
183+ struct flow_offload_tuple *tuple)
184+{
185+ struct nlattr *tb[FTA_IP_MAX+1];
186+ int err;
187+
188+ err = nla_parse_nested_deprecated(tb, FTA_IP_MAX, attr, ip_nla_policy, NULL);
189+
190+ if (err < 0)
191+ return err;
192+
193+ switch (tuple->l3proto) {
194+ case NFPROTO_IPV4:
195+ if (!tb[FTA_IP_V4_SRC] || !tb[FTA_IP_V4_DST])
196+ return -EINVAL;
197+
198+ tuple->src_v4.s_addr = nla_get_in_addr(tb[FTA_IP_V4_SRC]);
199+ tuple->dst_v4.s_addr = nla_get_in_addr(tb[FTA_IP_V4_DST]);
200+ }
201+
202+ return err;
203+}
204+
205+static inline int ftnetlink_parse_tuple_proto(struct nlattr *attr,
206+ struct flow_offload_tuple *tuple)
207+{
208+ struct nlattr *tb[FTA_PROTO_MAX+1];
209+ int err;
210+
211+ err = nla_parse_nested_deprecated(tb, FTA_PROTO_MAX, attr, l4proto_nla_policy, NULL);
212+
213+ if(err < 0)
214+ return err;
215+
216+ if (!tb[FTA_PROTO_NUM] || !tb[FTA_PROTO_SPORT] || !tb[FTA_PROTO_DPORT])
217+ return -EINVAL;
218+
219+ tuple->l4proto = nla_get_u8(tb[FTA_PROTO_NUM]);
220+ tuple->src_port = nla_get_u16(tb[FTA_PROTO_SPORT]);
221+ tuple->dst_port = nla_get_u16(tb[FTA_PROTO_DPORT]);
222+
223+ return err;
224+}
225+
226+static int ftnetlink_parse_tuple(const struct nlattr * const cda[],
227+ struct flow_offload_tuple *tuple,
228+ int attrtype, int l3proto)
229+{
230+ struct nlattr *tb[FTA_TUPLE_MAX+1];
231+ int err;
232+
233+ memset(tuple, 0, sizeof(*tuple));
234+
235+ err = nla_parse_nested_deprecated(tb, FTA_TUPLE_MAX, cda[attrtype], tuple_nla_policy, NULL);
236+ if (err < 0)
237+ return err;
238+
239+ if (!tb[FTA_TUPLE_IP])
240+ return -EINVAL;
241+
242+ /* parse IP */
243+ tuple->l3proto = l3proto;
244+ err = ftnetlink_parse_tuple_ip(tb[FTA_TUPLE_IP], tuple);
245+ if (err < 0)
246+ return err;
247+
248+ /* parse proto */
249+ if (!tb[FTA_TUPLE_PROTO])
250+ return -EINVAL;
251+ err = ftnetlink_parse_tuple_proto(tb[FTA_TUPLE_PROTO], tuple);
252+
253+ if (err >= 0)
254+ printk("tuple info:sip=%pI4,dip=%pI4 proto=%d "
255+ "sport=%d dport=%d\n",
256+ &tuple->src_v4, &tuple->dst_v4, tuple->l4proto,
257+ ntohs(tuple->src_port), ntohs(tuple->dst_port));
258+
259+ return err;
260+}
261+
262+static int ftnetlink_del_nf_flow(struct net *net, struct sock *ftnl, struct sk_buff *skb,
263+ const struct nlmsghdr *nlh,
264+ const struct nlattr * const cda[],
265+ struct netlink_ext_ack *extack)
266+{
267+ struct net_device *dev = skb->dev;
268+ struct flow_offload_tuple tuple;
269+ int err = -1;
270+ struct nfgenmsg *nfmsg = nlmsg_data(nlh);
271+ u_int8_t u3 = nfmsg->nfgen_family;
272+
273+ /* parse tuple */
274+ if(!cda[FTA_TUPLE])
275+ return -EINVAL;
276+
277+ err = ftnetlink_parse_tuple(cda, &tuple, FTA_TUPLE, u3);
278+ if (err < 0)
279+ return err;
280+
281+ /* teardown the flow */
282+ flow_offload_teardown_by_tuple(&tuple);
283+
284+ return 0;
285+}
286+
287+static int ftnetlink_add_nf_flow(struct net *net, struct sock *ftnl, struct sk_buff *skb,
288+ const struct nlmsghdr *nlh,
289+ const struct nlattr * const cda[],
290+ struct netlink_ext_ack *extack)
291+{
292+ return 0;
293+}
294+
295+static int ftnetlink_flush_table(struct net *net, struct sock *ftnl, struct sk_buff *skb,
296+ const struct nlmsghdr *nlh,
297+ const struct nlattr * const cda[],
298+ struct netlink_ext_ack *extack)
299+{
300+ struct net_device *dev = skb->dev;
301+
302+ nf_flow_table_cleanup(dev);
303+
304+ return 0;
305+}
306+
307+static const struct nla_policy ft_nla_policy[FTA_MAX + 1] = {
308+ [FTA_TUPLE] = { .type = NLA_NESTED },
309+};
310+
311+static const struct nfnl_callback flow_table_cb[FT_MSG_MAX] = {
312+ [FT_MSG_DEL] = {
313+ .call = ftnetlink_del_nf_flow,
314+ .attr_count = FTA_MAX,
315+ .policy = ft_nla_policy
316+ },
317+ [FT_MSG_ADD] = {
318+ .call = ftnetlink_add_nf_flow,
319+ .attr_count = FTA_MAX,
320+ .policy = ft_nla_policy
321+ },
322+ [FT_MSG_FLUSH] = {
323+ .call = ftnetlink_flush_table,
324+ .attr_count = FTA_MAX,
325+ .policy = ft_nla_policy
326+ },
327+};
328+
329+static const struct nfnetlink_subsystem ftnl_subsys = {
330+ .name = "flowtable",
331+ .subsys_id = NFNL_SUBSYS_FLOWTABLE,
332+ .cb_count = FT_MSG_MAX,
333+ .cb = flow_table_cb,
334+};
335+
336+static int __init ftnetlink_init(void)
337+{
338+ int ret;
339+
340+ ret = nfnetlink_subsys_register(&ftnl_subsys);
341+
342+ return ret;
343+}
344+
345+static void ftnetlink_exit(void)
346+{
347+ nfnetlink_subsys_unregister(&ftnl_subsys);
348+}
349+
350+MODULE_LICENSE("GPL");
351+module_init(ftnetlink_init);
352+module_exit(ftnetlink_exit);
developer58aa0682023-09-18 14:02:26 +0800353--
3542.18.0
355