xref: /openbmc/linux/include/net/pkt_cls.h (revision 9dae47aba0a055f761176d9297371d5bb24289ec)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __NET_PKT_CLS_H
3 #define __NET_PKT_CLS_H
4 
5 #include <linux/pkt_cls.h>
6 #include <linux/workqueue.h>
7 #include <net/sch_generic.h>
8 #include <net/act_api.h>
9 
10 /* Basic packet classifier frontend definitions. */
11 
12 struct tcf_walker {
13 	int	stop;
14 	int	skip;
15 	int	count;
16 	int	(*fn)(struct tcf_proto *, void *node, struct tcf_walker *);
17 };
18 
19 int register_tcf_proto_ops(struct tcf_proto_ops *ops);
20 int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
21 
22 enum tcf_block_binder_type {
23 	TCF_BLOCK_BINDER_TYPE_UNSPEC,
24 	TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
25 	TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
26 };
27 
28 struct tcf_block_ext_info {
29 	enum tcf_block_binder_type binder_type;
30 	tcf_chain_head_change_t *chain_head_change;
31 	void *chain_head_change_priv;
32 };
33 
34 struct tcf_block_cb;
35 bool tcf_queue_work(struct work_struct *work);
36 
37 #ifdef CONFIG_NET_CLS
38 struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
39 				bool create);
40 void tcf_chain_put(struct tcf_chain *chain);
41 int tcf_block_get(struct tcf_block **p_block,
42 		  struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
43 		  struct netlink_ext_ack *extack);
44 int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
45 		      struct tcf_block_ext_info *ei,
46 		      struct netlink_ext_ack *extack);
47 void tcf_block_put(struct tcf_block *block);
48 void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
49 		       struct tcf_block_ext_info *ei);
50 
51 static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
52 {
53 	return block->q;
54 }
55 
56 static inline struct net_device *tcf_block_dev(struct tcf_block *block)
57 {
58 	return tcf_block_q(block)->dev_queue->dev;
59 }
60 
61 void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
62 struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
63 					 tc_setup_cb_t *cb, void *cb_ident);
64 void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
65 unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
66 struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
67 					     tc_setup_cb_t *cb, void *cb_ident,
68 					     void *cb_priv);
69 int tcf_block_cb_register(struct tcf_block *block,
70 			  tc_setup_cb_t *cb, void *cb_ident,
71 			  void *cb_priv);
72 void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb);
73 void tcf_block_cb_unregister(struct tcf_block *block,
74 			     tc_setup_cb_t *cb, void *cb_ident);
75 
76 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
77 		 struct tcf_result *res, bool compat_mode);
78 
79 #else
80 static inline
81 int tcf_block_get(struct tcf_block **p_block,
82 		  struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
83 		  struct netlink_ext_ack *extack)
84 {
85 	return 0;
86 }
87 
88 static inline
89 int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
90 		      struct tcf_block_ext_info *ei,
91 		      struct netlink_ext_ack *extack)
92 {
93 	return 0;
94 }
95 
96 static inline void tcf_block_put(struct tcf_block *block)
97 {
98 }
99 
100 static inline
101 void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
102 		       struct tcf_block_ext_info *ei)
103 {
104 }
105 
106 static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
107 {
108 	return NULL;
109 }
110 
111 static inline struct net_device *tcf_block_dev(struct tcf_block *block)
112 {
113 	return NULL;
114 }
115 
116 static inline
117 int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
118 			       void *cb_priv)
119 {
120 	return 0;
121 }
122 
123 static inline
124 void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
125 				  void *cb_priv)
126 {
127 }
128 
129 static inline
130 void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
131 {
132 	return NULL;
133 }
134 
135 static inline
136 struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
137 					 tc_setup_cb_t *cb, void *cb_ident)
138 {
139 	return NULL;
140 }
141 
142 static inline
143 void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
144 {
145 }
146 
147 static inline
148 unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
149 {
150 	return 0;
151 }
152 
153 static inline
154 struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
155 					     tc_setup_cb_t *cb, void *cb_ident,
156 					     void *cb_priv)
157 {
158 	return NULL;
159 }
160 
161 static inline
162 int tcf_block_cb_register(struct tcf_block *block,
163 			  tc_setup_cb_t *cb, void *cb_ident,
164 			  void *cb_priv)
165 {
166 	return 0;
167 }
168 
169 static inline
170 void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
171 {
172 }
173 
174 static inline
175 void tcf_block_cb_unregister(struct tcf_block *block,
176 			     tc_setup_cb_t *cb, void *cb_ident)
177 {
178 }
179 
180 static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
181 			       struct tcf_result *res, bool compat_mode)
182 {
183 	return TC_ACT_UNSPEC;
184 }
185 #endif
186 
187 static inline unsigned long
188 __cls_set_class(unsigned long *clp, unsigned long cl)
189 {
190 	return xchg(clp, cl);
191 }
192 
193 static inline unsigned long
194 cls_set_class(struct Qdisc *q, unsigned long *clp, unsigned long cl)
195 {
196 	unsigned long old_cl;
197 
198 	sch_tree_lock(q);
199 	old_cl = __cls_set_class(clp, cl);
200 	sch_tree_unlock(q);
201 	return old_cl;
202 }
203 
204 static inline void
205 tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
206 {
207 	struct Qdisc *q = tp->chain->block->q;
208 	unsigned long cl;
209 
210 	/* Check q as it is not set for shared blocks. In that case,
211 	 * setting class is not supported.
212 	 */
213 	if (!q)
214 		return;
215 	cl = q->ops->cl_ops->bind_tcf(q, base, r->classid);
216 	cl = cls_set_class(q, &r->class, cl);
217 	if (cl)
218 		q->ops->cl_ops->unbind_tcf(q, cl);
219 }
220 
221 static inline void
222 tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
223 {
224 	struct Qdisc *q = tp->chain->block->q;
225 	unsigned long cl;
226 
227 	if (!q)
228 		return;
229 	if ((cl = __cls_set_class(&r->class, 0)) != 0)
230 		q->ops->cl_ops->unbind_tcf(q, cl);
231 }
232 
233 struct tcf_exts {
234 #ifdef CONFIG_NET_CLS_ACT
235 	__u32	type; /* for backward compat(TCA_OLD_COMPAT) */
236 	int nr_actions;
237 	struct tc_action **actions;
238 	struct net *net;
239 #endif
240 	/* Map to export classifier specific extension TLV types to the
241 	 * generic extensions API. Unsupported extensions must be set to 0.
242 	 */
243 	int action;
244 	int police;
245 };
246 
247 static inline int tcf_exts_init(struct tcf_exts *exts, int action, int police)
248 {
249 #ifdef CONFIG_NET_CLS_ACT
250 	exts->type = 0;
251 	exts->nr_actions = 0;
252 	exts->net = NULL;
253 	exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
254 				GFP_KERNEL);
255 	if (!exts->actions)
256 		return -ENOMEM;
257 #endif
258 	exts->action = action;
259 	exts->police = police;
260 	return 0;
261 }
262 
263 /* Return false if the netns is being destroyed in cleanup_net(). Callers
264  * need to do cleanup synchronously in this case, otherwise may race with
265  * tc_action_net_exit(). Return true for other cases.
266  */
267 static inline bool tcf_exts_get_net(struct tcf_exts *exts)
268 {
269 #ifdef CONFIG_NET_CLS_ACT
270 	exts->net = maybe_get_net(exts->net);
271 	return exts->net != NULL;
272 #else
273 	return true;
274 #endif
275 }
276 
277 static inline void tcf_exts_put_net(struct tcf_exts *exts)
278 {
279 #ifdef CONFIG_NET_CLS_ACT
280 	if (exts->net)
281 		put_net(exts->net);
282 #endif
283 }
284 
285 static inline void tcf_exts_to_list(const struct tcf_exts *exts,
286 				    struct list_head *actions)
287 {
288 #ifdef CONFIG_NET_CLS_ACT
289 	int i;
290 
291 	for (i = 0; i < exts->nr_actions; i++) {
292 		struct tc_action *a = exts->actions[i];
293 
294 		list_add_tail(&a->list, actions);
295 	}
296 #endif
297 }
298 
299 static inline void
300 tcf_exts_stats_update(const struct tcf_exts *exts,
301 		      u64 bytes, u64 packets, u64 lastuse)
302 {
303 #ifdef CONFIG_NET_CLS_ACT
304 	int i;
305 
306 	preempt_disable();
307 
308 	for (i = 0; i < exts->nr_actions; i++) {
309 		struct tc_action *a = exts->actions[i];
310 
311 		tcf_action_stats_update(a, bytes, packets, lastuse);
312 	}
313 
314 	preempt_enable();
315 #endif
316 }
317 
318 /**
319  * tcf_exts_has_actions - check if at least one action is present
320  * @exts: tc filter extensions handle
321  *
322  * Returns true if at least one action is present.
323  */
324 static inline bool tcf_exts_has_actions(struct tcf_exts *exts)
325 {
326 #ifdef CONFIG_NET_CLS_ACT
327 	return exts->nr_actions;
328 #else
329 	return false;
330 #endif
331 }
332 
333 /**
334  * tcf_exts_has_one_action - check if exactly one action is present
335  * @exts: tc filter extensions handle
336  *
337  * Returns true if exactly one action is present.
338  */
339 static inline bool tcf_exts_has_one_action(struct tcf_exts *exts)
340 {
341 #ifdef CONFIG_NET_CLS_ACT
342 	return exts->nr_actions == 1;
343 #else
344 	return false;
345 #endif
346 }
347 
348 /**
349  * tcf_exts_exec - execute tc filter extensions
350  * @skb: socket buffer
351  * @exts: tc filter extensions handle
352  * @res: desired result
353  *
354  * Executes all configured extensions. Returns TC_ACT_OK on a normal execution,
355  * a negative number if the filter must be considered unmatched or
356  * a positive action code (TC_ACT_*) which must be returned to the
357  * underlying layer.
358  */
359 static inline int
360 tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
361 	      struct tcf_result *res)
362 {
363 #ifdef CONFIG_NET_CLS_ACT
364 	return tcf_action_exec(skb, exts->actions, exts->nr_actions, res);
365 #endif
366 	return TC_ACT_OK;
367 }
368 
369 int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
370 		      struct nlattr **tb, struct nlattr *rate_tlv,
371 		      struct tcf_exts *exts, bool ovr);
372 void tcf_exts_destroy(struct tcf_exts *exts);
373 void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
374 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
375 int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
376 
377 /**
378  * struct tcf_pkt_info - packet information
379  */
380 struct tcf_pkt_info {
381 	unsigned char *		ptr;
382 	int			nexthdr;
383 };
384 
385 #ifdef CONFIG_NET_EMATCH
386 
387 struct tcf_ematch_ops;
388 
389 /**
390  * struct tcf_ematch - extended match (ematch)
391  *
392  * @matchid: identifier to allow userspace to reidentify a match
393  * @flags: flags specifying attributes and the relation to other matches
394  * @ops: the operations lookup table of the corresponding ematch module
395  * @datalen: length of the ematch specific configuration data
396  * @data: ematch specific data
397  */
398 struct tcf_ematch {
399 	struct tcf_ematch_ops * ops;
400 	unsigned long		data;
401 	unsigned int		datalen;
402 	u16			matchid;
403 	u16			flags;
404 	struct net		*net;
405 };
406 
407 static inline int tcf_em_is_container(struct tcf_ematch *em)
408 {
409 	return !em->ops;
410 }
411 
412 static inline int tcf_em_is_simple(struct tcf_ematch *em)
413 {
414 	return em->flags & TCF_EM_SIMPLE;
415 }
416 
417 static inline int tcf_em_is_inverted(struct tcf_ematch *em)
418 {
419 	return em->flags & TCF_EM_INVERT;
420 }
421 
422 static inline int tcf_em_last_match(struct tcf_ematch *em)
423 {
424 	return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END;
425 }
426 
427 static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
428 {
429 	if (tcf_em_last_match(em))
430 		return 1;
431 
432 	if (result == 0 && em->flags & TCF_EM_REL_AND)
433 		return 1;
434 
435 	if (result != 0 && em->flags & TCF_EM_REL_OR)
436 		return 1;
437 
438 	return 0;
439 }
440 
441 /**
442  * struct tcf_ematch_tree - ematch tree handle
443  *
444  * @hdr: ematch tree header supplied by userspace
445  * @matches: array of ematches
446  */
447 struct tcf_ematch_tree {
448 	struct tcf_ematch_tree_hdr hdr;
449 	struct tcf_ematch *	matches;
450 
451 };
452 
453 /**
454  * struct tcf_ematch_ops - ematch module operations
455  *
456  * @kind: identifier (kind) of this ematch module
457  * @datalen: length of expected configuration data (optional)
458  * @change: called during validation (optional)
459  * @match: called during ematch tree evaluation, must return 1/0
460  * @destroy: called during destroyage (optional)
461  * @dump: called during dumping process (optional)
462  * @owner: owner, must be set to THIS_MODULE
463  * @link: link to previous/next ematch module (internal use)
464  */
465 struct tcf_ematch_ops {
466 	int			kind;
467 	int			datalen;
468 	int			(*change)(struct net *net, void *,
469 					  int, struct tcf_ematch *);
470 	int			(*match)(struct sk_buff *, struct tcf_ematch *,
471 					 struct tcf_pkt_info *);
472 	void			(*destroy)(struct tcf_ematch *);
473 	int			(*dump)(struct sk_buff *, struct tcf_ematch *);
474 	struct module		*owner;
475 	struct list_head	link;
476 };
477 
478 int tcf_em_register(struct tcf_ematch_ops *);
479 void tcf_em_unregister(struct tcf_ematch_ops *);
480 int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
481 			 struct tcf_ematch_tree *);
482 void tcf_em_tree_destroy(struct tcf_ematch_tree *);
483 int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
484 int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
485 			struct tcf_pkt_info *);
486 
487 /**
488  * tcf_em_tree_match - evaulate an ematch tree
489  *
490  * @skb: socket buffer of the packet in question
491  * @tree: ematch tree to be used for evaluation
492  * @info: packet information examined by classifier
493  *
494  * This function matches @skb against the ematch tree in @tree by going
495  * through all ematches respecting their logic relations returning
496  * as soon as the result is obvious.
497  *
498  * Returns 1 if the ematch tree as-one matches, no ematches are configured
499  * or ematch is not enabled in the kernel, otherwise 0 is returned.
500  */
501 static inline int tcf_em_tree_match(struct sk_buff *skb,
502 				    struct tcf_ematch_tree *tree,
503 				    struct tcf_pkt_info *info)
504 {
505 	if (tree->hdr.nmatches)
506 		return __tcf_em_tree_match(skb, tree, info);
507 	else
508 		return 1;
509 }
510 
511 #define MODULE_ALIAS_TCF_EMATCH(kind)	MODULE_ALIAS("ematch-kind-" __stringify(kind))
512 
513 #else /* CONFIG_NET_EMATCH */
514 
515 struct tcf_ematch_tree {
516 };
517 
518 #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
519 #define tcf_em_tree_destroy(t) do { (void)(t); } while(0)
520 #define tcf_em_tree_dump(skb, t, tlv) (0)
521 #define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
522 
523 #endif /* CONFIG_NET_EMATCH */
524 
525 static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
526 {
527 	switch (layer) {
528 		case TCF_LAYER_LINK:
529 			return skb->data;
530 		case TCF_LAYER_NETWORK:
531 			return skb_network_header(skb);
532 		case TCF_LAYER_TRANSPORT:
533 			return skb_transport_header(skb);
534 	}
535 
536 	return NULL;
537 }
538 
539 static inline int tcf_valid_offset(const struct sk_buff *skb,
540 				   const unsigned char *ptr, const int len)
541 {
542 	return likely((ptr + len) <= skb_tail_pointer(skb) &&
543 		      ptr >= skb->head &&
544 		      (ptr <= (ptr + len)));
545 }
546 
547 #ifdef CONFIG_NET_CLS_IND
548 #include <net/net_namespace.h>
549 
550 static inline int
551 tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
552 {
553 	char indev[IFNAMSIZ];
554 	struct net_device *dev;
555 
556 	if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
557 		return -EINVAL;
558 	dev = __dev_get_by_name(net, indev);
559 	if (!dev)
560 		return -ENODEV;
561 	return dev->ifindex;
562 }
563 
564 static inline bool
565 tcf_match_indev(struct sk_buff *skb, int ifindex)
566 {
567 	if (!ifindex)
568 		return true;
569 	if  (!skb->skb_iif)
570 		return false;
571 	return ifindex == skb->skb_iif;
572 }
573 #endif /* CONFIG_NET_CLS_IND */
574 
575 int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
576 		     enum tc_setup_type type, void *type_data, bool err_stop);
577 
578 enum tc_block_command {
579 	TC_BLOCK_BIND,
580 	TC_BLOCK_UNBIND,
581 };
582 
583 struct tc_block_offload {
584 	enum tc_block_command command;
585 	enum tcf_block_binder_type binder_type;
586 	struct tcf_block *block;
587 };
588 
589 struct tc_cls_common_offload {
590 	u32 chain_index;
591 	__be16 protocol;
592 	u32 prio;
593 };
594 
595 static inline void
596 tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common,
597 			   const struct tcf_proto *tp)
598 {
599 	cls_common->chain_index = tp->chain->index;
600 	cls_common->protocol = tp->protocol;
601 	cls_common->prio = tp->prio;
602 }
603 
604 struct tc_cls_u32_knode {
605 	struct tcf_exts *exts;
606 	struct tc_u32_sel *sel;
607 	u32 handle;
608 	u32 val;
609 	u32 mask;
610 	u32 link_handle;
611 	u8 fshift;
612 };
613 
614 struct tc_cls_u32_hnode {
615 	u32 handle;
616 	u32 prio;
617 	unsigned int divisor;
618 };
619 
620 enum tc_clsu32_command {
621 	TC_CLSU32_NEW_KNODE,
622 	TC_CLSU32_REPLACE_KNODE,
623 	TC_CLSU32_DELETE_KNODE,
624 	TC_CLSU32_NEW_HNODE,
625 	TC_CLSU32_REPLACE_HNODE,
626 	TC_CLSU32_DELETE_HNODE,
627 };
628 
629 struct tc_cls_u32_offload {
630 	struct tc_cls_common_offload common;
631 	/* knode values */
632 	enum tc_clsu32_command command;
633 	union {
634 		struct tc_cls_u32_knode knode;
635 		struct tc_cls_u32_hnode hnode;
636 	};
637 };
638 
639 static inline bool tc_can_offload(const struct net_device *dev)
640 {
641 	return dev->features & NETIF_F_HW_TC;
642 }
643 
644 static inline bool tc_skip_hw(u32 flags)
645 {
646 	return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false;
647 }
648 
649 static inline bool tc_skip_sw(u32 flags)
650 {
651 	return (flags & TCA_CLS_FLAGS_SKIP_SW) ? true : false;
652 }
653 
654 /* SKIP_HW and SKIP_SW are mutually exclusive flags. */
655 static inline bool tc_flags_valid(u32 flags)
656 {
657 	if (flags & ~(TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW))
658 		return false;
659 
660 	if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW | TCA_CLS_FLAGS_SKIP_SW)))
661 		return false;
662 
663 	return true;
664 }
665 
666 static inline bool tc_in_hw(u32 flags)
667 {
668 	return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false;
669 }
670 
671 enum tc_fl_command {
672 	TC_CLSFLOWER_REPLACE,
673 	TC_CLSFLOWER_DESTROY,
674 	TC_CLSFLOWER_STATS,
675 };
676 
677 struct tc_cls_flower_offload {
678 	struct tc_cls_common_offload common;
679 	enum tc_fl_command command;
680 	unsigned long cookie;
681 	struct flow_dissector *dissector;
682 	struct fl_flow_key *mask;
683 	struct fl_flow_key *key;
684 	struct tcf_exts *exts;
685 	u32 classid;
686 };
687 
688 enum tc_matchall_command {
689 	TC_CLSMATCHALL_REPLACE,
690 	TC_CLSMATCHALL_DESTROY,
691 };
692 
693 struct tc_cls_matchall_offload {
694 	struct tc_cls_common_offload common;
695 	enum tc_matchall_command command;
696 	struct tcf_exts *exts;
697 	unsigned long cookie;
698 };
699 
700 enum tc_clsbpf_command {
701 	TC_CLSBPF_OFFLOAD,
702 	TC_CLSBPF_STATS,
703 };
704 
705 struct tc_cls_bpf_offload {
706 	struct tc_cls_common_offload common;
707 	enum tc_clsbpf_command command;
708 	struct tcf_exts *exts;
709 	struct bpf_prog *prog;
710 	struct bpf_prog *oldprog;
711 	const char *name;
712 	bool exts_integrated;
713 	u32 gen_flags;
714 };
715 
716 struct tc_mqprio_qopt_offload {
717 	/* struct tc_mqprio_qopt must always be the first element */
718 	struct tc_mqprio_qopt qopt;
719 	u16 mode;
720 	u16 shaper;
721 	u32 flags;
722 	u64 min_rate[TC_QOPT_MAX_QUEUE];
723 	u64 max_rate[TC_QOPT_MAX_QUEUE];
724 };
725 
726 /* This structure holds cookie structure that is passed from user
727  * to the kernel for actions and classifiers
728  */
729 struct tc_cookie {
730 	u8  *data;
731 	u32 len;
732 };
733 
734 enum tc_red_command {
735 	TC_RED_REPLACE,
736 	TC_RED_DESTROY,
737 	TC_RED_STATS,
738 	TC_RED_XSTATS,
739 };
740 
741 struct tc_red_qopt_offload_params {
742 	u32 min;
743 	u32 max;
744 	u32 probability;
745 	bool is_ecn;
746 };
747 struct tc_red_qopt_offload_stats {
748 	struct gnet_stats_basic_packed *bstats;
749 	struct gnet_stats_queue *qstats;
750 };
751 
752 struct tc_red_qopt_offload {
753 	enum tc_red_command command;
754 	u32 handle;
755 	u32 parent;
756 	union {
757 		struct tc_red_qopt_offload_params set;
758 		struct tc_red_qopt_offload_stats stats;
759 		struct red_stats *xstats;
760 	};
761 };
762 
763 #endif
764