Line data Source code
1 : #ifndef _NET_FLOW_OFFLOAD_H
2 : #define _NET_FLOW_OFFLOAD_H
3 :
4 : #include <linux/kernel.h>
5 : #include <linux/list.h>
6 : #include <linux/netlink.h>
7 : #include <net/flow_dissector.h>
8 :
9 : struct flow_match {
10 : struct flow_dissector *dissector;
11 : void *mask;
12 : void *key;
13 : };
14 :
15 : struct flow_match_meta {
16 : struct flow_dissector_key_meta *key, *mask;
17 : };
18 :
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_match_ct {
72 : struct flow_dissector_key_ct *key, *mask;
73 : };
74 :
75 : struct flow_rule;
76 :
77 : void flow_rule_match_meta(const struct flow_rule *rule,
78 : struct flow_match_meta *out);
79 : void flow_rule_match_basic(const struct flow_rule *rule,
80 : struct flow_match_basic *out);
81 : void flow_rule_match_control(const struct flow_rule *rule,
82 : struct flow_match_control *out);
83 : void flow_rule_match_eth_addrs(const struct flow_rule *rule,
84 : struct flow_match_eth_addrs *out);
85 : void flow_rule_match_vlan(const struct flow_rule *rule,
86 : struct flow_match_vlan *out);
87 : void flow_rule_match_cvlan(const struct flow_rule *rule,
88 : struct flow_match_vlan *out);
89 : void flow_rule_match_ipv4_addrs(const struct flow_rule *rule,
90 : struct flow_match_ipv4_addrs *out);
91 : void flow_rule_match_ipv6_addrs(const struct flow_rule *rule,
92 : struct flow_match_ipv6_addrs *out);
93 : void flow_rule_match_ip(const struct flow_rule *rule,
94 : struct flow_match_ip *out);
95 : void flow_rule_match_ports(const struct flow_rule *rule,
96 : struct flow_match_ports *out);
97 : void flow_rule_match_tcp(const struct flow_rule *rule,
98 : struct flow_match_tcp *out);
99 : void flow_rule_match_icmp(const struct flow_rule *rule,
100 : struct flow_match_icmp *out);
101 : void flow_rule_match_mpls(const struct flow_rule *rule,
102 : struct flow_match_mpls *out);
103 : void flow_rule_match_enc_control(const struct flow_rule *rule,
104 : struct flow_match_control *out);
105 : void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule,
106 : struct flow_match_ipv4_addrs *out);
107 : void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule,
108 : struct flow_match_ipv6_addrs *out);
109 : void flow_rule_match_enc_ip(const struct flow_rule *rule,
110 : struct flow_match_ip *out);
111 : void flow_rule_match_enc_ports(const struct flow_rule *rule,
112 : struct flow_match_ports *out);
113 : void flow_rule_match_enc_keyid(const struct flow_rule *rule,
114 : struct flow_match_enc_keyid *out);
115 : void flow_rule_match_enc_opts(const struct flow_rule *rule,
116 : struct flow_match_enc_opts *out);
117 : void flow_rule_match_ct(const struct flow_rule *rule,
118 : struct flow_match_ct *out);
119 :
120 : enum flow_action_id {
121 : FLOW_ACTION_ACCEPT = 0,
122 : FLOW_ACTION_DROP,
123 : FLOW_ACTION_TRAP,
124 : FLOW_ACTION_GOTO,
125 : FLOW_ACTION_REDIRECT,
126 : FLOW_ACTION_MIRRED,
127 : FLOW_ACTION_REDIRECT_INGRESS,
128 : FLOW_ACTION_MIRRED_INGRESS,
129 : FLOW_ACTION_VLAN_PUSH,
130 : FLOW_ACTION_VLAN_POP,
131 : FLOW_ACTION_VLAN_MANGLE,
132 : FLOW_ACTION_TUNNEL_ENCAP,
133 : FLOW_ACTION_TUNNEL_DECAP,
134 : FLOW_ACTION_MANGLE,
135 : FLOW_ACTION_ADD,
136 : FLOW_ACTION_CSUM,
137 : FLOW_ACTION_MARK,
138 : FLOW_ACTION_PTYPE,
139 : FLOW_ACTION_PRIORITY,
140 : FLOW_ACTION_WAKE,
141 : FLOW_ACTION_QUEUE,
142 : FLOW_ACTION_SAMPLE,
143 : FLOW_ACTION_POLICE,
144 : FLOW_ACTION_CT,
145 : FLOW_ACTION_CT_METADATA,
146 : FLOW_ACTION_MPLS_PUSH,
147 : FLOW_ACTION_MPLS_POP,
148 : FLOW_ACTION_MPLS_MANGLE,
149 : FLOW_ACTION_GATE,
150 : NUM_FLOW_ACTIONS,
151 : };
152 :
153 : /* This is mirroring enum pedit_header_type definition for easy mapping between
154 : * tc pedit action. Legacy TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK is mapped to
155 : * FLOW_ACT_MANGLE_UNSPEC, which is supported by no driver.
156 : */
157 : enum flow_action_mangle_base {
158 : FLOW_ACT_MANGLE_UNSPEC = 0,
159 : FLOW_ACT_MANGLE_HDR_TYPE_ETH,
160 : FLOW_ACT_MANGLE_HDR_TYPE_IP4,
161 : FLOW_ACT_MANGLE_HDR_TYPE_IP6,
162 : FLOW_ACT_MANGLE_HDR_TYPE_TCP,
163 : FLOW_ACT_MANGLE_HDR_TYPE_UDP,
164 : };
165 :
166 : enum flow_action_hw_stats_bit {
167 : FLOW_ACTION_HW_STATS_IMMEDIATE_BIT,
168 : FLOW_ACTION_HW_STATS_DELAYED_BIT,
169 : FLOW_ACTION_HW_STATS_DISABLED_BIT,
170 :
171 : FLOW_ACTION_HW_STATS_NUM_BITS
172 : };
173 :
174 : enum flow_action_hw_stats {
175 : FLOW_ACTION_HW_STATS_IMMEDIATE =
176 : BIT(FLOW_ACTION_HW_STATS_IMMEDIATE_BIT),
177 : FLOW_ACTION_HW_STATS_DELAYED = BIT(FLOW_ACTION_HW_STATS_DELAYED_BIT),
178 : FLOW_ACTION_HW_STATS_ANY = FLOW_ACTION_HW_STATS_IMMEDIATE |
179 : FLOW_ACTION_HW_STATS_DELAYED,
180 : FLOW_ACTION_HW_STATS_DISABLED =
181 : BIT(FLOW_ACTION_HW_STATS_DISABLED_BIT),
182 : FLOW_ACTION_HW_STATS_DONT_CARE = BIT(FLOW_ACTION_HW_STATS_NUM_BITS) - 1,
183 : };
184 :
185 : typedef void (*action_destr)(void *priv);
186 :
187 : struct flow_action_cookie {
188 : u32 cookie_len;
189 : u8 cookie[];
190 : };
191 :
192 : struct flow_action_cookie *flow_action_cookie_create(void *data,
193 : unsigned int len,
194 : gfp_t gfp);
195 : void flow_action_cookie_destroy(struct flow_action_cookie *cookie);
196 :
197 : struct flow_action_entry {
198 : enum flow_action_id id;
199 : enum flow_action_hw_stats hw_stats;
200 : action_destr destructor;
201 : void *destructor_priv;
202 : union {
203 : u32 chain_index; /* FLOW_ACTION_GOTO */
204 : struct net_device *dev; /* FLOW_ACTION_REDIRECT */
205 : struct { /* FLOW_ACTION_VLAN */
206 : u16 vid;
207 : __be16 proto;
208 : u8 prio;
209 : } vlan;
210 : struct { /* FLOW_ACTION_MANGLE */
211 : /* FLOW_ACTION_ADD */
212 : enum flow_action_mangle_base htype;
213 : u32 offset;
214 : u32 mask;
215 : u32 val;
216 : } mangle;
217 : struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */
218 : u32 csum_flags; /* FLOW_ACTION_CSUM */
219 : u32 mark; /* FLOW_ACTION_MARK */
220 : u16 ptype; /* FLOW_ACTION_PTYPE */
221 : u32 priority; /* FLOW_ACTION_PRIORITY */
222 : struct { /* FLOW_ACTION_QUEUE */
223 : u32 ctx;
224 : u32 index;
225 : u8 vf;
226 : } queue;
227 : struct { /* FLOW_ACTION_SAMPLE */
228 : struct psample_group *psample_group;
229 : u32 rate;
230 : u32 trunc_size;
231 : bool truncate;
232 : } sample;
233 : struct { /* FLOW_ACTION_POLICE */
234 : u32 index;
235 : u32 burst;
236 : u64 rate_bytes_ps;
237 : u32 mtu;
238 : } police;
239 : struct { /* FLOW_ACTION_CT */
240 : int action;
241 : u16 zone;
242 : struct nf_flowtable *flow_table;
243 : } ct;
244 : struct {
245 : unsigned long cookie;
246 : u32 mark;
247 : u32 labels[4];
248 : bool orig_dir;
249 : } ct_metadata;
250 : struct { /* FLOW_ACTION_MPLS_PUSH */
251 : u32 label;
252 : __be16 proto;
253 : u8 tc;
254 : u8 bos;
255 : u8 ttl;
256 : } mpls_push;
257 : struct { /* FLOW_ACTION_MPLS_POP */
258 : __be16 proto;
259 : } mpls_pop;
260 : struct { /* FLOW_ACTION_MPLS_MANGLE */
261 : u32 label;
262 : u8 tc;
263 : u8 bos;
264 : u8 ttl;
265 : } mpls_mangle;
266 : struct {
267 : u32 index;
268 : s32 prio;
269 : u64 basetime;
270 : u64 cycletime;
271 : u64 cycletimeext;
272 : u32 num_entries;
273 : struct action_gate_entry *entries;
274 : } gate;
275 : };
276 : struct flow_action_cookie *cookie; /* user defined action cookie */
277 : };
278 :
279 : struct flow_action {
280 : unsigned int num_entries;
281 : struct flow_action_entry entries[];
282 : };
283 :
284 : static inline bool flow_action_has_entries(const struct flow_action *action)
285 : {
286 : return action->num_entries;
287 : }
288 :
289 : /**
290 : * flow_action_has_one_action() - check if exactly one action is present
291 : * @action: tc filter flow offload action
292 : *
293 : * Returns true if exactly one action is present.
294 : */
295 : static inline bool flow_offload_has_one_action(const struct flow_action *action)
296 : {
297 : return action->num_entries == 1;
298 : }
299 :
300 : #define flow_action_for_each(__i, __act, __actions) \
301 : for (__i = 0, __act = &(__actions)->entries[0]; \
302 : __i < (__actions)->num_entries; \
303 : __act = &(__actions)->entries[++__i])
304 :
305 : static inline bool
306 : flow_action_mixed_hw_stats_check(const struct flow_action *action,
307 : struct netlink_ext_ack *extack)
308 : {
309 : const struct flow_action_entry *action_entry;
310 : u8 last_hw_stats;
311 : int i;
312 :
313 : if (flow_offload_has_one_action(action))
314 : return true;
315 :
316 : flow_action_for_each(i, action_entry, action) {
317 : if (i && action_entry->hw_stats != last_hw_stats) {
318 : NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
319 : return false;
320 : }
321 : last_hw_stats = action_entry->hw_stats;
322 : }
323 : return true;
324 : }
325 :
326 : static inline const struct flow_action_entry *
327 : flow_action_first_entry_get(const struct flow_action *action)
328 : {
329 : WARN_ON(!flow_action_has_entries(action));
330 : return &action->entries[0];
331 : }
332 :
333 : static inline bool
334 : __flow_action_hw_stats_check(const struct flow_action *action,
335 : struct netlink_ext_ack *extack,
336 : bool check_allow_bit,
337 : enum flow_action_hw_stats_bit allow_bit)
338 : {
339 : const struct flow_action_entry *action_entry;
340 :
341 : if (!flow_action_has_entries(action))
342 : return true;
343 : if (!flow_action_mixed_hw_stats_check(action, extack))
344 : return false;
345 :
346 : action_entry = flow_action_first_entry_get(action);
347 :
348 : /* Zero is not a legal value for hw_stats, catch anyone passing it */
349 : WARN_ON_ONCE(!action_entry->hw_stats);
350 :
351 : if (!check_allow_bit &&
352 : ~action_entry->hw_stats & FLOW_ACTION_HW_STATS_ANY) {
353 : NL_SET_ERR_MSG_MOD(extack, "Driver supports only default HW stats type \"any\"");
354 : return false;
355 : } else if (check_allow_bit &&
356 : !(action_entry->hw_stats & BIT(allow_bit))) {
357 : NL_SET_ERR_MSG_MOD(extack, "Driver does not support selected HW stats type");
358 : return false;
359 : }
360 : return true;
361 : }
362 :
363 : static inline bool
364 : flow_action_hw_stats_check(const struct flow_action *action,
365 : struct netlink_ext_ack *extack,
366 : enum flow_action_hw_stats_bit allow_bit)
367 : {
368 : return __flow_action_hw_stats_check(action, extack, true, allow_bit);
369 : }
370 :
371 : static inline bool
372 : flow_action_basic_hw_stats_check(const struct flow_action *action,
373 : struct netlink_ext_ack *extack)
374 : {
375 : return __flow_action_hw_stats_check(action, extack, false, 0);
376 : }
377 :
378 : struct flow_rule {
379 : struct flow_match match;
380 : struct flow_action action;
381 : };
382 :
383 : struct flow_rule *flow_rule_alloc(unsigned int num_actions);
384 :
385 : static inline bool flow_rule_match_key(const struct flow_rule *rule,
386 : enum flow_dissector_key_id key)
387 : {
388 : return dissector_uses_key(rule->match.dissector, key);
389 : }
390 :
391 : struct flow_stats {
392 : u64 pkts;
393 : u64 bytes;
394 : u64 drops;
395 : u64 lastused;
396 : enum flow_action_hw_stats used_hw_stats;
397 : bool used_hw_stats_valid;
398 : };
399 :
400 : static inline void flow_stats_update(struct flow_stats *flow_stats,
401 : u64 bytes, u64 pkts,
402 : u64 drops, u64 lastused,
403 : enum flow_action_hw_stats used_hw_stats)
404 : {
405 : flow_stats->pkts += pkts;
406 : flow_stats->bytes += bytes;
407 : flow_stats->drops += drops;
408 : flow_stats->lastused = max_t(u64, flow_stats->lastused, lastused);
409 :
410 : /* The driver should pass value with a maximum of one bit set.
411 : * Passing FLOW_ACTION_HW_STATS_ANY is invalid.
412 : */
413 : WARN_ON(used_hw_stats == FLOW_ACTION_HW_STATS_ANY);
414 : flow_stats->used_hw_stats |= used_hw_stats;
415 : flow_stats->used_hw_stats_valid = true;
416 : }
417 :
418 : enum flow_block_command {
419 : FLOW_BLOCK_BIND,
420 : FLOW_BLOCK_UNBIND,
421 : };
422 :
423 : enum flow_block_binder_type {
424 : FLOW_BLOCK_BINDER_TYPE_UNSPEC,
425 : FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
426 : FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
427 : FLOW_BLOCK_BINDER_TYPE_RED_EARLY_DROP,
428 : FLOW_BLOCK_BINDER_TYPE_RED_MARK,
429 : };
430 :
431 : struct flow_block {
432 : struct list_head cb_list;
433 : };
434 :
435 : struct netlink_ext_ack;
436 :
437 : struct flow_block_offload {
438 : enum flow_block_command command;
439 : enum flow_block_binder_type binder_type;
440 : bool block_shared;
441 : bool unlocked_driver_cb;
442 : struct net *net;
443 : struct flow_block *block;
444 : struct list_head cb_list;
445 : struct list_head *driver_block_list;
446 : struct netlink_ext_ack *extack;
447 : struct Qdisc *sch;
448 : };
449 :
450 : enum tc_setup_type;
451 : typedef int flow_setup_cb_t(enum tc_setup_type type, void *type_data,
452 : void *cb_priv);
453 :
454 : struct flow_block_cb;
455 :
456 : struct flow_block_indr {
457 : struct list_head list;
458 : struct net_device *dev;
459 : struct Qdisc *sch;
460 : enum flow_block_binder_type binder_type;
461 : void *data;
462 : void *cb_priv;
463 : void (*cleanup)(struct flow_block_cb *block_cb);
464 : };
465 :
466 : struct flow_block_cb {
467 : struct list_head driver_list;
468 : struct list_head list;
469 : flow_setup_cb_t *cb;
470 : void *cb_ident;
471 : void *cb_priv;
472 : void (*release)(void *cb_priv);
473 : struct flow_block_indr indr;
474 : unsigned int refcnt;
475 : };
476 :
477 : struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
478 : void *cb_ident, void *cb_priv,
479 : void (*release)(void *cb_priv));
480 : struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
481 : void *cb_ident, void *cb_priv,
482 : void (*release)(void *cb_priv),
483 : struct flow_block_offload *bo,
484 : struct net_device *dev,
485 : struct Qdisc *sch, void *data,
486 : void *indr_cb_priv,
487 : void (*cleanup)(struct flow_block_cb *block_cb));
488 : void flow_block_cb_free(struct flow_block_cb *block_cb);
489 :
490 : struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
491 : flow_setup_cb_t *cb, void *cb_ident);
492 :
493 : void *flow_block_cb_priv(struct flow_block_cb *block_cb);
494 : void flow_block_cb_incref(struct flow_block_cb *block_cb);
495 : unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb);
496 :
497 0 : static inline void flow_block_cb_add(struct flow_block_cb *block_cb,
498 : struct flow_block_offload *offload)
499 : {
500 0 : list_add_tail(&block_cb->list, &offload->cb_list);
501 : }
502 :
503 0 : static inline void flow_block_cb_remove(struct flow_block_cb *block_cb,
504 : struct flow_block_offload *offload)
505 : {
506 0 : list_move(&block_cb->list, &offload->cb_list);
507 : }
508 :
509 : static inline void flow_indr_block_cb_remove(struct flow_block_cb *block_cb,
510 : struct flow_block_offload *offload)
511 : {
512 : list_del(&block_cb->indr.list);
513 : list_move(&block_cb->list, &offload->cb_list);
514 : }
515 :
516 : bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
517 : struct list_head *driver_block_list);
518 :
519 : int flow_block_cb_setup_simple(struct flow_block_offload *f,
520 : struct list_head *driver_list,
521 : flow_setup_cb_t *cb,
522 : void *cb_ident, void *cb_priv, bool ingress_only);
523 :
524 : enum flow_cls_command {
525 : FLOW_CLS_REPLACE,
526 : FLOW_CLS_DESTROY,
527 : FLOW_CLS_STATS,
528 : FLOW_CLS_TMPLT_CREATE,
529 : FLOW_CLS_TMPLT_DESTROY,
530 : };
531 :
532 : struct flow_cls_common_offload {
533 : u32 chain_index;
534 : __be16 protocol;
535 : u32 prio;
536 : struct netlink_ext_ack *extack;
537 : };
538 :
539 : struct flow_cls_offload {
540 : struct flow_cls_common_offload common;
541 : enum flow_cls_command command;
542 : unsigned long cookie;
543 : struct flow_rule *rule;
544 : struct flow_stats stats;
545 : u32 classid;
546 : };
547 :
548 : static inline struct flow_rule *
549 : flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd)
550 : {
551 : return flow_cmd->rule;
552 : }
553 :
554 : static inline void flow_block_init(struct flow_block *flow_block)
555 : {
556 : INIT_LIST_HEAD(&flow_block->cb_list);
557 : }
558 :
559 : typedef int flow_indr_block_bind_cb_t(struct net_device *dev, struct Qdisc *sch, void *cb_priv,
560 : enum tc_setup_type type, void *type_data,
561 : void *data,
562 : void (*cleanup)(struct flow_block_cb *block_cb));
563 :
564 : int flow_indr_dev_register(flow_indr_block_bind_cb_t *cb, void *cb_priv);
565 : void flow_indr_dev_unregister(flow_indr_block_bind_cb_t *cb, void *cb_priv,
566 : void (*release)(void *cb_priv));
567 : int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
568 : enum tc_setup_type type, void *data,
569 : struct flow_block_offload *bo,
570 : void (*cleanup)(struct flow_block_cb *block_cb));
571 :
572 : #endif /* _NET_FLOW_OFFLOAD_H */
|