18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __NET_SCHED_GENERIC_H
38c2ecf20Sopenharmony_ci#define __NET_SCHED_GENERIC_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
68c2ecf20Sopenharmony_ci#include <linux/types.h>
78c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
88c2ecf20Sopenharmony_ci#include <linux/pkt_sched.h>
98c2ecf20Sopenharmony_ci#include <linux/pkt_cls.h>
108c2ecf20Sopenharmony_ci#include <linux/percpu.h>
118c2ecf20Sopenharmony_ci#include <linux/dynamic_queue_limits.h>
128c2ecf20Sopenharmony_ci#include <linux/list.h>
138c2ecf20Sopenharmony_ci#include <linux/refcount.h>
148c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
158c2ecf20Sopenharmony_ci#include <linux/mutex.h>
168c2ecf20Sopenharmony_ci#include <linux/rwsem.h>
178c2ecf20Sopenharmony_ci#include <linux/atomic.h>
188c2ecf20Sopenharmony_ci#include <linux/hashtable.h>
198c2ecf20Sopenharmony_ci#include <net/gen_stats.h>
208c2ecf20Sopenharmony_ci#include <net/rtnetlink.h>
218c2ecf20Sopenharmony_ci#include <net/flow_offload.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistruct Qdisc_ops;
248c2ecf20Sopenharmony_cistruct qdisc_walker;
258c2ecf20Sopenharmony_cistruct tcf_walker;
268c2ecf20Sopenharmony_cistruct module;
278c2ecf20Sopenharmony_cistruct bpf_flow_keys;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistruct qdisc_rate_table {
308c2ecf20Sopenharmony_ci	struct tc_ratespec rate;
318c2ecf20Sopenharmony_ci	u32		data[256];
328c2ecf20Sopenharmony_ci	struct qdisc_rate_table *next;
338c2ecf20Sopenharmony_ci	int		refcnt;
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cienum qdisc_state_t {
378c2ecf20Sopenharmony_ci	__QDISC_STATE_SCHED,
388c2ecf20Sopenharmony_ci	__QDISC_STATE_DEACTIVATED,
398c2ecf20Sopenharmony_ci	__QDISC_STATE_MISSED,
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistruct qdisc_size_table {
438c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
448c2ecf20Sopenharmony_ci	struct list_head	list;
458c2ecf20Sopenharmony_ci	struct tc_sizespec	szopts;
468c2ecf20Sopenharmony_ci	int			refcnt;
478c2ecf20Sopenharmony_ci	u16			data[];
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/* similar to sk_buff_head, but skb->prev pointer is undefined. */
518c2ecf20Sopenharmony_cistruct qdisc_skb_head {
528c2ecf20Sopenharmony_ci	struct sk_buff	*head;
538c2ecf20Sopenharmony_ci	struct sk_buff	*tail;
548c2ecf20Sopenharmony_ci	__u32		qlen;
558c2ecf20Sopenharmony_ci	spinlock_t	lock;
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistruct Qdisc {
598c2ecf20Sopenharmony_ci	int 			(*enqueue)(struct sk_buff *skb,
608c2ecf20Sopenharmony_ci					   struct Qdisc *sch,
618c2ecf20Sopenharmony_ci					   struct sk_buff **to_free);
628c2ecf20Sopenharmony_ci	struct sk_buff *	(*dequeue)(struct Qdisc *sch);
638c2ecf20Sopenharmony_ci	unsigned int		flags;
648c2ecf20Sopenharmony_ci#define TCQ_F_BUILTIN		1
658c2ecf20Sopenharmony_ci#define TCQ_F_INGRESS		2
668c2ecf20Sopenharmony_ci#define TCQ_F_CAN_BYPASS	4
678c2ecf20Sopenharmony_ci#define TCQ_F_MQROOT		8
688c2ecf20Sopenharmony_ci#define TCQ_F_ONETXQUEUE	0x10 /* dequeue_skb() can assume all skbs are for
698c2ecf20Sopenharmony_ci				      * q->dev_queue : It can test
708c2ecf20Sopenharmony_ci				      * netif_xmit_frozen_or_stopped() before
718c2ecf20Sopenharmony_ci				      * dequeueing next packet.
728c2ecf20Sopenharmony_ci				      * Its true for MQ/MQPRIO slaves, or non
738c2ecf20Sopenharmony_ci				      * multiqueue device.
748c2ecf20Sopenharmony_ci				      */
758c2ecf20Sopenharmony_ci#define TCQ_F_WARN_NONWC	(1 << 16)
768c2ecf20Sopenharmony_ci#define TCQ_F_CPUSTATS		0x20 /* run using percpu statistics */
778c2ecf20Sopenharmony_ci#define TCQ_F_NOPARENT		0x40 /* root of its hierarchy :
788c2ecf20Sopenharmony_ci				      * qdisc_tree_decrease_qlen() should stop.
798c2ecf20Sopenharmony_ci				      */
808c2ecf20Sopenharmony_ci#define TCQ_F_INVISIBLE		0x80 /* invisible by default in dump */
818c2ecf20Sopenharmony_ci#define TCQ_F_NOLOCK		0x100 /* qdisc does not require locking */
828c2ecf20Sopenharmony_ci#define TCQ_F_OFFLOADED		0x200 /* qdisc is offloaded to HW */
838c2ecf20Sopenharmony_ci	u32			limit;
848c2ecf20Sopenharmony_ci	const struct Qdisc_ops	*ops;
858c2ecf20Sopenharmony_ci	struct qdisc_size_table	__rcu *stab;
868c2ecf20Sopenharmony_ci	struct hlist_node       hash;
878c2ecf20Sopenharmony_ci	u32			handle;
888c2ecf20Sopenharmony_ci	u32			parent;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	struct netdev_queue	*dev_queue;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	struct net_rate_estimator __rcu *rate_est;
938c2ecf20Sopenharmony_ci	struct gnet_stats_basic_cpu __percpu *cpu_bstats;
948c2ecf20Sopenharmony_ci	struct gnet_stats_queue	__percpu *cpu_qstats;
958c2ecf20Sopenharmony_ci	int			pad;
968c2ecf20Sopenharmony_ci	refcount_t		refcnt;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/*
998c2ecf20Sopenharmony_ci	 * For performance sake on SMP, we put highly modified fields at the end
1008c2ecf20Sopenharmony_ci	 */
1018c2ecf20Sopenharmony_ci	struct sk_buff_head	gso_skb ____cacheline_aligned_in_smp;
1028c2ecf20Sopenharmony_ci	struct qdisc_skb_head	q;
1038c2ecf20Sopenharmony_ci	struct gnet_stats_basic_packed bstats;
1048c2ecf20Sopenharmony_ci	seqcount_t		running;
1058c2ecf20Sopenharmony_ci	struct gnet_stats_queue	qstats;
1068c2ecf20Sopenharmony_ci	unsigned long		state;
1078c2ecf20Sopenharmony_ci	struct Qdisc            *next_sched;
1088c2ecf20Sopenharmony_ci	struct sk_buff_head	skb_bad_txq;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	spinlock_t		busylock ____cacheline_aligned_in_smp;
1118c2ecf20Sopenharmony_ci	spinlock_t		seqlock;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	/* for NOLOCK qdisc, true if there are no enqueued skbs */
1148c2ecf20Sopenharmony_ci	bool			empty;
1158c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/* private data */
1188c2ecf20Sopenharmony_ci	long privdata[] ____cacheline_aligned;
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic inline void qdisc_refcount_inc(struct Qdisc *qdisc)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	if (qdisc->flags & TCQ_F_BUILTIN)
1248c2ecf20Sopenharmony_ci		return;
1258c2ecf20Sopenharmony_ci	refcount_inc(&qdisc->refcnt);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/* Intended to be used by unlocked users, when concurrent qdisc release is
1298c2ecf20Sopenharmony_ci * possible.
1308c2ecf20Sopenharmony_ci */
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic inline struct Qdisc *qdisc_refcount_inc_nz(struct Qdisc *qdisc)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	if (qdisc->flags & TCQ_F_BUILTIN)
1358c2ecf20Sopenharmony_ci		return qdisc;
1368c2ecf20Sopenharmony_ci	if (refcount_inc_not_zero(&qdisc->refcnt))
1378c2ecf20Sopenharmony_ci		return qdisc;
1388c2ecf20Sopenharmony_ci	return NULL;
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic inline bool qdisc_is_running(struct Qdisc *qdisc)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	if (qdisc->flags & TCQ_F_NOLOCK)
1448c2ecf20Sopenharmony_ci		return spin_is_locked(&qdisc->seqlock);
1458c2ecf20Sopenharmony_ci	return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	return q->flags & TCQ_F_CPUSTATS;
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic inline bool qdisc_is_empty(const struct Qdisc *qdisc)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	if (qdisc_is_percpu_stats(qdisc))
1568c2ecf20Sopenharmony_ci		return READ_ONCE(qdisc->empty);
1578c2ecf20Sopenharmony_ci	return !READ_ONCE(qdisc->q.qlen);
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic inline bool qdisc_run_begin(struct Qdisc *qdisc)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	if (qdisc->flags & TCQ_F_NOLOCK) {
1638c2ecf20Sopenharmony_ci		if (spin_trylock(&qdisc->seqlock))
1648c2ecf20Sopenharmony_ci			goto nolock_empty;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci		/* No need to insist if the MISSED flag was already set.
1678c2ecf20Sopenharmony_ci		 * Note that test_and_set_bit() also gives us memory ordering
1688c2ecf20Sopenharmony_ci		 * guarantees wrt potential earlier enqueue() and below
1698c2ecf20Sopenharmony_ci		 * spin_trylock(), both of which are necessary to prevent races
1708c2ecf20Sopenharmony_ci		 */
1718c2ecf20Sopenharmony_ci		if (test_and_set_bit(__QDISC_STATE_MISSED, &qdisc->state))
1728c2ecf20Sopenharmony_ci			return false;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		/* Try to take the lock again to make sure that we will either
1758c2ecf20Sopenharmony_ci		 * grab it or the CPU that still has it will see MISSED set
1768c2ecf20Sopenharmony_ci		 * when testing it in qdisc_run_end()
1778c2ecf20Sopenharmony_ci		 */
1788c2ecf20Sopenharmony_ci		if (!spin_trylock(&qdisc->seqlock))
1798c2ecf20Sopenharmony_ci			return false;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cinolock_empty:
1828c2ecf20Sopenharmony_ci		WRITE_ONCE(qdisc->empty, false);
1838c2ecf20Sopenharmony_ci	} else if (qdisc_is_running(qdisc)) {
1848c2ecf20Sopenharmony_ci		return false;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci	/* Variant of write_seqcount_begin() telling lockdep a trylock
1878c2ecf20Sopenharmony_ci	 * was attempted.
1888c2ecf20Sopenharmony_ci	 */
1898c2ecf20Sopenharmony_ci	raw_write_seqcount_begin(&qdisc->running);
1908c2ecf20Sopenharmony_ci	seqcount_acquire(&qdisc->running.dep_map, 0, 1, _RET_IP_);
1918c2ecf20Sopenharmony_ci	return true;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic inline void qdisc_run_end(struct Qdisc *qdisc)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	write_seqcount_end(&qdisc->running);
1978c2ecf20Sopenharmony_ci	if (qdisc->flags & TCQ_F_NOLOCK) {
1988c2ecf20Sopenharmony_ci		spin_unlock(&qdisc->seqlock);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		/* spin_unlock() only has store-release semantic. The unlock
2018c2ecf20Sopenharmony_ci		 * and test_bit() ordering is a store-load ordering, so a full
2028c2ecf20Sopenharmony_ci		 * memory barrier is needed here.
2038c2ecf20Sopenharmony_ci		 */
2048c2ecf20Sopenharmony_ci		smp_mb();
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		if (unlikely(test_bit(__QDISC_STATE_MISSED,
2078c2ecf20Sopenharmony_ci				      &qdisc->state))) {
2088c2ecf20Sopenharmony_ci			clear_bit(__QDISC_STATE_MISSED, &qdisc->state);
2098c2ecf20Sopenharmony_ci			__netif_schedule(qdisc);
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic inline bool qdisc_may_bulk(const struct Qdisc *qdisc)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	return qdisc->flags & TCQ_F_ONETXQUEUE;
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic inline int qdisc_avail_bulklimit(const struct netdev_queue *txq)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci#ifdef CONFIG_BQL
2228c2ecf20Sopenharmony_ci	/* Non-BQL migrated drivers will return 0, too. */
2238c2ecf20Sopenharmony_ci	return dql_avail(&txq->dql);
2248c2ecf20Sopenharmony_ci#else
2258c2ecf20Sopenharmony_ci	return 0;
2268c2ecf20Sopenharmony_ci#endif
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistruct Qdisc_class_ops {
2308c2ecf20Sopenharmony_ci	unsigned int		flags;
2318c2ecf20Sopenharmony_ci	/* Child qdisc manipulation */
2328c2ecf20Sopenharmony_ci	struct netdev_queue *	(*select_queue)(struct Qdisc *, struct tcmsg *);
2338c2ecf20Sopenharmony_ci	int			(*graft)(struct Qdisc *, unsigned long cl,
2348c2ecf20Sopenharmony_ci					struct Qdisc *, struct Qdisc **,
2358c2ecf20Sopenharmony_ci					struct netlink_ext_ack *extack);
2368c2ecf20Sopenharmony_ci	struct Qdisc *		(*leaf)(struct Qdisc *, unsigned long cl);
2378c2ecf20Sopenharmony_ci	void			(*qlen_notify)(struct Qdisc *, unsigned long);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	/* Class manipulation routines */
2408c2ecf20Sopenharmony_ci	unsigned long		(*find)(struct Qdisc *, u32 classid);
2418c2ecf20Sopenharmony_ci	int			(*change)(struct Qdisc *, u32, u32,
2428c2ecf20Sopenharmony_ci					struct nlattr **, unsigned long *,
2438c2ecf20Sopenharmony_ci					struct netlink_ext_ack *);
2448c2ecf20Sopenharmony_ci	int			(*delete)(struct Qdisc *, unsigned long);
2458c2ecf20Sopenharmony_ci	void			(*walk)(struct Qdisc *, struct qdisc_walker * arg);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	/* Filter manipulation */
2488c2ecf20Sopenharmony_ci	struct tcf_block *	(*tcf_block)(struct Qdisc *sch,
2498c2ecf20Sopenharmony_ci					     unsigned long arg,
2508c2ecf20Sopenharmony_ci					     struct netlink_ext_ack *extack);
2518c2ecf20Sopenharmony_ci	unsigned long		(*bind_tcf)(struct Qdisc *, unsigned long,
2528c2ecf20Sopenharmony_ci					u32 classid);
2538c2ecf20Sopenharmony_ci	void			(*unbind_tcf)(struct Qdisc *, unsigned long);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	/* rtnetlink specific */
2568c2ecf20Sopenharmony_ci	int			(*dump)(struct Qdisc *, unsigned long,
2578c2ecf20Sopenharmony_ci					struct sk_buff *skb, struct tcmsg*);
2588c2ecf20Sopenharmony_ci	int			(*dump_stats)(struct Qdisc *, unsigned long,
2598c2ecf20Sopenharmony_ci					struct gnet_dump *);
2608c2ecf20Sopenharmony_ci};
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci/* Qdisc_class_ops flag values */
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci/* Implements API that doesn't require rtnl lock */
2658c2ecf20Sopenharmony_cienum qdisc_class_ops_flags {
2668c2ecf20Sopenharmony_ci	QDISC_CLASS_OPS_DOIT_UNLOCKED = 1,
2678c2ecf20Sopenharmony_ci};
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistruct Qdisc_ops {
2708c2ecf20Sopenharmony_ci	struct Qdisc_ops	*next;
2718c2ecf20Sopenharmony_ci	const struct Qdisc_class_ops	*cl_ops;
2728c2ecf20Sopenharmony_ci	char			id[IFNAMSIZ];
2738c2ecf20Sopenharmony_ci	int			priv_size;
2748c2ecf20Sopenharmony_ci	unsigned int		static_flags;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	int 			(*enqueue)(struct sk_buff *skb,
2778c2ecf20Sopenharmony_ci					   struct Qdisc *sch,
2788c2ecf20Sopenharmony_ci					   struct sk_buff **to_free);
2798c2ecf20Sopenharmony_ci	struct sk_buff *	(*dequeue)(struct Qdisc *);
2808c2ecf20Sopenharmony_ci	struct sk_buff *	(*peek)(struct Qdisc *);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	int			(*init)(struct Qdisc *sch, struct nlattr *arg,
2838c2ecf20Sopenharmony_ci					struct netlink_ext_ack *extack);
2848c2ecf20Sopenharmony_ci	void			(*reset)(struct Qdisc *);
2858c2ecf20Sopenharmony_ci	void			(*destroy)(struct Qdisc *);
2868c2ecf20Sopenharmony_ci	int			(*change)(struct Qdisc *sch,
2878c2ecf20Sopenharmony_ci					  struct nlattr *arg,
2888c2ecf20Sopenharmony_ci					  struct netlink_ext_ack *extack);
2898c2ecf20Sopenharmony_ci	void			(*attach)(struct Qdisc *sch);
2908c2ecf20Sopenharmony_ci	int			(*change_tx_queue_len)(struct Qdisc *, unsigned int);
2918c2ecf20Sopenharmony_ci	void			(*change_real_num_tx)(struct Qdisc *sch,
2928c2ecf20Sopenharmony_ci						      unsigned int new_real_tx);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	int			(*dump)(struct Qdisc *, struct sk_buff *);
2958c2ecf20Sopenharmony_ci	int			(*dump_stats)(struct Qdisc *, struct gnet_dump *);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	void			(*ingress_block_set)(struct Qdisc *sch,
2988c2ecf20Sopenharmony_ci						     u32 block_index);
2998c2ecf20Sopenharmony_ci	void			(*egress_block_set)(struct Qdisc *sch,
3008c2ecf20Sopenharmony_ci						    u32 block_index);
3018c2ecf20Sopenharmony_ci	u32			(*ingress_block_get)(struct Qdisc *sch);
3028c2ecf20Sopenharmony_ci	u32			(*egress_block_get)(struct Qdisc *sch);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	struct module		*owner;
3058c2ecf20Sopenharmony_ci};
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistruct tcf_result {
3098c2ecf20Sopenharmony_ci	union {
3108c2ecf20Sopenharmony_ci		struct {
3118c2ecf20Sopenharmony_ci			unsigned long	class;
3128c2ecf20Sopenharmony_ci			u32		classid;
3138c2ecf20Sopenharmony_ci		};
3148c2ecf20Sopenharmony_ci		const struct tcf_proto *goto_tp;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci		/* used in the skb_tc_reinsert function */
3178c2ecf20Sopenharmony_ci		struct {
3188c2ecf20Sopenharmony_ci			bool		ingress;
3198c2ecf20Sopenharmony_ci			struct gnet_stats_queue *qstats;
3208c2ecf20Sopenharmony_ci		};
3218c2ecf20Sopenharmony_ci	};
3228c2ecf20Sopenharmony_ci};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistruct tcf_chain;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistruct tcf_proto_ops {
3278c2ecf20Sopenharmony_ci	struct list_head	head;
3288c2ecf20Sopenharmony_ci	char			kind[IFNAMSIZ];
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	int			(*classify)(struct sk_buff *,
3318c2ecf20Sopenharmony_ci					    const struct tcf_proto *,
3328c2ecf20Sopenharmony_ci					    struct tcf_result *);
3338c2ecf20Sopenharmony_ci	int			(*init)(struct tcf_proto*);
3348c2ecf20Sopenharmony_ci	void			(*destroy)(struct tcf_proto *tp, bool rtnl_held,
3358c2ecf20Sopenharmony_ci					   struct netlink_ext_ack *extack);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	void*			(*get)(struct tcf_proto*, u32 handle);
3388c2ecf20Sopenharmony_ci	void			(*put)(struct tcf_proto *tp, void *f);
3398c2ecf20Sopenharmony_ci	int			(*change)(struct net *net, struct sk_buff *,
3408c2ecf20Sopenharmony_ci					struct tcf_proto*, unsigned long,
3418c2ecf20Sopenharmony_ci					u32 handle, struct nlattr **,
3428c2ecf20Sopenharmony_ci					void **, bool, bool,
3438c2ecf20Sopenharmony_ci					struct netlink_ext_ack *);
3448c2ecf20Sopenharmony_ci	int			(*delete)(struct tcf_proto *tp, void *arg,
3458c2ecf20Sopenharmony_ci					  bool *last, bool rtnl_held,
3468c2ecf20Sopenharmony_ci					  struct netlink_ext_ack *);
3478c2ecf20Sopenharmony_ci	bool			(*delete_empty)(struct tcf_proto *tp);
3488c2ecf20Sopenharmony_ci	void			(*walk)(struct tcf_proto *tp,
3498c2ecf20Sopenharmony_ci					struct tcf_walker *arg, bool rtnl_held);
3508c2ecf20Sopenharmony_ci	int			(*reoffload)(struct tcf_proto *tp, bool add,
3518c2ecf20Sopenharmony_ci					     flow_setup_cb_t *cb, void *cb_priv,
3528c2ecf20Sopenharmony_ci					     struct netlink_ext_ack *extack);
3538c2ecf20Sopenharmony_ci	void			(*hw_add)(struct tcf_proto *tp,
3548c2ecf20Sopenharmony_ci					  void *type_data);
3558c2ecf20Sopenharmony_ci	void			(*hw_del)(struct tcf_proto *tp,
3568c2ecf20Sopenharmony_ci					  void *type_data);
3578c2ecf20Sopenharmony_ci	void			(*bind_class)(void *, u32, unsigned long,
3588c2ecf20Sopenharmony_ci					      void *, unsigned long);
3598c2ecf20Sopenharmony_ci	void *			(*tmplt_create)(struct net *net,
3608c2ecf20Sopenharmony_ci						struct tcf_chain *chain,
3618c2ecf20Sopenharmony_ci						struct nlattr **tca,
3628c2ecf20Sopenharmony_ci						struct netlink_ext_ack *extack);
3638c2ecf20Sopenharmony_ci	void			(*tmplt_destroy)(void *tmplt_priv);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	/* rtnetlink specific */
3668c2ecf20Sopenharmony_ci	int			(*dump)(struct net*, struct tcf_proto*, void *,
3678c2ecf20Sopenharmony_ci					struct sk_buff *skb, struct tcmsg*,
3688c2ecf20Sopenharmony_ci					bool);
3698c2ecf20Sopenharmony_ci	int			(*terse_dump)(struct net *net,
3708c2ecf20Sopenharmony_ci					      struct tcf_proto *tp, void *fh,
3718c2ecf20Sopenharmony_ci					      struct sk_buff *skb,
3728c2ecf20Sopenharmony_ci					      struct tcmsg *t, bool rtnl_held);
3738c2ecf20Sopenharmony_ci	int			(*tmplt_dump)(struct sk_buff *skb,
3748c2ecf20Sopenharmony_ci					      struct net *net,
3758c2ecf20Sopenharmony_ci					      void *tmplt_priv);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	struct module		*owner;
3788c2ecf20Sopenharmony_ci	int			flags;
3798c2ecf20Sopenharmony_ci};
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci/* Classifiers setting TCF_PROTO_OPS_DOIT_UNLOCKED in tcf_proto_ops->flags
3828c2ecf20Sopenharmony_ci * are expected to implement tcf_proto_ops->delete_empty(), otherwise race
3838c2ecf20Sopenharmony_ci * conditions can occur when filters are inserted/deleted simultaneously.
3848c2ecf20Sopenharmony_ci */
3858c2ecf20Sopenharmony_cienum tcf_proto_ops_flags {
3868c2ecf20Sopenharmony_ci	TCF_PROTO_OPS_DOIT_UNLOCKED = 1,
3878c2ecf20Sopenharmony_ci};
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistruct tcf_proto {
3908c2ecf20Sopenharmony_ci	/* Fast access part */
3918c2ecf20Sopenharmony_ci	struct tcf_proto __rcu	*next;
3928c2ecf20Sopenharmony_ci	void __rcu		*root;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	/* called under RCU BH lock*/
3958c2ecf20Sopenharmony_ci	int			(*classify)(struct sk_buff *,
3968c2ecf20Sopenharmony_ci					    const struct tcf_proto *,
3978c2ecf20Sopenharmony_ci					    struct tcf_result *);
3988c2ecf20Sopenharmony_ci	__be16			protocol;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	/* All the rest */
4018c2ecf20Sopenharmony_ci	u32			prio;
4028c2ecf20Sopenharmony_ci	void			*data;
4038c2ecf20Sopenharmony_ci	const struct tcf_proto_ops	*ops;
4048c2ecf20Sopenharmony_ci	struct tcf_chain	*chain;
4058c2ecf20Sopenharmony_ci	/* Lock protects tcf_proto shared state and can be used by unlocked
4068c2ecf20Sopenharmony_ci	 * classifiers to protect their private data.
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	spinlock_t		lock;
4098c2ecf20Sopenharmony_ci	bool			deleting;
4108c2ecf20Sopenharmony_ci	refcount_t		refcnt;
4118c2ecf20Sopenharmony_ci	struct rcu_head		rcu;
4128c2ecf20Sopenharmony_ci	struct hlist_node	destroy_ht_node;
4138c2ecf20Sopenharmony_ci};
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistruct qdisc_skb_cb {
4168c2ecf20Sopenharmony_ci	struct {
4178c2ecf20Sopenharmony_ci		unsigned int		pkt_len;
4188c2ecf20Sopenharmony_ci		u16			slave_dev_queue_mapping;
4198c2ecf20Sopenharmony_ci		u16			tc_classid;
4208c2ecf20Sopenharmony_ci	};
4218c2ecf20Sopenharmony_ci#define QDISC_CB_PRIV_LEN 20
4228c2ecf20Sopenharmony_ci	unsigned char		data[QDISC_CB_PRIV_LEN];
4238c2ecf20Sopenharmony_ci	u16			mru;
4248c2ecf20Sopenharmony_ci};
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_citypedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_cistruct tcf_chain {
4298c2ecf20Sopenharmony_ci	/* Protects filter_chain. */
4308c2ecf20Sopenharmony_ci	struct mutex filter_chain_lock;
4318c2ecf20Sopenharmony_ci	struct tcf_proto __rcu *filter_chain;
4328c2ecf20Sopenharmony_ci	struct list_head list;
4338c2ecf20Sopenharmony_ci	struct tcf_block *block;
4348c2ecf20Sopenharmony_ci	u32 index; /* chain index */
4358c2ecf20Sopenharmony_ci	unsigned int refcnt;
4368c2ecf20Sopenharmony_ci	unsigned int action_refcnt;
4378c2ecf20Sopenharmony_ci	bool explicitly_created;
4388c2ecf20Sopenharmony_ci	bool flushing;
4398c2ecf20Sopenharmony_ci	const struct tcf_proto_ops *tmplt_ops;
4408c2ecf20Sopenharmony_ci	void *tmplt_priv;
4418c2ecf20Sopenharmony_ci	struct rcu_head rcu;
4428c2ecf20Sopenharmony_ci};
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistruct tcf_block {
4458c2ecf20Sopenharmony_ci	/* Lock protects tcf_block and lifetime-management data of chains
4468c2ecf20Sopenharmony_ci	 * attached to the block (refcnt, action_refcnt, explicitly_created).
4478c2ecf20Sopenharmony_ci	 */
4488c2ecf20Sopenharmony_ci	struct mutex lock;
4498c2ecf20Sopenharmony_ci	struct list_head chain_list;
4508c2ecf20Sopenharmony_ci	u32 index; /* block index for shared blocks */
4518c2ecf20Sopenharmony_ci	u32 classid; /* which class this block belongs to */
4528c2ecf20Sopenharmony_ci	refcount_t refcnt;
4538c2ecf20Sopenharmony_ci	struct net *net;
4548c2ecf20Sopenharmony_ci	struct Qdisc *q;
4558c2ecf20Sopenharmony_ci	struct rw_semaphore cb_lock; /* protects cb_list and offload counters */
4568c2ecf20Sopenharmony_ci	struct flow_block flow_block;
4578c2ecf20Sopenharmony_ci	struct list_head owner_list;
4588c2ecf20Sopenharmony_ci	bool keep_dst;
4598c2ecf20Sopenharmony_ci	atomic_t offloadcnt; /* Number of oddloaded filters */
4608c2ecf20Sopenharmony_ci	unsigned int nooffloaddevcnt; /* Number of devs unable to do offload */
4618c2ecf20Sopenharmony_ci	unsigned int lockeddevcnt; /* Number of devs that require rtnl lock. */
4628c2ecf20Sopenharmony_ci	struct {
4638c2ecf20Sopenharmony_ci		struct tcf_chain *chain;
4648c2ecf20Sopenharmony_ci		struct list_head filter_chain_list;
4658c2ecf20Sopenharmony_ci	} chain0;
4668c2ecf20Sopenharmony_ci	struct rcu_head rcu;
4678c2ecf20Sopenharmony_ci	DECLARE_HASHTABLE(proto_destroy_ht, 7);
4688c2ecf20Sopenharmony_ci	struct mutex proto_destroy_lock; /* Lock for proto_destroy hashtable. */
4698c2ecf20Sopenharmony_ci};
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci#ifdef CONFIG_PROVE_LOCKING
4728c2ecf20Sopenharmony_cistatic inline bool lockdep_tcf_chain_is_locked(struct tcf_chain *chain)
4738c2ecf20Sopenharmony_ci{
4748c2ecf20Sopenharmony_ci	return lockdep_is_held(&chain->filter_chain_lock);
4758c2ecf20Sopenharmony_ci}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_cistatic inline bool lockdep_tcf_proto_is_locked(struct tcf_proto *tp)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	return lockdep_is_held(&tp->lock);
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci#else
4828c2ecf20Sopenharmony_cistatic inline bool lockdep_tcf_chain_is_locked(struct tcf_block *chain)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	return true;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic inline bool lockdep_tcf_proto_is_locked(struct tcf_proto *tp)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	return true;
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci#endif /* #ifdef CONFIG_PROVE_LOCKING */
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci#define tcf_chain_dereference(p, chain)					\
4948c2ecf20Sopenharmony_ci	rcu_dereference_protected(p, lockdep_tcf_chain_is_locked(chain))
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci#define tcf_proto_dereference(p, tp)					\
4978c2ecf20Sopenharmony_ci	rcu_dereference_protected(p, lockdep_tcf_proto_is_locked(tp))
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	struct qdisc_skb_cb *qcb;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*qcb));
5048c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(qcb->data) < sz);
5058c2ecf20Sopenharmony_ci}
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_cistatic inline int qdisc_qlen_cpu(const struct Qdisc *q)
5088c2ecf20Sopenharmony_ci{
5098c2ecf20Sopenharmony_ci	return this_cpu_ptr(q->cpu_qstats)->qlen;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic inline int qdisc_qlen(const struct Qdisc *q)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	return q->q.qlen;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic inline int qdisc_qlen_sum(const struct Qdisc *q)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	__u32 qlen = q->qstats.qlen;
5208c2ecf20Sopenharmony_ci	int i;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	if (qdisc_is_percpu_stats(q)) {
5238c2ecf20Sopenharmony_ci		for_each_possible_cpu(i)
5248c2ecf20Sopenharmony_ci			qlen += per_cpu_ptr(q->cpu_qstats, i)->qlen;
5258c2ecf20Sopenharmony_ci	} else {
5268c2ecf20Sopenharmony_ci		qlen += q->q.qlen;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	return qlen;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_cistatic inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	return (struct qdisc_skb_cb *)skb->cb;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_cistatic inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	return &qdisc->q.lock;
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	struct Qdisc *q = rcu_dereference_rtnl(qdisc->dev_queue->qdisc);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	return q;
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_cistatic inline struct Qdisc *qdisc_root_bh(const struct Qdisc *qdisc)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	return rcu_dereference_bh(qdisc->dev_queue->qdisc);
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
5558c2ecf20Sopenharmony_ci{
5568c2ecf20Sopenharmony_ci	return qdisc->dev_queue->qdisc_sleeping;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci/* The qdisc root lock is a mechanism by which to top level
5608c2ecf20Sopenharmony_ci * of a qdisc tree can be locked from any qdisc node in the
5618c2ecf20Sopenharmony_ci * forest.  This allows changing the configuration of some
5628c2ecf20Sopenharmony_ci * aspect of the qdisc tree while blocking out asynchronous
5638c2ecf20Sopenharmony_ci * qdisc access in the packet processing paths.
5648c2ecf20Sopenharmony_ci *
5658c2ecf20Sopenharmony_ci * It is only legal to do this when the root will not change
5668c2ecf20Sopenharmony_ci * on us.  Otherwise we'll potentially lock the wrong qdisc
5678c2ecf20Sopenharmony_ci * root.  This is enforced by holding the RTNL semaphore, which
5688c2ecf20Sopenharmony_ci * all users of this lock accessor must do.
5698c2ecf20Sopenharmony_ci */
5708c2ecf20Sopenharmony_cistatic inline spinlock_t *qdisc_root_lock(const struct Qdisc *qdisc)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	struct Qdisc *root = qdisc_root(qdisc);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	ASSERT_RTNL();
5758c2ecf20Sopenharmony_ci	return qdisc_lock(root);
5768c2ecf20Sopenharmony_ci}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_cistatic inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	struct Qdisc *root = qdisc_root_sleeping(qdisc);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	ASSERT_RTNL();
5838c2ecf20Sopenharmony_ci	return qdisc_lock(root);
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc)
5878c2ecf20Sopenharmony_ci{
5888c2ecf20Sopenharmony_ci	struct Qdisc *root = qdisc_root_sleeping(qdisc);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	ASSERT_RTNL();
5918c2ecf20Sopenharmony_ci	return &root->running;
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	return qdisc->dev_queue->dev;
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cistatic inline void sch_tree_lock(const struct Qdisc *q)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	spin_lock_bh(qdisc_root_sleeping_lock(q));
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_cistatic inline void sch_tree_unlock(const struct Qdisc *q)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	spin_unlock_bh(qdisc_root_sleeping_lock(q));
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ciextern struct Qdisc noop_qdisc;
6108c2ecf20Sopenharmony_ciextern struct Qdisc_ops noop_qdisc_ops;
6118c2ecf20Sopenharmony_ciextern struct Qdisc_ops pfifo_fast_ops;
6128c2ecf20Sopenharmony_ciextern struct Qdisc_ops mq_qdisc_ops;
6138c2ecf20Sopenharmony_ciextern struct Qdisc_ops noqueue_qdisc_ops;
6148c2ecf20Sopenharmony_ciextern const struct Qdisc_ops *default_qdisc_ops;
6158c2ecf20Sopenharmony_cistatic inline const struct Qdisc_ops *
6168c2ecf20Sopenharmony_ciget_default_qdisc_ops(const struct net_device *dev, int ntx)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	return ntx < dev->real_num_tx_queues ?
6198c2ecf20Sopenharmony_ci			default_qdisc_ops : &pfifo_fast_ops;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistruct Qdisc_class_common {
6238c2ecf20Sopenharmony_ci	u32			classid;
6248c2ecf20Sopenharmony_ci	struct hlist_node	hnode;
6258c2ecf20Sopenharmony_ci};
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistruct Qdisc_class_hash {
6288c2ecf20Sopenharmony_ci	struct hlist_head	*hash;
6298c2ecf20Sopenharmony_ci	unsigned int		hashsize;
6308c2ecf20Sopenharmony_ci	unsigned int		hashmask;
6318c2ecf20Sopenharmony_ci	unsigned int		hashelems;
6328c2ecf20Sopenharmony_ci};
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cistatic inline unsigned int qdisc_class_hash(u32 id, u32 mask)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	id ^= id >> 8;
6378c2ecf20Sopenharmony_ci	id ^= id >> 4;
6388c2ecf20Sopenharmony_ci	return id & mask;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic inline struct Qdisc_class_common *
6428c2ecf20Sopenharmony_ciqdisc_class_find(const struct Qdisc_class_hash *hash, u32 id)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	struct Qdisc_class_common *cl;
6458c2ecf20Sopenharmony_ci	unsigned int h;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (!id)
6488c2ecf20Sopenharmony_ci		return NULL;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	h = qdisc_class_hash(id, hash->hashmask);
6518c2ecf20Sopenharmony_ci	hlist_for_each_entry(cl, &hash->hash[h], hnode) {
6528c2ecf20Sopenharmony_ci		if (cl->classid == id)
6538c2ecf20Sopenharmony_ci			return cl;
6548c2ecf20Sopenharmony_ci	}
6558c2ecf20Sopenharmony_ci	return NULL;
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic inline int tc_classid_to_hwtc(struct net_device *dev, u32 classid)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	u32 hwtc = TC_H_MIN(classid) - TC_H_MIN_PRIORITY;
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	return (hwtc < netdev_get_num_tc(dev)) ? hwtc : -EINVAL;
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ciint qdisc_class_hash_init(struct Qdisc_class_hash *);
6668c2ecf20Sopenharmony_civoid qdisc_class_hash_insert(struct Qdisc_class_hash *,
6678c2ecf20Sopenharmony_ci			     struct Qdisc_class_common *);
6688c2ecf20Sopenharmony_civoid qdisc_class_hash_remove(struct Qdisc_class_hash *,
6698c2ecf20Sopenharmony_ci			     struct Qdisc_class_common *);
6708c2ecf20Sopenharmony_civoid qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *);
6718c2ecf20Sopenharmony_civoid qdisc_class_hash_destroy(struct Qdisc_class_hash *);
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ciint dev_qdisc_change_tx_queue_len(struct net_device *dev);
6748c2ecf20Sopenharmony_civoid dev_qdisc_change_real_num_tx(struct net_device *dev,
6758c2ecf20Sopenharmony_ci				  unsigned int new_real_tx);
6768c2ecf20Sopenharmony_civoid dev_init_scheduler(struct net_device *dev);
6778c2ecf20Sopenharmony_civoid dev_shutdown(struct net_device *dev);
6788c2ecf20Sopenharmony_civoid dev_activate(struct net_device *dev);
6798c2ecf20Sopenharmony_civoid dev_deactivate(struct net_device *dev);
6808c2ecf20Sopenharmony_civoid dev_deactivate_many(struct list_head *head);
6818c2ecf20Sopenharmony_cistruct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
6828c2ecf20Sopenharmony_ci			      struct Qdisc *qdisc);
6838c2ecf20Sopenharmony_civoid qdisc_reset(struct Qdisc *qdisc);
6848c2ecf20Sopenharmony_civoid qdisc_put(struct Qdisc *qdisc);
6858c2ecf20Sopenharmony_civoid qdisc_put_unlocked(struct Qdisc *qdisc);
6868c2ecf20Sopenharmony_civoid qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len);
6878c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_SCHED
6888c2ecf20Sopenharmony_ciint qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type,
6898c2ecf20Sopenharmony_ci			      void *type_data);
6908c2ecf20Sopenharmony_civoid qdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch,
6918c2ecf20Sopenharmony_ci				struct Qdisc *new, struct Qdisc *old,
6928c2ecf20Sopenharmony_ci				enum tc_setup_type type, void *type_data,
6938c2ecf20Sopenharmony_ci				struct netlink_ext_ack *extack);
6948c2ecf20Sopenharmony_ci#else
6958c2ecf20Sopenharmony_cistatic inline int
6968c2ecf20Sopenharmony_ciqdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type,
6978c2ecf20Sopenharmony_ci			  void *type_data)
6988c2ecf20Sopenharmony_ci{
6998c2ecf20Sopenharmony_ci	q->flags &= ~TCQ_F_OFFLOADED;
7008c2ecf20Sopenharmony_ci	return 0;
7018c2ecf20Sopenharmony_ci}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cistatic inline void
7048c2ecf20Sopenharmony_ciqdisc_offload_graft_helper(struct net_device *dev, struct Qdisc *sch,
7058c2ecf20Sopenharmony_ci			   struct Qdisc *new, struct Qdisc *old,
7068c2ecf20Sopenharmony_ci			   enum tc_setup_type type, void *type_data,
7078c2ecf20Sopenharmony_ci			   struct netlink_ext_ack *extack)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci}
7108c2ecf20Sopenharmony_ci#endif
7118c2ecf20Sopenharmony_cistruct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
7128c2ecf20Sopenharmony_ci			  const struct Qdisc_ops *ops,
7138c2ecf20Sopenharmony_ci			  struct netlink_ext_ack *extack);
7148c2ecf20Sopenharmony_civoid qdisc_free(struct Qdisc *qdisc);
7158c2ecf20Sopenharmony_cistruct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
7168c2ecf20Sopenharmony_ci				const struct Qdisc_ops *ops, u32 parentid,
7178c2ecf20Sopenharmony_ci				struct netlink_ext_ack *extack);
7188c2ecf20Sopenharmony_civoid __qdisc_calculate_pkt_len(struct sk_buff *skb,
7198c2ecf20Sopenharmony_ci			       const struct qdisc_size_table *stab);
7208c2ecf20Sopenharmony_ciint skb_do_redirect(struct sk_buff *);
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic inline bool skb_at_tc_ingress(const struct sk_buff *skb)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
7258c2ecf20Sopenharmony_ci	return skb->tc_at_ingress;
7268c2ecf20Sopenharmony_ci#else
7278c2ecf20Sopenharmony_ci	return false;
7288c2ecf20Sopenharmony_ci#endif
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_cistatic inline bool skb_skip_tc_classify(struct sk_buff *skb)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
7348c2ecf20Sopenharmony_ci	if (skb->tc_skip_classify) {
7358c2ecf20Sopenharmony_ci		skb->tc_skip_classify = 0;
7368c2ecf20Sopenharmony_ci		return true;
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci#endif
7398c2ecf20Sopenharmony_ci	return false;
7408c2ecf20Sopenharmony_ci}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci/* Reset all TX qdiscs greater than index of a device.  */
7438c2ecf20Sopenharmony_cistatic inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
7448c2ecf20Sopenharmony_ci{
7458c2ecf20Sopenharmony_ci	struct Qdisc *qdisc;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	for (; i < dev->num_tx_queues; i++) {
7488c2ecf20Sopenharmony_ci		qdisc = rtnl_dereference(netdev_get_tx_queue(dev, i)->qdisc);
7498c2ecf20Sopenharmony_ci		if (qdisc) {
7508c2ecf20Sopenharmony_ci			spin_lock_bh(qdisc_lock(qdisc));
7518c2ecf20Sopenharmony_ci			qdisc_reset(qdisc);
7528c2ecf20Sopenharmony_ci			spin_unlock_bh(qdisc_lock(qdisc));
7538c2ecf20Sopenharmony_ci		}
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci/* Are all TX queues of the device empty?  */
7588c2ecf20Sopenharmony_cistatic inline bool qdisc_all_tx_empty(const struct net_device *dev)
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	unsigned int i;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	rcu_read_lock();
7638c2ecf20Sopenharmony_ci	for (i = 0; i < dev->num_tx_queues; i++) {
7648c2ecf20Sopenharmony_ci		struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
7658c2ecf20Sopenharmony_ci		const struct Qdisc *q = rcu_dereference(txq->qdisc);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci		if (!qdisc_is_empty(q)) {
7688c2ecf20Sopenharmony_ci			rcu_read_unlock();
7698c2ecf20Sopenharmony_ci			return false;
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci	rcu_read_unlock();
7738c2ecf20Sopenharmony_ci	return true;
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci/* Are any of the TX qdiscs changing?  */
7778c2ecf20Sopenharmony_cistatic inline bool qdisc_tx_changing(const struct net_device *dev)
7788c2ecf20Sopenharmony_ci{
7798c2ecf20Sopenharmony_ci	unsigned int i;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	for (i = 0; i < dev->num_tx_queues; i++) {
7828c2ecf20Sopenharmony_ci		struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
7838c2ecf20Sopenharmony_ci		if (rcu_access_pointer(txq->qdisc) != txq->qdisc_sleeping)
7848c2ecf20Sopenharmony_ci			return true;
7858c2ecf20Sopenharmony_ci	}
7868c2ecf20Sopenharmony_ci	return false;
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci/* Is the device using the noop qdisc on all queues?  */
7908c2ecf20Sopenharmony_cistatic inline bool qdisc_tx_is_noop(const struct net_device *dev)
7918c2ecf20Sopenharmony_ci{
7928c2ecf20Sopenharmony_ci	unsigned int i;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	for (i = 0; i < dev->num_tx_queues; i++) {
7958c2ecf20Sopenharmony_ci		struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
7968c2ecf20Sopenharmony_ci		if (rcu_access_pointer(txq->qdisc) != &noop_qdisc)
7978c2ecf20Sopenharmony_ci			return false;
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci	return true;
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic inline unsigned int qdisc_pkt_len(const struct sk_buff *skb)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	return qdisc_skb_cb(skb)->pkt_len;
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci/* additional qdisc xmit flags (NET_XMIT_MASK in linux/netdevice.h) */
8088c2ecf20Sopenharmony_cienum net_xmit_qdisc_t {
8098c2ecf20Sopenharmony_ci	__NET_XMIT_STOLEN = 0x00010000,
8108c2ecf20Sopenharmony_ci	__NET_XMIT_BYPASS = 0x00020000,
8118c2ecf20Sopenharmony_ci};
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
8148c2ecf20Sopenharmony_ci#define net_xmit_drop_count(e)	((e) & __NET_XMIT_STOLEN ? 0 : 1)
8158c2ecf20Sopenharmony_ci#else
8168c2ecf20Sopenharmony_ci#define net_xmit_drop_count(e)	(1)
8178c2ecf20Sopenharmony_ci#endif
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_cistatic inline void qdisc_calculate_pkt_len(struct sk_buff *skb,
8208c2ecf20Sopenharmony_ci					   const struct Qdisc *sch)
8218c2ecf20Sopenharmony_ci{
8228c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_SCHED
8238c2ecf20Sopenharmony_ci	struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	if (stab)
8268c2ecf20Sopenharmony_ci		__qdisc_calculate_pkt_len(skb, stab);
8278c2ecf20Sopenharmony_ci#endif
8288c2ecf20Sopenharmony_ci}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cistatic inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
8318c2ecf20Sopenharmony_ci				struct sk_buff **to_free)
8328c2ecf20Sopenharmony_ci{
8338c2ecf20Sopenharmony_ci	qdisc_calculate_pkt_len(skb, sch);
8348c2ecf20Sopenharmony_ci	return sch->enqueue(skb, sch, to_free);
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_cistatic inline void _bstats_update(struct gnet_stats_basic_packed *bstats,
8388c2ecf20Sopenharmony_ci				  __u64 bytes, __u32 packets)
8398c2ecf20Sopenharmony_ci{
8408c2ecf20Sopenharmony_ci	bstats->bytes += bytes;
8418c2ecf20Sopenharmony_ci	bstats->packets += packets;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic inline void bstats_update(struct gnet_stats_basic_packed *bstats,
8458c2ecf20Sopenharmony_ci				 const struct sk_buff *skb)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	_bstats_update(bstats,
8488c2ecf20Sopenharmony_ci		       qdisc_pkt_len(skb),
8498c2ecf20Sopenharmony_ci		       skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1);
8508c2ecf20Sopenharmony_ci}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_cistatic inline void _bstats_cpu_update(struct gnet_stats_basic_cpu *bstats,
8538c2ecf20Sopenharmony_ci				      __u64 bytes, __u32 packets)
8548c2ecf20Sopenharmony_ci{
8558c2ecf20Sopenharmony_ci	u64_stats_update_begin(&bstats->syncp);
8568c2ecf20Sopenharmony_ci	_bstats_update(&bstats->bstats, bytes, packets);
8578c2ecf20Sopenharmony_ci	u64_stats_update_end(&bstats->syncp);
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic inline void bstats_cpu_update(struct gnet_stats_basic_cpu *bstats,
8618c2ecf20Sopenharmony_ci				     const struct sk_buff *skb)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	u64_stats_update_begin(&bstats->syncp);
8648c2ecf20Sopenharmony_ci	bstats_update(&bstats->bstats, skb);
8658c2ecf20Sopenharmony_ci	u64_stats_update_end(&bstats->syncp);
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_cistatic inline void qdisc_bstats_cpu_update(struct Qdisc *sch,
8698c2ecf20Sopenharmony_ci					   const struct sk_buff *skb)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	bstats_cpu_update(this_cpu_ptr(sch->cpu_bstats), skb);
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_cistatic inline void qdisc_bstats_update(struct Qdisc *sch,
8758c2ecf20Sopenharmony_ci				       const struct sk_buff *skb)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	bstats_update(&sch->bstats, skb);
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_backlog_dec(struct Qdisc *sch,
8818c2ecf20Sopenharmony_ci					    const struct sk_buff *skb)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	sch->qstats.backlog -= qdisc_pkt_len(skb);
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_backlog_dec(struct Qdisc *sch,
8878c2ecf20Sopenharmony_ci						const struct sk_buff *skb)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	this_cpu_sub(sch->cpu_qstats->backlog, qdisc_pkt_len(skb));
8908c2ecf20Sopenharmony_ci}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_backlog_inc(struct Qdisc *sch,
8938c2ecf20Sopenharmony_ci					    const struct sk_buff *skb)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	sch->qstats.backlog += qdisc_pkt_len(skb);
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_backlog_inc(struct Qdisc *sch,
8998c2ecf20Sopenharmony_ci						const struct sk_buff *skb)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	this_cpu_add(sch->cpu_qstats->backlog, qdisc_pkt_len(skb));
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_qlen_inc(struct Qdisc *sch)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	this_cpu_inc(sch->cpu_qstats->qlen);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_qlen_dec(struct Qdisc *sch)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	this_cpu_dec(sch->cpu_qstats->qlen);
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_requeues_inc(struct Qdisc *sch)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	this_cpu_inc(sch->cpu_qstats->requeues);
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_cistatic inline void __qdisc_qstats_drop(struct Qdisc *sch, int count)
9208c2ecf20Sopenharmony_ci{
9218c2ecf20Sopenharmony_ci	sch->qstats.drops += count;
9228c2ecf20Sopenharmony_ci}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_cistatic inline void qstats_drop_inc(struct gnet_stats_queue *qstats)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	qstats->drops++;
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic inline void qstats_overlimit_inc(struct gnet_stats_queue *qstats)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	qstats->overlimits++;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_drop(struct Qdisc *sch)
9358c2ecf20Sopenharmony_ci{
9368c2ecf20Sopenharmony_ci	qstats_drop_inc(&sch->qstats);
9378c2ecf20Sopenharmony_ci}
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_cpu_drop(struct Qdisc *sch)
9408c2ecf20Sopenharmony_ci{
9418c2ecf20Sopenharmony_ci	this_cpu_inc(sch->cpu_qstats->drops);
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_overlimit(struct Qdisc *sch)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	sch->qstats.overlimits++;
9478c2ecf20Sopenharmony_ci}
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cistatic inline int qdisc_qstats_copy(struct gnet_dump *d, struct Qdisc *sch)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	__u32 qlen = qdisc_qlen_sum(sch);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	return gnet_stats_copy_queue(d, sch->cpu_qstats, &sch->qstats, qlen);
9548c2ecf20Sopenharmony_ci}
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_cistatic inline void qdisc_qstats_qlen_backlog(struct Qdisc *sch,  __u32 *qlen,
9578c2ecf20Sopenharmony_ci					     __u32 *backlog)
9588c2ecf20Sopenharmony_ci{
9598c2ecf20Sopenharmony_ci	struct gnet_stats_queue qstats = { 0 };
9608c2ecf20Sopenharmony_ci	__u32 len = qdisc_qlen_sum(sch);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	__gnet_stats_copy_queue(&qstats, sch->cpu_qstats, &sch->qstats, len);
9638c2ecf20Sopenharmony_ci	*qlen = qstats.qlen;
9648c2ecf20Sopenharmony_ci	*backlog = qstats.backlog;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cistatic inline void qdisc_tree_flush_backlog(struct Qdisc *sch)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	__u32 qlen, backlog;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	qdisc_qstats_qlen_backlog(sch, &qlen, &backlog);
9728c2ecf20Sopenharmony_ci	qdisc_tree_reduce_backlog(sch, qlen, backlog);
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic inline void qdisc_purge_queue(struct Qdisc *sch)
9768c2ecf20Sopenharmony_ci{
9778c2ecf20Sopenharmony_ci	__u32 qlen, backlog;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	qdisc_qstats_qlen_backlog(sch, &qlen, &backlog);
9808c2ecf20Sopenharmony_ci	qdisc_reset(sch);
9818c2ecf20Sopenharmony_ci	qdisc_tree_reduce_backlog(sch, qlen, backlog);
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic inline void qdisc_skb_head_init(struct qdisc_skb_head *qh)
9858c2ecf20Sopenharmony_ci{
9868c2ecf20Sopenharmony_ci	qh->head = NULL;
9878c2ecf20Sopenharmony_ci	qh->tail = NULL;
9888c2ecf20Sopenharmony_ci	qh->qlen = 0;
9898c2ecf20Sopenharmony_ci}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_cistatic inline void __qdisc_enqueue_tail(struct sk_buff *skb,
9928c2ecf20Sopenharmony_ci					struct qdisc_skb_head *qh)
9938c2ecf20Sopenharmony_ci{
9948c2ecf20Sopenharmony_ci	struct sk_buff *last = qh->tail;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	if (last) {
9978c2ecf20Sopenharmony_ci		skb->next = NULL;
9988c2ecf20Sopenharmony_ci		last->next = skb;
9998c2ecf20Sopenharmony_ci		qh->tail = skb;
10008c2ecf20Sopenharmony_ci	} else {
10018c2ecf20Sopenharmony_ci		qh->tail = skb;
10028c2ecf20Sopenharmony_ci		qh->head = skb;
10038c2ecf20Sopenharmony_ci	}
10048c2ecf20Sopenharmony_ci	qh->qlen++;
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_cistatic inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	__qdisc_enqueue_tail(skb, &sch->q);
10108c2ecf20Sopenharmony_ci	qdisc_qstats_backlog_inc(sch, skb);
10118c2ecf20Sopenharmony_ci	return NET_XMIT_SUCCESS;
10128c2ecf20Sopenharmony_ci}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_cistatic inline void __qdisc_enqueue_head(struct sk_buff *skb,
10158c2ecf20Sopenharmony_ci					struct qdisc_skb_head *qh)
10168c2ecf20Sopenharmony_ci{
10178c2ecf20Sopenharmony_ci	skb->next = qh->head;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	if (!qh->head)
10208c2ecf20Sopenharmony_ci		qh->tail = skb;
10218c2ecf20Sopenharmony_ci	qh->head = skb;
10228c2ecf20Sopenharmony_ci	qh->qlen++;
10238c2ecf20Sopenharmony_ci}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_cistatic inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh)
10268c2ecf20Sopenharmony_ci{
10278c2ecf20Sopenharmony_ci	struct sk_buff *skb = qh->head;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	if (likely(skb != NULL)) {
10308c2ecf20Sopenharmony_ci		qh->head = skb->next;
10318c2ecf20Sopenharmony_ci		qh->qlen--;
10328c2ecf20Sopenharmony_ci		if (qh->head == NULL)
10338c2ecf20Sopenharmony_ci			qh->tail = NULL;
10348c2ecf20Sopenharmony_ci		skb->next = NULL;
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	return skb;
10388c2ecf20Sopenharmony_ci}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_cistatic inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
10418c2ecf20Sopenharmony_ci{
10428c2ecf20Sopenharmony_ci	struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (likely(skb != NULL)) {
10458c2ecf20Sopenharmony_ci		qdisc_qstats_backlog_dec(sch, skb);
10468c2ecf20Sopenharmony_ci		qdisc_bstats_update(sch, skb);
10478c2ecf20Sopenharmony_ci	}
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	return skb;
10508c2ecf20Sopenharmony_ci}
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci/* Instead of calling kfree_skb() while root qdisc lock is held,
10538c2ecf20Sopenharmony_ci * queue the skb for future freeing at end of __dev_xmit_skb()
10548c2ecf20Sopenharmony_ci */
10558c2ecf20Sopenharmony_cistatic inline void __qdisc_drop(struct sk_buff *skb, struct sk_buff **to_free)
10568c2ecf20Sopenharmony_ci{
10578c2ecf20Sopenharmony_ci	skb->next = *to_free;
10588c2ecf20Sopenharmony_ci	*to_free = skb;
10598c2ecf20Sopenharmony_ci}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic inline void __qdisc_drop_all(struct sk_buff *skb,
10628c2ecf20Sopenharmony_ci				    struct sk_buff **to_free)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	if (skb->prev)
10658c2ecf20Sopenharmony_ci		skb->prev->next = *to_free;
10668c2ecf20Sopenharmony_ci	else
10678c2ecf20Sopenharmony_ci		skb->next = *to_free;
10688c2ecf20Sopenharmony_ci	*to_free = skb;
10698c2ecf20Sopenharmony_ci}
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_cistatic inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch,
10728c2ecf20Sopenharmony_ci						   struct qdisc_skb_head *qh,
10738c2ecf20Sopenharmony_ci						   struct sk_buff **to_free)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	struct sk_buff *skb = __qdisc_dequeue_head(qh);
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	if (likely(skb != NULL)) {
10788c2ecf20Sopenharmony_ci		unsigned int len = qdisc_pkt_len(skb);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		qdisc_qstats_backlog_dec(sch, skb);
10818c2ecf20Sopenharmony_ci		__qdisc_drop(skb, to_free);
10828c2ecf20Sopenharmony_ci		return len;
10838c2ecf20Sopenharmony_ci	}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	return 0;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	const struct qdisc_skb_head *qh = &sch->q;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	return qh->head;
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci/* generic pseudo peek method for non-work-conserving qdisc */
10968c2ecf20Sopenharmony_cistatic inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
10978c2ecf20Sopenharmony_ci{
10988c2ecf20Sopenharmony_ci	struct sk_buff *skb = skb_peek(&sch->gso_skb);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	/* we can reuse ->gso_skb because peek isn't called for root qdiscs */
11018c2ecf20Sopenharmony_ci	if (!skb) {
11028c2ecf20Sopenharmony_ci		skb = sch->dequeue(sch);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci		if (skb) {
11058c2ecf20Sopenharmony_ci			__skb_queue_head(&sch->gso_skb, skb);
11068c2ecf20Sopenharmony_ci			/* it's still part of the queue */
11078c2ecf20Sopenharmony_ci			qdisc_qstats_backlog_inc(sch, skb);
11088c2ecf20Sopenharmony_ci			sch->q.qlen++;
11098c2ecf20Sopenharmony_ci		}
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	return skb;
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic inline void qdisc_update_stats_at_dequeue(struct Qdisc *sch,
11168c2ecf20Sopenharmony_ci						 struct sk_buff *skb)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	if (qdisc_is_percpu_stats(sch)) {
11198c2ecf20Sopenharmony_ci		qdisc_qstats_cpu_backlog_dec(sch, skb);
11208c2ecf20Sopenharmony_ci		qdisc_bstats_cpu_update(sch, skb);
11218c2ecf20Sopenharmony_ci		qdisc_qstats_cpu_qlen_dec(sch);
11228c2ecf20Sopenharmony_ci	} else {
11238c2ecf20Sopenharmony_ci		qdisc_qstats_backlog_dec(sch, skb);
11248c2ecf20Sopenharmony_ci		qdisc_bstats_update(sch, skb);
11258c2ecf20Sopenharmony_ci		sch->q.qlen--;
11268c2ecf20Sopenharmony_ci	}
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_cistatic inline void qdisc_update_stats_at_enqueue(struct Qdisc *sch,
11308c2ecf20Sopenharmony_ci						 unsigned int pkt_len)
11318c2ecf20Sopenharmony_ci{
11328c2ecf20Sopenharmony_ci	if (qdisc_is_percpu_stats(sch)) {
11338c2ecf20Sopenharmony_ci		qdisc_qstats_cpu_qlen_inc(sch);
11348c2ecf20Sopenharmony_ci		this_cpu_add(sch->cpu_qstats->backlog, pkt_len);
11358c2ecf20Sopenharmony_ci	} else {
11368c2ecf20Sopenharmony_ci		sch->qstats.backlog += pkt_len;
11378c2ecf20Sopenharmony_ci		sch->q.qlen++;
11388c2ecf20Sopenharmony_ci	}
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */
11428c2ecf20Sopenharmony_cistatic inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
11438c2ecf20Sopenharmony_ci{
11448c2ecf20Sopenharmony_ci	struct sk_buff *skb = skb_peek(&sch->gso_skb);
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	if (skb) {
11478c2ecf20Sopenharmony_ci		skb = __skb_dequeue(&sch->gso_skb);
11488c2ecf20Sopenharmony_ci		if (qdisc_is_percpu_stats(sch)) {
11498c2ecf20Sopenharmony_ci			qdisc_qstats_cpu_backlog_dec(sch, skb);
11508c2ecf20Sopenharmony_ci			qdisc_qstats_cpu_qlen_dec(sch);
11518c2ecf20Sopenharmony_ci		} else {
11528c2ecf20Sopenharmony_ci			qdisc_qstats_backlog_dec(sch, skb);
11538c2ecf20Sopenharmony_ci			sch->q.qlen--;
11548c2ecf20Sopenharmony_ci		}
11558c2ecf20Sopenharmony_ci	} else {
11568c2ecf20Sopenharmony_ci		skb = sch->dequeue(sch);
11578c2ecf20Sopenharmony_ci	}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	return skb;
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_cistatic inline void __qdisc_reset_queue(struct qdisc_skb_head *qh)
11638c2ecf20Sopenharmony_ci{
11648c2ecf20Sopenharmony_ci	/*
11658c2ecf20Sopenharmony_ci	 * We do not know the backlog in bytes of this list, it
11668c2ecf20Sopenharmony_ci	 * is up to the caller to correct it
11678c2ecf20Sopenharmony_ci	 */
11688c2ecf20Sopenharmony_ci	ASSERT_RTNL();
11698c2ecf20Sopenharmony_ci	if (qh->qlen) {
11708c2ecf20Sopenharmony_ci		rtnl_kfree_skbs(qh->head, qh->tail);
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci		qh->head = NULL;
11738c2ecf20Sopenharmony_ci		qh->tail = NULL;
11748c2ecf20Sopenharmony_ci		qh->qlen = 0;
11758c2ecf20Sopenharmony_ci	}
11768c2ecf20Sopenharmony_ci}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_cistatic inline void qdisc_reset_queue(struct Qdisc *sch)
11798c2ecf20Sopenharmony_ci{
11808c2ecf20Sopenharmony_ci	__qdisc_reset_queue(&sch->q);
11818c2ecf20Sopenharmony_ci}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_cistatic inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
11848c2ecf20Sopenharmony_ci					  struct Qdisc **pold)
11858c2ecf20Sopenharmony_ci{
11868c2ecf20Sopenharmony_ci	struct Qdisc *old;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	sch_tree_lock(sch);
11898c2ecf20Sopenharmony_ci	old = *pold;
11908c2ecf20Sopenharmony_ci	*pold = new;
11918c2ecf20Sopenharmony_ci	if (old != NULL)
11928c2ecf20Sopenharmony_ci		qdisc_purge_queue(old);
11938c2ecf20Sopenharmony_ci	sch_tree_unlock(sch);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	return old;
11968c2ecf20Sopenharmony_ci}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_cistatic inline void rtnl_qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
11998c2ecf20Sopenharmony_ci{
12008c2ecf20Sopenharmony_ci	rtnl_kfree_skbs(skb, skb);
12018c2ecf20Sopenharmony_ci	qdisc_qstats_drop(sch);
12028c2ecf20Sopenharmony_ci}
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_cistatic inline int qdisc_drop_cpu(struct sk_buff *skb, struct Qdisc *sch,
12058c2ecf20Sopenharmony_ci				 struct sk_buff **to_free)
12068c2ecf20Sopenharmony_ci{
12078c2ecf20Sopenharmony_ci	__qdisc_drop(skb, to_free);
12088c2ecf20Sopenharmony_ci	qdisc_qstats_cpu_drop(sch);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	return NET_XMIT_DROP;
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch,
12148c2ecf20Sopenharmony_ci			     struct sk_buff **to_free)
12158c2ecf20Sopenharmony_ci{
12168c2ecf20Sopenharmony_ci	__qdisc_drop(skb, to_free);
12178c2ecf20Sopenharmony_ci	qdisc_qstats_drop(sch);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	return NET_XMIT_DROP;
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cistatic inline int qdisc_drop_all(struct sk_buff *skb, struct Qdisc *sch,
12238c2ecf20Sopenharmony_ci				 struct sk_buff **to_free)
12248c2ecf20Sopenharmony_ci{
12258c2ecf20Sopenharmony_ci	__qdisc_drop_all(skb, to_free);
12268c2ecf20Sopenharmony_ci	qdisc_qstats_drop(sch);
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	return NET_XMIT_DROP;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci/* Length to Time (L2T) lookup in a qdisc_rate_table, to determine how
12328c2ecf20Sopenharmony_ci   long it will take to send a packet given its size.
12338c2ecf20Sopenharmony_ci */
12348c2ecf20Sopenharmony_cistatic inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen)
12358c2ecf20Sopenharmony_ci{
12368c2ecf20Sopenharmony_ci	int slot = pktlen + rtab->rate.cell_align + rtab->rate.overhead;
12378c2ecf20Sopenharmony_ci	if (slot < 0)
12388c2ecf20Sopenharmony_ci		slot = 0;
12398c2ecf20Sopenharmony_ci	slot >>= rtab->rate.cell_log;
12408c2ecf20Sopenharmony_ci	if (slot > 255)
12418c2ecf20Sopenharmony_ci		return rtab->data[255]*(slot >> 8) + rtab->data[slot & 0xFF];
12428c2ecf20Sopenharmony_ci	return rtab->data[slot];
12438c2ecf20Sopenharmony_ci}
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_cistruct psched_ratecfg {
12468c2ecf20Sopenharmony_ci	u64	rate_bytes_ps; /* bytes per second */
12478c2ecf20Sopenharmony_ci	u32	mult;
12488c2ecf20Sopenharmony_ci	u16	overhead;
12498c2ecf20Sopenharmony_ci	u16	mpu;
12508c2ecf20Sopenharmony_ci	u8	linklayer;
12518c2ecf20Sopenharmony_ci	u8	shift;
12528c2ecf20Sopenharmony_ci};
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_cistatic inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
12558c2ecf20Sopenharmony_ci				unsigned int len)
12568c2ecf20Sopenharmony_ci{
12578c2ecf20Sopenharmony_ci	len += r->overhead;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	if (len < r->mpu)
12608c2ecf20Sopenharmony_ci		len = r->mpu;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	if (unlikely(r->linklayer == TC_LINKLAYER_ATM))
12638c2ecf20Sopenharmony_ci		return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	return ((u64)len * r->mult) >> r->shift;
12668c2ecf20Sopenharmony_ci}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_civoid psched_ratecfg_precompute(struct psched_ratecfg *r,
12698c2ecf20Sopenharmony_ci			       const struct tc_ratespec *conf,
12708c2ecf20Sopenharmony_ci			       u64 rate64);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_cistatic inline void psched_ratecfg_getrate(struct tc_ratespec *res,
12738c2ecf20Sopenharmony_ci					  const struct psched_ratecfg *r)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	memset(res, 0, sizeof(*res));
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	/* legacy struct tc_ratespec has a 32bit @rate field
12788c2ecf20Sopenharmony_ci	 * Qdisc using 64bit rate should add new attributes
12798c2ecf20Sopenharmony_ci	 * in order to maintain compatibility.
12808c2ecf20Sopenharmony_ci	 */
12818c2ecf20Sopenharmony_ci	res->rate = min_t(u64, r->rate_bytes_ps, ~0U);
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	res->overhead = r->overhead;
12848c2ecf20Sopenharmony_ci	res->mpu = r->mpu;
12858c2ecf20Sopenharmony_ci	res->linklayer = (r->linklayer & TC_LINKLAYER_MASK);
12868c2ecf20Sopenharmony_ci}
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci/* Mini Qdisc serves for specific needs of ingress/clsact Qdisc.
12898c2ecf20Sopenharmony_ci * The fast path only needs to access filter list and to update stats
12908c2ecf20Sopenharmony_ci */
12918c2ecf20Sopenharmony_cistruct mini_Qdisc {
12928c2ecf20Sopenharmony_ci	struct tcf_proto *filter_list;
12938c2ecf20Sopenharmony_ci	struct tcf_block *block;
12948c2ecf20Sopenharmony_ci	struct gnet_stats_basic_cpu __percpu *cpu_bstats;
12958c2ecf20Sopenharmony_ci	struct gnet_stats_queue	__percpu *cpu_qstats;
12968c2ecf20Sopenharmony_ci	struct rcu_head rcu;
12978c2ecf20Sopenharmony_ci};
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_cistatic inline void mini_qdisc_bstats_cpu_update(struct mini_Qdisc *miniq,
13008c2ecf20Sopenharmony_ci						const struct sk_buff *skb)
13018c2ecf20Sopenharmony_ci{
13028c2ecf20Sopenharmony_ci	bstats_cpu_update(this_cpu_ptr(miniq->cpu_bstats), skb);
13038c2ecf20Sopenharmony_ci}
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_cistatic inline void mini_qdisc_qstats_cpu_drop(struct mini_Qdisc *miniq)
13068c2ecf20Sopenharmony_ci{
13078c2ecf20Sopenharmony_ci	this_cpu_inc(miniq->cpu_qstats->drops);
13088c2ecf20Sopenharmony_ci}
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_cistruct mini_Qdisc_pair {
13118c2ecf20Sopenharmony_ci	struct mini_Qdisc miniq1;
13128c2ecf20Sopenharmony_ci	struct mini_Qdisc miniq2;
13138c2ecf20Sopenharmony_ci	struct mini_Qdisc __rcu **p_miniq;
13148c2ecf20Sopenharmony_ci};
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_civoid mini_qdisc_pair_swap(struct mini_Qdisc_pair *miniqp,
13178c2ecf20Sopenharmony_ci			  struct tcf_proto *tp_head);
13188c2ecf20Sopenharmony_civoid mini_qdisc_pair_init(struct mini_Qdisc_pair *miniqp, struct Qdisc *qdisc,
13198c2ecf20Sopenharmony_ci			  struct mini_Qdisc __rcu **p_miniq);
13208c2ecf20Sopenharmony_civoid mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp,
13218c2ecf20Sopenharmony_ci				struct tcf_block *block);
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci/* Make sure qdisc is no longer in SCHED state. */
13248c2ecf20Sopenharmony_cistatic inline void qdisc_synchronize(const struct Qdisc *q)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	while (test_bit(__QDISC_STATE_SCHED, &q->state))
13278c2ecf20Sopenharmony_ci		msleep(1);
13288c2ecf20Sopenharmony_ci}
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci#endif
1331