Commit | Line | Data |
---|---|---|
8f256622 PNA |
1 | #ifndef _NET_FLOW_OFFLOAD_H |
2 | #define _NET_FLOW_OFFLOAD_H | |
3 | ||
fa85999f | 4 | #include <linux/kernel.h> |
a7323311 | 5 | #include <linux/list.h> |
8f256622 | 6 | #include <net/flow_dissector.h> |
4e481908 | 7 | #include <linux/rhashtable.h> |
8f256622 PNA |
8 | |
9 | struct flow_match { | |
10 | struct flow_dissector *dissector; | |
11 | void *mask; | |
12 | void *key; | |
13 | }; | |
14 | ||
9558a83a JP |
15 | struct flow_match_meta { |
16 | struct flow_dissector_key_meta *key, *mask; | |
17 | }; | |
18 | ||
8f256622 PNA |
19 | struct flow_match_basic { |
20 | struct flow_dissector_key_basic *key, *mask; | |
21 | }; | |
22 | ||
23 | struct flow_match_control { | |
24 | struct flow_dissector_key_control *key, *mask; | |
25 | }; | |
26 | ||
27 | struct flow_match_eth_addrs { | |
28 | struct flow_dissector_key_eth_addrs *key, *mask; | |
29 | }; | |
30 | ||
31 | struct flow_match_vlan { | |
32 | struct flow_dissector_key_vlan *key, *mask; | |
33 | }; | |
34 | ||
35 | struct flow_match_ipv4_addrs { | |
36 | struct flow_dissector_key_ipv4_addrs *key, *mask; | |
37 | }; | |
38 | ||
39 | struct flow_match_ipv6_addrs { | |
40 | struct flow_dissector_key_ipv6_addrs *key, *mask; | |
41 | }; | |
42 | ||
43 | struct flow_match_ip { | |
44 | struct flow_dissector_key_ip *key, *mask; | |
45 | }; | |
46 | ||
47 | struct flow_match_ports { | |
48 | struct flow_dissector_key_ports *key, *mask; | |
49 | }; | |
50 | ||
51 | struct flow_match_icmp { | |
52 | struct flow_dissector_key_icmp *key, *mask; | |
53 | }; | |
54 | ||
55 | struct flow_match_tcp { | |
56 | struct flow_dissector_key_tcp *key, *mask; | |
57 | }; | |
58 | ||
59 | struct flow_match_mpls { | |
60 | struct flow_dissector_key_mpls *key, *mask; | |
61 | }; | |
62 | ||
63 | struct flow_match_enc_keyid { | |
64 | struct flow_dissector_key_keyid *key, *mask; | |
65 | }; | |
66 | ||
67 | struct flow_match_enc_opts { | |
68 | struct flow_dissector_key_enc_opts *key, *mask; | |
69 | }; | |
70 | ||
71 | struct flow_rule; | |
72 | ||
9558a83a JP |
73 | void flow_rule_match_meta(const struct flow_rule *rule, |
74 | struct flow_match_meta *out); | |
8f256622 PNA |
75 | void flow_rule_match_basic(const struct flow_rule *rule, |
76 | struct flow_match_basic *out); | |
77 | void flow_rule_match_control(const struct flow_rule *rule, | |
78 | struct flow_match_control *out); | |
79 | void flow_rule_match_eth_addrs(const struct flow_rule *rule, | |
80 | struct flow_match_eth_addrs *out); | |
81 | void flow_rule_match_vlan(const struct flow_rule *rule, | |
82 | struct flow_match_vlan *out); | |
bae9ed69 EC |
83 | void flow_rule_match_cvlan(const struct flow_rule *rule, |
84 | struct flow_match_vlan *out); | |
8f256622 PNA |
85 | void flow_rule_match_ipv4_addrs(const struct flow_rule *rule, |
86 | struct flow_match_ipv4_addrs *out); | |
87 | void flow_rule_match_ipv6_addrs(const struct flow_rule *rule, | |
88 | struct flow_match_ipv6_addrs *out); | |
89 | void flow_rule_match_ip(const struct flow_rule *rule, | |
90 | struct flow_match_ip *out); | |
91 | void flow_rule_match_ports(const struct flow_rule *rule, | |
92 | struct flow_match_ports *out); | |
93 | void flow_rule_match_tcp(const struct flow_rule *rule, | |
94 | struct flow_match_tcp *out); | |
95 | void flow_rule_match_icmp(const struct flow_rule *rule, | |
96 | struct flow_match_icmp *out); | |
97 | void flow_rule_match_mpls(const struct flow_rule *rule, | |
98 | struct flow_match_mpls *out); | |
99 | void flow_rule_match_enc_control(const struct flow_rule *rule, | |
100 | struct flow_match_control *out); | |
101 | void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule, | |
102 | struct flow_match_ipv4_addrs *out); | |
103 | void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule, | |
104 | struct flow_match_ipv6_addrs *out); | |
105 | void flow_rule_match_enc_ip(const struct flow_rule *rule, | |
106 | struct flow_match_ip *out); | |
107 | void flow_rule_match_enc_ports(const struct flow_rule *rule, | |
108 | struct flow_match_ports *out); | |
109 | void flow_rule_match_enc_keyid(const struct flow_rule *rule, | |
110 | struct flow_match_enc_keyid *out); | |
111 | void flow_rule_match_enc_opts(const struct flow_rule *rule, | |
112 | struct flow_match_enc_opts *out); | |
113 | ||
e3ab786b PNA |
114 | enum flow_action_id { |
115 | FLOW_ACTION_ACCEPT = 0, | |
116 | FLOW_ACTION_DROP, | |
117 | FLOW_ACTION_TRAP, | |
118 | FLOW_ACTION_GOTO, | |
119 | FLOW_ACTION_REDIRECT, | |
120 | FLOW_ACTION_MIRRED, | |
48e584ac JH |
121 | FLOW_ACTION_REDIRECT_INGRESS, |
122 | FLOW_ACTION_MIRRED_INGRESS, | |
e3ab786b PNA |
123 | FLOW_ACTION_VLAN_PUSH, |
124 | FLOW_ACTION_VLAN_POP, | |
125 | FLOW_ACTION_VLAN_MANGLE, | |
126 | FLOW_ACTION_TUNNEL_ENCAP, | |
127 | FLOW_ACTION_TUNNEL_DECAP, | |
128 | FLOW_ACTION_MANGLE, | |
129 | FLOW_ACTION_ADD, | |
130 | FLOW_ACTION_CSUM, | |
131 | FLOW_ACTION_MARK, | |
fb1b775a | 132 | FLOW_ACTION_PTYPE, |
8bec2833 PNA |
133 | FLOW_ACTION_WAKE, |
134 | FLOW_ACTION_QUEUE, | |
a7a7be60 | 135 | FLOW_ACTION_SAMPLE, |
8c8cfc6e | 136 | FLOW_ACTION_POLICE, |
b57dc7c1 | 137 | FLOW_ACTION_CT, |
6749d590 JH |
138 | FLOW_ACTION_MPLS_PUSH, |
139 | FLOW_ACTION_MPLS_POP, | |
140 | FLOW_ACTION_MPLS_MANGLE, | |
7a978759 | 141 | NUM_FLOW_ACTIONS, |
e3ab786b PNA |
142 | }; |
143 | ||
144 | /* This is mirroring enum pedit_header_type definition for easy mapping between | |
145 | * tc pedit action. Legacy TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK is mapped to | |
146 | * FLOW_ACT_MANGLE_UNSPEC, which is supported by no driver. | |
147 | */ | |
148 | enum flow_action_mangle_base { | |
149 | FLOW_ACT_MANGLE_UNSPEC = 0, | |
150 | FLOW_ACT_MANGLE_HDR_TYPE_ETH, | |
151 | FLOW_ACT_MANGLE_HDR_TYPE_IP4, | |
152 | FLOW_ACT_MANGLE_HDR_TYPE_IP6, | |
153 | FLOW_ACT_MANGLE_HDR_TYPE_TCP, | |
154 | FLOW_ACT_MANGLE_HDR_TYPE_UDP, | |
155 | }; | |
156 | ||
1158958a VB |
157 | typedef void (*action_destr)(void *priv); |
158 | ||
e3ab786b PNA |
159 | struct flow_action_entry { |
160 | enum flow_action_id id; | |
1158958a VB |
161 | action_destr destructor; |
162 | void *destructor_priv; | |
e3ab786b PNA |
163 | union { |
164 | u32 chain_index; /* FLOW_ACTION_GOTO */ | |
165 | struct net_device *dev; /* FLOW_ACTION_REDIRECT */ | |
166 | struct { /* FLOW_ACTION_VLAN */ | |
167 | u16 vid; | |
168 | __be16 proto; | |
169 | u8 prio; | |
170 | } vlan; | |
171 | struct { /* FLOW_ACTION_PACKET_EDIT */ | |
172 | enum flow_action_mangle_base htype; | |
173 | u32 offset; | |
174 | u32 mask; | |
175 | u32 val; | |
176 | } mangle; | |
1158958a | 177 | struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */ |
e3ab786b PNA |
178 | u32 csum_flags; /* FLOW_ACTION_CSUM */ |
179 | u32 mark; /* FLOW_ACTION_MARK */ | |
fb1b775a | 180 | u16 ptype; /* FLOW_ACTION_PTYPE */ |
8bec2833 PNA |
181 | struct { /* FLOW_ACTION_QUEUE */ |
182 | u32 ctx; | |
183 | u32 index; | |
184 | u8 vf; | |
185 | } queue; | |
a7a7be60 PJV |
186 | struct { /* FLOW_ACTION_SAMPLE */ |
187 | struct psample_group *psample_group; | |
188 | u32 rate; | |
189 | u32 trunc_size; | |
190 | bool truncate; | |
191 | } sample; | |
8c8cfc6e PJV |
192 | struct { /* FLOW_ACTION_POLICE */ |
193 | s64 burst; | |
194 | u64 rate_bytes_ps; | |
195 | } police; | |
b57dc7c1 PB |
196 | struct { /* FLOW_ACTION_CT */ |
197 | int action; | |
198 | u16 zone; | |
199 | } ct; | |
6749d590 JH |
200 | struct { /* FLOW_ACTION_MPLS_PUSH */ |
201 | u32 label; | |
202 | __be16 proto; | |
203 | u8 tc; | |
204 | u8 bos; | |
205 | u8 ttl; | |
206 | } mpls_push; | |
207 | struct { /* FLOW_ACTION_MPLS_POP */ | |
208 | __be16 proto; | |
209 | } mpls_pop; | |
210 | struct { /* FLOW_ACTION_MPLS_MANGLE */ | |
211 | u32 label; | |
212 | u8 tc; | |
213 | u8 bos; | |
214 | u8 ttl; | |
215 | } mpls_mangle; | |
e3ab786b PNA |
216 | }; |
217 | }; | |
218 | ||
219 | struct flow_action { | |
220 | unsigned int num_entries; | |
221 | struct flow_action_entry entries[0]; | |
222 | }; | |
223 | ||
224 | static inline bool flow_action_has_entries(const struct flow_action *action) | |
225 | { | |
226 | return action->num_entries; | |
227 | } | |
228 | ||
ab79af32 PJV |
229 | /** |
230 | * flow_action_has_one_action() - check if exactly one action is present | |
231 | * @action: tc filter flow offload action | |
232 | * | |
233 | * Returns true if exactly one action is present. | |
234 | */ | |
235 | static inline bool flow_offload_has_one_action(const struct flow_action *action) | |
236 | { | |
237 | return action->num_entries == 1; | |
238 | } | |
239 | ||
e3ab786b | 240 | #define flow_action_for_each(__i, __act, __actions) \ |
6663cf82 | 241 | for (__i = 0, __act = &(__actions)->entries[0]; __i < (__actions)->num_entries; __act = &(__actions)->entries[++__i]) |
e3ab786b | 242 | |
8f256622 PNA |
243 | struct flow_rule { |
244 | struct flow_match match; | |
e3ab786b | 245 | struct flow_action action; |
8f256622 PNA |
246 | }; |
247 | ||
e3ab786b | 248 | struct flow_rule *flow_rule_alloc(unsigned int num_actions); |
8f256622 PNA |
249 | |
250 | static inline bool flow_rule_match_key(const struct flow_rule *rule, | |
251 | enum flow_dissector_key_id key) | |
252 | { | |
253 | return dissector_uses_key(rule->match.dissector, key); | |
254 | } | |
255 | ||
3b1903ef PNA |
256 | struct flow_stats { |
257 | u64 pkts; | |
258 | u64 bytes; | |
259 | u64 lastused; | |
260 | }; | |
261 | ||
262 | static inline void flow_stats_update(struct flow_stats *flow_stats, | |
263 | u64 bytes, u64 pkts, u64 lastused) | |
264 | { | |
9f9dc493 JH |
265 | flow_stats->pkts += pkts; |
266 | flow_stats->bytes += bytes; | |
267 | flow_stats->lastused = max_t(u64, flow_stats->lastused, lastused); | |
3b1903ef PNA |
268 | } |
269 | ||
4e95bc26 | 270 | enum flow_block_command { |
9c0e189e PNA |
271 | FLOW_BLOCK_BIND, |
272 | FLOW_BLOCK_UNBIND, | |
4e95bc26 PNA |
273 | }; |
274 | ||
275 | enum flow_block_binder_type { | |
32f8c409 PNA |
276 | FLOW_BLOCK_BINDER_TYPE_UNSPEC, |
277 | FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS, | |
278 | FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS, | |
4e95bc26 PNA |
279 | }; |
280 | ||
14bfb13f PNA |
281 | struct flow_block { |
282 | struct list_head cb_list; | |
283 | }; | |
284 | ||
4e95bc26 PNA |
285 | struct netlink_ext_ack; |
286 | ||
287 | struct flow_block_offload { | |
288 | enum flow_block_command command; | |
289 | enum flow_block_binder_type binder_type; | |
955bcb6e | 290 | bool block_shared; |
c9f14470 | 291 | bool unlocked_driver_cb; |
da3eeb90 | 292 | struct net *net; |
14bfb13f | 293 | struct flow_block *block; |
da3eeb90 | 294 | struct list_head cb_list; |
4e95bc26 PNA |
295 | struct list_head *driver_block_list; |
296 | struct netlink_ext_ack *extack; | |
297 | }; | |
298 | ||
a7323311 PNA |
299 | enum tc_setup_type; |
300 | typedef int flow_setup_cb_t(enum tc_setup_type type, void *type_data, | |
301 | void *cb_priv); | |
302 | ||
d63db30c | 303 | struct flow_block_cb { |
da3eeb90 | 304 | struct list_head driver_list; |
d63db30c | 305 | struct list_head list; |
a7323311 | 306 | flow_setup_cb_t *cb; |
d63db30c PNA |
307 | void *cb_ident; |
308 | void *cb_priv; | |
309 | void (*release)(void *cb_priv); | |
310 | unsigned int refcnt; | |
311 | }; | |
312 | ||
a7323311 | 313 | struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb, |
d63db30c PNA |
314 | void *cb_ident, void *cb_priv, |
315 | void (*release)(void *cb_priv)); | |
316 | void flow_block_cb_free(struct flow_block_cb *block_cb); | |
317 | ||
14bfb13f | 318 | struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block, |
a7323311 | 319 | flow_setup_cb_t *cb, void *cb_ident); |
da3eeb90 | 320 | |
67bd0d5e PNA |
321 | void *flow_block_cb_priv(struct flow_block_cb *block_cb); |
322 | void flow_block_cb_incref(struct flow_block_cb *block_cb); | |
323 | unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb); | |
324 | ||
da3eeb90 PNA |
325 | static inline void flow_block_cb_add(struct flow_block_cb *block_cb, |
326 | struct flow_block_offload *offload) | |
327 | { | |
328 | list_add_tail(&block_cb->list, &offload->cb_list); | |
329 | } | |
330 | ||
331 | static inline void flow_block_cb_remove(struct flow_block_cb *block_cb, | |
332 | struct flow_block_offload *offload) | |
333 | { | |
334 | list_move(&block_cb->list, &offload->cb_list); | |
335 | } | |
336 | ||
a7323311 | 337 | bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident, |
0d4fd02e PNA |
338 | struct list_head *driver_block_list); |
339 | ||
4e95bc26 | 340 | int flow_block_cb_setup_simple(struct flow_block_offload *f, |
a7323311 PNA |
341 | struct list_head *driver_list, |
342 | flow_setup_cb_t *cb, | |
4e95bc26 PNA |
343 | void *cb_ident, void *cb_priv, bool ingress_only); |
344 | ||
f9e30088 PNA |
345 | enum flow_cls_command { |
346 | FLOW_CLS_REPLACE, | |
347 | FLOW_CLS_DESTROY, | |
348 | FLOW_CLS_STATS, | |
349 | FLOW_CLS_TMPLT_CREATE, | |
350 | FLOW_CLS_TMPLT_DESTROY, | |
351 | }; | |
352 | ||
353 | struct flow_cls_common_offload { | |
354 | u32 chain_index; | |
355 | __be16 protocol; | |
356 | u32 prio; | |
357 | struct netlink_ext_ack *extack; | |
358 | }; | |
359 | ||
360 | struct flow_cls_offload { | |
361 | struct flow_cls_common_offload common; | |
362 | enum flow_cls_command command; | |
363 | unsigned long cookie; | |
364 | struct flow_rule *rule; | |
365 | struct flow_stats stats; | |
366 | u32 classid; | |
367 | }; | |
368 | ||
369 | static inline struct flow_rule * | |
370 | flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd) | |
371 | { | |
372 | return flow_cmd->rule; | |
373 | } | |
374 | ||
14bfb13f PNA |
375 | static inline void flow_block_init(struct flow_block *flow_block) |
376 | { | |
377 | INIT_LIST_HEAD(&flow_block->cb_list); | |
378 | } | |
379 | ||
4e481908 | 380 | typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv, |
381 | enum tc_setup_type type, void *type_data); | |
382 | ||
383 | typedef void flow_indr_block_ing_cmd_t(struct net_device *dev, | |
384 | flow_indr_block_bind_cb_t *cb, | |
385 | void *cb_priv, | |
386 | enum flow_block_command command); | |
387 | ||
1150ab0f | 388 | struct flow_indr_block_ing_entry { |
389 | flow_indr_block_ing_cmd_t *cb; | |
390 | struct list_head list; | |
391 | }; | |
392 | ||
393 | void flow_indr_add_block_ing_cb(struct flow_indr_block_ing_entry *entry); | |
394 | ||
395 | void flow_indr_del_block_ing_cb(struct flow_indr_block_ing_entry *entry); | |
396 | ||
4e481908 | 397 | int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, |
398 | flow_indr_block_bind_cb_t *cb, | |
399 | void *cb_ident); | |
400 | ||
401 | void __flow_indr_block_cb_unregister(struct net_device *dev, | |
402 | flow_indr_block_bind_cb_t *cb, | |
403 | void *cb_ident); | |
404 | ||
405 | int flow_indr_block_cb_register(struct net_device *dev, void *cb_priv, | |
406 | flow_indr_block_bind_cb_t *cb, void *cb_ident); | |
407 | ||
408 | void flow_indr_block_cb_unregister(struct net_device *dev, | |
409 | flow_indr_block_bind_cb_t *cb, | |
410 | void *cb_ident); | |
411 | ||
412 | void flow_indr_block_call(struct net_device *dev, | |
4e481908 | 413 | struct flow_block_offload *bo, |
414 | enum flow_block_command command); | |
415 | ||
8f256622 | 416 | #endif /* _NET_FLOW_OFFLOAD_H */ |