aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/utils/nftables/patches/203-src-flow-offload-support.patch
blob: 86dfb1d94aaf9ee64aa2e3994770ecfb70641851 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sun, 3 Dec 2017 21:27:03 +0100
Subject: [PATCH] src: flow offload support

This patch allows us to refer to existing flowtables:

 # nft add rule x x flow offload @m

Packets matching this rule create an entry in the flow table 'm', hence,
follow up packets that get to the flowtable at ingress bypass the
classic forwarding path.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---

--- a/include/ct.h
+++ b/include/ct.h
@@ -29,6 +29,8 @@ extern struct expr *ct_expr_alloc(const
 extern void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr);
 
 extern struct stmt *notrack_stmt_alloc(const struct location *loc);
+extern struct stmt *flow_offload_stmt_alloc(const struct location *loc,
+					    const char *table_name);
 
 extern const struct datatype ct_dir_type;
 extern const struct datatype ct_state_type;
--- a/include/statement.h
+++ b/include/statement.h
@@ -10,6 +10,12 @@ extern struct stmt *expr_stmt_alloc(cons
 extern struct stmt *verdict_stmt_alloc(const struct location *loc,
 				       struct expr *expr);
 
+struct flow_stmt {
+	const char		*table_name;
+};
+
+struct stmt *flow_stmt_alloc(const struct location *loc, const char *name);
+
 struct objref_stmt {
 	uint32_t		type;
 	struct expr		*expr;
@@ -231,6 +237,7 @@ extern struct stmt *xt_stmt_alloc(const
  * @STMT_NOTRACK:	notrack statement
  * @STMT_OBJREF:	stateful object reference statement
  * @STMT_EXTHDR:	extension header statement
+ * @STMT_FLOW_OFFLOAD:	flow offload statement
  */
 enum stmt_types {
 	STMT_INVALID,
@@ -256,6 +263,7 @@ enum stmt_types {
 	STMT_NOTRACK,
 	STMT_OBJREF,
 	STMT_EXTHDR,
+	STMT_FLOW_OFFLOAD,
 };
 
 /**
@@ -316,6 +324,7 @@ struct stmt {
 		struct fwd_stmt		fwd;
 		struct xt_stmt		xt;
 		struct objref_stmt	objref;
+		struct flow_stmt	flow;
 	};
 };
 
--- a/src/ct.c
+++ b/src/ct.c
@@ -456,3 +456,26 @@ struct stmt *notrack_stmt_alloc(const st
 {
 	return stmt_alloc(loc, &notrack_stmt_ops);
 }
+
+static void flow_offload_stmt_print(const struct stmt *stmt,
+				    struct output_ctx *octx)
+{
+	printf("flow offload @%s", stmt->flow.table_name);
+}
+
+static const struct stmt_ops flow_offload_stmt_ops = {
+	.type		= STMT_FLOW_OFFLOAD,
+	.name		= "flow_offload",
+	.print		= flow_offload_stmt_print,
+};
+
+struct stmt *flow_offload_stmt_alloc(const struct location *loc,
+				     const char *table_name)
+{
+	struct stmt *stmt;
+
+	stmt = stmt_alloc(loc, &flow_offload_stmt_ops);
+	stmt->flow.table_name	= table_name;
+
+	return stmt;
+}
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2773,6 +2773,7 @@ int stmt_evaluate(struct eval_ctx *ctx,
 	case STMT_LIMIT:
 	case STMT_QUOTA:
 	case STMT_NOTRACK:
+	case STMT_FLOW_OFFLOAD:
 		return 0;
 	case STMT_EXPRESSION:
 		return stmt_evaluate_expr(ctx, stmt);
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -680,6 +680,16 @@ static void netlink_parse_notrack(struct
 	ctx->stmt = notrack_stmt_alloc(loc);
 }
 
+static void netlink_parse_flow_offload(struct netlink_parse_ctx *ctx,
+				       const struct location *loc,
+				       const struct nftnl_expr *nle)
+{
+	const char *table_name;
+
+	table_name = xstrdup(nftnl_expr_get_str(nle, NFTNL_EXPR_FLOW_TABLE_NAME));
+	ctx->stmt = flow_offload_stmt_alloc(loc, table_name);
+}
+
 static void netlink_parse_ct_stmt(struct netlink_parse_ctx *ctx,
 				  const struct location *loc,
 				  const struct nftnl_expr *nle)
@@ -1255,6 +1265,7 @@ static const struct {
 	{ .name = "hash",	.parse = netlink_parse_hash },
 	{ .name = "fib",	.parse = netlink_parse_fib },
 	{ .name = "tcpopt",	.parse = netlink_parse_exthdr },
+	{ .name = "flow_offload", .parse = netlink_parse_flow_offload },
 };
 
 static int netlink_parse_expr(const struct nftnl_expr *nle,
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1201,6 +1201,17 @@ static void netlink_gen_notrack_stmt(str
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
+static void netlink_gen_flow_offload_stmt(struct netlink_linearize_ctx *ctx,
+					  const struct stmt *stmt)
+{
+	struct nftnl_expr *nle;
+
+	nle = alloc_nft_expr("flow_offload");
+	nftnl_expr_set_str(nle, NFTNL_EXPR_FLOW_TABLE_NAME,
+			   stmt->flow.table_name);
+	nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
 static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
 				 const struct stmt *stmt)
 {
@@ -1300,6 +1311,8 @@ static void netlink_gen_stmt(struct netl
 		break;
 	case STMT_NOTRACK:
 		return netlink_gen_notrack_stmt(ctx, stmt);
+	case STMT_FLOW_OFFLOAD:
+		return netlink_gen_flow_offload_stmt(ctx, stmt);
 	case STMT_OBJREF:
 		return netlink_gen_objref_stmt(ctx, stmt);
 	default:
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -248,6 +248,7 @@ int nft_lex(void *, void *, void *);
 %token SIZE			"size"
 
 %token FLOW			"flow"
+%token OFFLOAD			"offload"
 %token METER			"meter"
 %token METERS			"meters"
 
@@ -3384,6 +3385,10 @@ meta_stmt		:	META	meta_key	SET	stmt_expr
 			{
 				$$ = notrack_stmt_alloc(&@$);
 			}
+			|	FLOW	OFFLOAD	AT string
+			{
+				$$ = flow_offload_stmt_alloc(&@$, $4);
+			}
 			;
 
 offset_opt		:	/* empty */	{ $$ = 0; }
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -296,6 +296,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr
 "memory"		{ return MEMORY; }
 
 "flow"			{ return FLOW; }
+"offload"		{ return OFFLOAD; }
 "meter"			{ return METER; }
 "meters"		{ return METERS; }