OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | From: Pablo Neira Ayuso <pablo@netfilter.org> |
2 | Date: Sun, 3 Dec 2017 21:05:54 +0100 |
||
3 | Subject: [PATCH] expr: add flow offload expression |
||
4 | |||
5 | This patch adds the new "flow_offload" expression to select what flows |
||
6 | are offloaded to an existing flowtable. |
||
7 | |||
8 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
||
9 | --- |
||
10 | create mode 100644 src/expr/flow_offload.c |
||
11 | |||
12 | --- a/include/libnftnl/expr.h |
||
13 | +++ b/include/libnftnl/expr.h |
||
14 | @@ -221,6 +221,10 @@ enum { |
||
15 | }; |
||
16 | |||
17 | enum { |
||
18 | + NFTNL_EXPR_FLOW_TABLE_NAME = NFTNL_EXPR_BASE, |
||
19 | +}; |
||
20 | + |
||
21 | +enum { |
||
22 | NFTNL_EXPR_FWD_SREG_DEV = NFTNL_EXPR_BASE, |
||
23 | }; |
||
24 | |||
25 | --- a/include/linux/netfilter/nf_tables.h |
||
26 | +++ b/include/linux/netfilter/nf_tables.h |
||
27 | @@ -952,6 +952,17 @@ enum nft_ct_attributes { |
||
28 | }; |
||
29 | #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) |
||
30 | |||
31 | +/** |
||
32 | + * enum nft_flow_attributes - ct offload expression attributes |
||
33 | + * @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING) |
||
34 | + */ |
||
35 | +enum nft_offload_attributes { |
||
36 | + NFTA_FLOW_UNSPEC, |
||
37 | + NFTA_FLOW_TABLE_NAME, |
||
38 | + __NFTA_FLOW_MAX, |
||
39 | +}; |
||
40 | +#define NFTA_FLOW_MAX (__NFTA_FLOW_MAX - 1) |
||
41 | + |
||
42 | enum nft_limit_type { |
||
43 | NFT_LIMIT_PKTS, |
||
44 | NFT_LIMIT_PKT_BYTES |
||
45 | --- a/src/Makefile.am |
||
46 | +++ b/src/Makefile.am |
||
47 | @@ -32,6 +32,7 @@ libnftnl_la_SOURCES = utils.c \ |
||
48 | expr/data_reg.c \ |
||
49 | expr/dup.c \ |
||
50 | expr/exthdr.c \ |
||
51 | + expr/flow_offload.c \ |
||
52 | expr/fib.c \ |
||
53 | expr/fwd.c \ |
||
54 | expr/limit.c \ |
||
55 | --- /dev/null |
||
56 | +++ b/src/expr/flow_offload.c |
||
57 | @@ -0,0 +1,184 @@ |
||
58 | +#include "internal.h" |
||
59 | + |
||
60 | +#include <stdio.h> |
||
61 | +#include <stdint.h> |
||
62 | +#include <string.h> /* for memcpy */ |
||
63 | +#include <arpa/inet.h> |
||
64 | +#include <errno.h> |
||
65 | +#include <libmnl/libmnl.h> |
||
66 | +#include <linux/netfilter/nf_tables.h> |
||
67 | +#include <libnftnl/rule.h> |
||
68 | +#include <libnftnl/expr.h> |
||
69 | + |
||
70 | +struct nftnl_expr_flow { |
||
71 | + char *table_name; |
||
72 | +}; |
||
73 | + |
||
74 | +static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type, |
||
75 | + const void *data, uint32_t data_len) |
||
76 | +{ |
||
77 | + struct nftnl_expr_flow *flow = nftnl_expr_data(e); |
||
78 | + |
||
79 | + switch (type) { |
||
80 | + case NFTNL_EXPR_FLOW_TABLE_NAME: |
||
81 | + flow->table_name = strdup((const char *)data); |
||
82 | + if (!flow->table_name) |
||
83 | + return -1; |
||
84 | + break; |
||
85 | + default: |
||
86 | + return -1; |
||
87 | + } |
||
88 | + return 0; |
||
89 | +} |
||
90 | + |
||
91 | +static const void *nftnl_expr_flow_get(const struct nftnl_expr *e, |
||
92 | + uint16_t type, uint32_t *data_len) |
||
93 | +{ |
||
94 | + struct nftnl_expr_flow *flow = nftnl_expr_data(e); |
||
95 | + |
||
96 | + switch(type) { |
||
97 | + case NFTNL_EXPR_FLOW_TABLE_NAME: |
||
98 | + *data_len = strlen(flow->table_name) + 1; |
||
99 | + return flow->table_name; |
||
100 | + } |
||
101 | + return NULL; |
||
102 | +} |
||
103 | + |
||
104 | +static int nftnl_expr_flow_cb(const struct nlattr *attr, void *data) |
||
105 | +{ |
||
106 | + const struct nlattr **tb = data; |
||
107 | + int type = mnl_attr_get_type(attr); |
||
108 | + |
||
109 | + if (mnl_attr_type_valid(attr, NFTA_FLOW_MAX) < 0) |
||
110 | + return MNL_CB_OK; |
||
111 | + |
||
112 | + switch(type) { |
||
113 | + case NFTA_FLOW_TABLE_NAME: |
||
114 | + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) |
||
115 | + abi_breakage(); |
||
116 | + break; |
||
117 | + } |
||
118 | + |
||
119 | + tb[type] = attr; |
||
120 | + return MNL_CB_OK; |
||
121 | +} |
||
122 | + |
||
123 | +static void nftnl_expr_flow_build(struct nlmsghdr *nlh, |
||
124 | + const struct nftnl_expr *e) |
||
125 | +{ |
||
126 | + struct nftnl_expr_flow *flow = nftnl_expr_data(e); |
||
127 | + |
||
128 | + if (e->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) |
||
129 | + mnl_attr_put_strz(nlh, NFTA_FLOW_TABLE_NAME, flow->table_name); |
||
130 | +} |
||
131 | + |
||
132 | +static int nftnl_expr_flow_parse(struct nftnl_expr *e, struct nlattr *attr) |
||
133 | +{ |
||
134 | + struct nftnl_expr_flow *flow = nftnl_expr_data(e); |
||
135 | + struct nlattr *tb[NFTA_FLOW_MAX+1] = {}; |
||
136 | + int ret = 0; |
||
137 | + |
||
138 | + if (mnl_attr_parse_nested(attr, nftnl_expr_flow_cb, tb) < 0) |
||
139 | + return -1; |
||
140 | + |
||
141 | + if (tb[NFTA_FLOW_TABLE_NAME]) { |
||
142 | + flow->table_name = |
||
143 | + strdup(mnl_attr_get_str(tb[NFTA_FLOW_TABLE_NAME])); |
||
144 | + if (!flow->table_name) |
||
145 | + return -1; |
||
146 | + e->flags |= (1 << NFTNL_EXPR_FLOW_TABLE_NAME); |
||
147 | + } |
||
148 | + |
||
149 | + return ret; |
||
150 | +} |
||
151 | + |
||
152 | +static int |
||
153 | +nftnl_expr_flow_json_parse(struct nftnl_expr *e, json_t *root, |
||
154 | + struct nftnl_parse_err *err) |
||
155 | +{ |
||
156 | +#ifdef JSON_PARSING |
||
157 | + const char *table_name; |
||
158 | + |
||
159 | + table_name = nftnl_jansson_parse_str(root, "flowtable", err); |
||
160 | + if (table_name != NULL) |
||
161 | + nftnl_expr_set_str(e, NFTNL_EXPR_FLOW_TABLE_NAME, table_name); |
||
162 | + |
||
163 | + return 0; |
||
164 | +#else |
||
165 | + errno = EOPNOTSUPP; |
||
166 | + return -1; |
||
167 | +#endif |
||
168 | +} |
||
169 | + |
||
170 | +static int nftnl_expr_flow_export(char *buf, size_t size, |
||
171 | + const struct nftnl_expr *e, int type) |
||
172 | +{ |
||
173 | + struct nftnl_expr_flow *l = nftnl_expr_data(e); |
||
174 | + NFTNL_BUF_INIT(b, buf, size); |
||
175 | + |
||
176 | + if (e->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) |
||
177 | + nftnl_buf_str(&b, type, l->table_name, SET); |
||
178 | + |
||
179 | + return nftnl_buf_done(&b); |
||
180 | +} |
||
181 | + |
||
182 | +static int nftnl_expr_flow_snprintf_default(char *buf, size_t size, |
||
183 | + const struct nftnl_expr *e) |
||
184 | +{ |
||
185 | + int remain = size, offset = 0, ret; |
||
186 | + struct nftnl_expr_flow *l = nftnl_expr_data(e); |
||
187 | + |
||
188 | + ret = snprintf(buf, remain, "flowtable %s ", l->table_name); |
||
189 | + SNPRINTF_BUFFER_SIZE(ret, remain, offset); |
||
190 | + |
||
191 | + return offset; |
||
192 | +} |
||
193 | + |
||
194 | +static int nftnl_expr_flow_snprintf(char *buf, size_t size, uint32_t type, |
||
195 | + uint32_t flags, const struct nftnl_expr *e) |
||
196 | +{ |
||
197 | + switch(type) { |
||
198 | + case NFTNL_OUTPUT_DEFAULT: |
||
199 | + return nftnl_expr_flow_snprintf_default(buf, size, e); |
||
200 | + case NFTNL_OUTPUT_XML: |
||
201 | + case NFTNL_OUTPUT_JSON: |
||
202 | + return nftnl_expr_flow_export(buf, size, e, type); |
||
203 | + default: |
||
204 | + break; |
||
205 | + } |
||
206 | + return -1; |
||
207 | +} |
||
208 | + |
||
209 | +static void nftnl_expr_flow_free(const struct nftnl_expr *e) |
||
210 | +{ |
||
211 | + struct nftnl_expr_flow *flow = nftnl_expr_data(e); |
||
212 | + |
||
213 | + xfree(flow->table_name); |
||
214 | +} |
||
215 | + |
||
216 | +static bool nftnl_expr_flow_cmp(const struct nftnl_expr *e1, |
||
217 | + const struct nftnl_expr *e2) |
||
218 | +{ |
||
219 | + struct nftnl_expr_flow *l1 = nftnl_expr_data(e1); |
||
220 | + struct nftnl_expr_flow *l2 = nftnl_expr_data(e2); |
||
221 | + bool eq = true; |
||
222 | + |
||
223 | + if (e1->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME)) |
||
224 | + eq &= !strcmp(l1->table_name, l2->table_name); |
||
225 | + |
||
226 | + return eq; |
||
227 | +} |
||
228 | + |
||
229 | +struct expr_ops expr_ops_flow = { |
||
230 | + .name = "flow_offload", |
||
231 | + .alloc_len = sizeof(struct nftnl_expr_flow), |
||
232 | + .max_attr = NFTA_FLOW_MAX, |
||
233 | + .free = nftnl_expr_flow_free, |
||
234 | + .cmp = nftnl_expr_flow_cmp, |
||
235 | + .set = nftnl_expr_flow_set, |
||
236 | + .get = nftnl_expr_flow_get, |
||
237 | + .parse = nftnl_expr_flow_parse, |
||
238 | + .build = nftnl_expr_flow_build, |
||
239 | + .snprintf = nftnl_expr_flow_snprintf, |
||
240 | + .json_parse = nftnl_expr_flow_json_parse, |
||
241 | +}; |
||
242 | --- a/src/expr_ops.c |
||
243 | +++ b/src/expr_ops.c |
||
244 | @@ -33,6 +33,7 @@ extern struct expr_ops expr_ops_target; |
||
245 | extern struct expr_ops expr_ops_dynset; |
||
246 | extern struct expr_ops expr_ops_hash; |
||
247 | extern struct expr_ops expr_ops_fib; |
||
248 | +extern struct expr_ops expr_ops_flow; |
||
249 | |||
250 | static struct expr_ops expr_ops_notrack = { |
||
251 | .name = "notrack", |
||
252 | @@ -69,6 +70,7 @@ static struct expr_ops *expr_ops[] = { |
||
253 | &expr_ops_hash, |
||
254 | &expr_ops_fib, |
||
255 | &expr_ops_objref, |
||
256 | + &expr_ops_flow, |
||
257 | NULL, |
||
258 | }; |
||
259 |