1542 lines · 38.7 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 */#ifndef __NET_SCHED_GENERIC_H#define __NET_SCHED_GENERIC_H #include <linux/netdevice.h>#include <linux/types.h>#include <linux/rcupdate.h>#include <linux/pkt_sched.h>#include <linux/pkt_cls.h>#include <linux/percpu.h>#include <linux/dynamic_queue_limits.h>#include <linux/list.h>#include <linux/refcount.h>#include <linux/workqueue.h>#include <linux/mutex.h>#include <linux/rwsem.h>#include <linux/atomic.h>#include <linux/hashtable.h>#include <net/gen_stats.h>#include <net/rtnetlink.h>#include <net/flow_offload.h>#include <linux/xarray.h>#include <net/dropreason-qdisc.h> struct Qdisc_ops;struct qdisc_walker;struct tcf_walker;struct module;struct bpf_flow_keys;struct Qdisc;struct netdev_queue; struct qdisc_rate_table {	struct tc_ratespec rate;	u32		data[256];	struct qdisc_rate_table *next;	int		refcnt;}; enum qdisc_state_t {	__QDISC_STATE_SCHED,	__QDISC_STATE_DEACTIVATED,	__QDISC_STATE_MISSED,	__QDISC_STATE_DRAINING,}; #define QDISC_STATE_MISSED	BIT(__QDISC_STATE_MISSED)#define QDISC_STATE_DRAINING	BIT(__QDISC_STATE_DRAINING) #define QDISC_STATE_NON_EMPTY	(QDISC_STATE_MISSED | \					QDISC_STATE_DRAINING) struct qdisc_size_table {	struct rcu_head		rcu;	struct list_head	list;	struct tc_sizespec	szopts;	int			refcnt;	u16			data[];}; /* similar to sk_buff_head, but skb->prev pointer is undefined. */struct qdisc_skb_head {	struct sk_buff	*head;	struct sk_buff	*tail;	__u32		qlen;	spinlock_t	lock;}; struct Qdisc {	int 			(*enqueue)(struct sk_buff *skb,					   struct Qdisc *sch,					   struct sk_buff **to_free);	struct sk_buff *	(*dequeue)(struct Qdisc *sch);	unsigned int		flags;#define TCQ_F_BUILTIN		1#define TCQ_F_INGRESS		2#define TCQ_F_CAN_BYPASS	4#define TCQ_F_MQROOT		8#define TCQ_F_ONETXQUEUE	0x10 /* dequeue_skb() can assume all skbs are for				      * q->dev_queue : It can test				      * netif_xmit_frozen_or_stopped() before				      * dequeueing next packet.				      * Its true for MQ/MQPRIO slaves, or non				      * multiqueue device.				      */#define TCQ_F_WARN_NONWC	(1 << 16)#define TCQ_F_CPUSTATS		0x20 /* run using percpu statistics */#define TCQ_F_NOPARENT		0x40 /* root of its hierarchy :				      * qdisc_tree_reduce_backlog() should stop.				      */#define TCQ_F_INVISIBLE		0x80 /* invisible by default in dump */#define TCQ_F_NOLOCK		0x100 /* qdisc does not require locking */#define TCQ_F_OFFLOADED		0x200 /* qdisc is offloaded to HW */#define TCQ_F_DEQUEUE_DROPS	0x400 /* ->dequeue() can drop packets in q->to_free */ 	u32			limit;	const struct Qdisc_ops	*ops;	struct qdisc_size_table	__rcu *stab;	struct hlist_node       hash;	u32			handle;	u32			parent; 	struct netdev_queue	*dev_queue; 	struct net_rate_estimator __rcu *rate_est;	struct gnet_stats_basic_sync __percpu *cpu_bstats;	struct gnet_stats_queue	__percpu *cpu_qstats;	int			pad;	refcount_t		refcnt; 	/* Cache line potentially dirtied in dequeue() or __netif_reschedule(). */	__cacheline_group_begin(Qdisc_read_mostly) ____cacheline_aligned;		struct sk_buff_head	gso_skb;		struct Qdisc		*next_sched;		struct sk_buff_head	skb_bad_txq;	__cacheline_group_end(Qdisc_read_mostly); 	/* Fields dirtied in dequeue() fast path. */	__cacheline_group_begin(Qdisc_write) ____cacheline_aligned;		struct qdisc_skb_head	q;		unsigned long		state;		struct gnet_stats_basic_sync bstats;		bool			running; /* must be written under qdisc spinlock */ 		/* Note : we only change qstats.backlog in fast path. */		struct gnet_stats_queue	qstats; 		struct sk_buff		*to_free;	__cacheline_group_end(Qdisc_write);  	atomic_long_t		defer_count ____cacheline_aligned_in_smp;	struct llist_head	defer_list; 	spinlock_t		seqlock; 	struct rcu_head		rcu;	netdevice_tracker	dev_tracker;	struct lock_class_key	root_lock_key;	/* private data */	long privdata[] ____cacheline_aligned;}; static inline void qdisc_refcount_inc(struct Qdisc *qdisc){	if (qdisc->flags & TCQ_F_BUILTIN)		return;	refcount_inc(&qdisc->refcnt);} static inline bool qdisc_refcount_dec_if_one(struct Qdisc *qdisc){	if (qdisc->flags & TCQ_F_BUILTIN)		return true;	return refcount_dec_if_one(&qdisc->refcnt);} /* Intended to be used by unlocked users, when concurrent qdisc release is * possible. */ static inline struct Qdisc *qdisc_refcount_inc_nz(struct Qdisc *qdisc){	if (qdisc->flags & TCQ_F_BUILTIN)		return qdisc;	if (refcount_inc_not_zero(&qdisc->refcnt))		return qdisc;	return NULL;} /* For !TCQ_F_NOLOCK qdisc: callers must either call this within a qdisc * root_lock section, or provide their own memory barriers -- ordering * against qdisc_run_begin/end() atomic bit operations. */static inline bool qdisc_is_running(struct Qdisc *qdisc){	if (qdisc->flags & TCQ_F_NOLOCK)		return spin_is_locked(&qdisc->seqlock);	return READ_ONCE(qdisc->running);} static inline bool nolock_qdisc_is_empty(const struct Qdisc *qdisc){	return !(READ_ONCE(qdisc->state) & QDISC_STATE_NON_EMPTY);} static inline bool qdisc_is_percpu_stats(const struct Qdisc *q){	return q->flags & TCQ_F_CPUSTATS;} static inline bool qdisc_is_empty(const struct Qdisc *qdisc){	if (qdisc_is_percpu_stats(qdisc))		return nolock_qdisc_is_empty(qdisc);	return !READ_ONCE(qdisc->q.qlen);} /* For !TCQ_F_NOLOCK qdisc, qdisc_run_begin/end() must be invoked with * the qdisc root lock acquired. */static inline bool qdisc_run_begin(struct Qdisc *qdisc){	if (qdisc->flags & TCQ_F_NOLOCK) {		if (spin_trylock(&qdisc->seqlock))			return true; 		/* No need to insist if the MISSED flag was already set.		 * Note that test_and_set_bit() also gives us memory ordering		 * guarantees wrt potential earlier enqueue() and below		 * spin_trylock(), both of which are necessary to prevent races		 */		if (test_and_set_bit(__QDISC_STATE_MISSED, &qdisc->state))			return false; 		/* Try to take the lock again to make sure that we will either		 * grab it or the CPU that still has it will see MISSED set		 * when testing it in qdisc_run_end()		 */		return spin_trylock(&qdisc->seqlock);	}	if (READ_ONCE(qdisc->running))		return false;	WRITE_ONCE(qdisc->running, true);	return true;} static inline struct sk_buff *qdisc_run_end(struct Qdisc *qdisc){	struct sk_buff *to_free = NULL; 	if (qdisc->flags & TCQ_F_NOLOCK) {		spin_unlock(&qdisc->seqlock); 		/* spin_unlock() only has store-release semantic. The unlock		 * and test_bit() ordering is a store-load ordering, so a full		 * memory barrier is needed here.		 */		smp_mb(); 		if (unlikely(test_bit(__QDISC_STATE_MISSED,				      &qdisc->state)))			__netif_schedule(qdisc);		return NULL;	} 	if (qdisc->flags & TCQ_F_DEQUEUE_DROPS) {		to_free = qdisc->to_free;		if (to_free)			qdisc->to_free = NULL;	}	WRITE_ONCE(qdisc->running, false);	return to_free;} static inline bool qdisc_may_bulk(const struct Qdisc *qdisc){	return qdisc->flags & TCQ_F_ONETXQUEUE;} static inline int qdisc_avail_bulklimit(const struct netdev_queue *txq){	return netdev_queue_dql_avail(txq);} struct Qdisc_class_ops {	unsigned int		flags;	/* Child qdisc manipulation */	struct netdev_queue *	(*select_queue)(struct Qdisc *, struct tcmsg *);	int			(*graft)(struct Qdisc *, unsigned long cl,					struct Qdisc *, struct Qdisc **,					struct netlink_ext_ack *extack);	struct Qdisc *		(*leaf)(struct Qdisc *, unsigned long cl);	void			(*qlen_notify)(struct Qdisc *, unsigned long); 	/* Class manipulation routines */	unsigned long		(*find)(struct Qdisc *, u32 classid);	int			(*change)(struct Qdisc *, u32, u32,					struct nlattr **, unsigned long *,					struct netlink_ext_ack *);	int			(*delete)(struct Qdisc *, unsigned long,					  struct netlink_ext_ack *);	void			(*walk)(struct Qdisc *, struct qdisc_walker * arg); 	/* Filter manipulation */	struct tcf_block *	(*tcf_block)(struct Qdisc *sch,					     unsigned long arg,					     struct netlink_ext_ack *extack);	unsigned long		(*bind_tcf)(struct Qdisc *, unsigned long,					u32 classid);	void			(*unbind_tcf)(struct Qdisc *, unsigned long); 	/* rtnetlink specific */	int			(*dump)(struct Qdisc *, unsigned long,					struct sk_buff *skb, struct tcmsg*);	int			(*dump_stats)(struct Qdisc *, unsigned long,					struct gnet_dump *);}; /* Qdisc_class_ops flag values */ /* Implements API that doesn't require rtnl lock */enum qdisc_class_ops_flags {	QDISC_CLASS_OPS_DOIT_UNLOCKED = 1,}; struct Qdisc_ops {	struct Qdisc_ops	*next;	const struct Qdisc_class_ops	*cl_ops;	char			id[IFNAMSIZ];	int			priv_size;	unsigned int		static_flags; 	int 			(*enqueue)(struct sk_buff *skb,					   struct Qdisc *sch,					   struct sk_buff **to_free);	struct sk_buff *	(*dequeue)(struct Qdisc *);	struct sk_buff *	(*peek)(struct Qdisc *); 	int			(*init)(struct Qdisc *sch, struct nlattr *arg,					struct netlink_ext_ack *extack);	void			(*reset)(struct Qdisc *);	void			(*destroy)(struct Qdisc *);	int			(*change)(struct Qdisc *sch,					  struct nlattr *arg,					  struct netlink_ext_ack *extack);	void			(*attach)(struct Qdisc *sch);	int			(*change_tx_queue_len)(struct Qdisc *, unsigned int);	void			(*change_real_num_tx)(struct Qdisc *sch,						      unsigned int new_real_tx); 	int			(*dump)(struct Qdisc *, struct sk_buff *);	int			(*dump_stats)(struct Qdisc *, struct gnet_dump *); 	void			(*ingress_block_set)(struct Qdisc *sch,						     u32 block_index);	void			(*egress_block_set)(struct Qdisc *sch,						    u32 block_index);	u32			(*ingress_block_get)(struct Qdisc *sch);	u32			(*egress_block_get)(struct Qdisc *sch); 	struct module		*owner;}; struct tcf_result {	union {		struct {			unsigned long	class;			u32		classid;		};		const struct tcf_proto *goto_tp;	};}; struct tcf_chain; struct tcf_proto_ops {	struct list_head	head;	char			kind[IFNAMSIZ]; 	int			(*classify)(struct sk_buff *,					    const struct tcf_proto *,					    struct tcf_result *);	int			(*init)(struct tcf_proto*);	void			(*destroy)(struct tcf_proto *tp, bool rtnl_held,					   struct netlink_ext_ack *extack); 	void*			(*get)(struct tcf_proto*, u32 handle);	void			(*put)(struct tcf_proto *tp, void *f);	int			(*change)(struct net *net, struct sk_buff *,					struct tcf_proto*, unsigned long,					u32 handle, struct nlattr **,					void **, u32,					struct netlink_ext_ack *);	int			(*delete)(struct tcf_proto *tp, void *arg,					  bool *last, bool rtnl_held,					  struct netlink_ext_ack *);	bool			(*delete_empty)(struct tcf_proto *tp);	void			(*walk)(struct tcf_proto *tp,					struct tcf_walker *arg, bool rtnl_held);	int			(*reoffload)(struct tcf_proto *tp, bool add,					     flow_setup_cb_t *cb, void *cb_priv,					     struct netlink_ext_ack *extack);	void			(*hw_add)(struct tcf_proto *tp,					  void *type_data);	void			(*hw_del)(struct tcf_proto *tp,					  void *type_data);	void			(*bind_class)(void *, u32, unsigned long,					      void *, unsigned long);	void *			(*tmplt_create)(struct net *net,						struct tcf_chain *chain,						struct nlattr **tca,						struct netlink_ext_ack *extack);	void			(*tmplt_destroy)(void *tmplt_priv);	void			(*tmplt_reoffload)(struct tcf_chain *chain,						   bool add,						   flow_setup_cb_t *cb,						   void *cb_priv);	struct tcf_exts *	(*get_exts)(const struct tcf_proto *tp,					    u32 handle); 	/* rtnetlink specific */	int			(*dump)(struct net*, struct tcf_proto*, void *,					struct sk_buff *skb, struct tcmsg*,					bool);	int			(*terse_dump)(struct net *net,					      struct tcf_proto *tp, void *fh,					      struct sk_buff *skb,					      struct tcmsg *t, bool rtnl_held);	int			(*tmplt_dump)(struct sk_buff *skb,					      struct net *net,					      void *tmplt_priv); 	struct module		*owner;	int			flags;}; /* Classifiers setting TCF_PROTO_OPS_DOIT_UNLOCKED in tcf_proto_ops->flags * are expected to implement tcf_proto_ops->delete_empty(), otherwise race * conditions can occur when filters are inserted/deleted simultaneously. */enum tcf_proto_ops_flags {	TCF_PROTO_OPS_DOIT_UNLOCKED = 1,}; struct tcf_proto {	/* Fast access part */	struct tcf_proto __rcu	*next;	void __rcu		*root; 	/* called under RCU BH lock*/	int			(*classify)(struct sk_buff *,					    const struct tcf_proto *,					    struct tcf_result *);	__be16			protocol; 	/* All the rest */	u32			prio;	void			*data;	const struct tcf_proto_ops	*ops;	struct tcf_chain	*chain;	/* Lock protects tcf_proto shared state and can be used by unlocked	 * classifiers to protect their private data.	 */	spinlock_t		lock;	bool			deleting;	bool			counted;	bool			usesw;	refcount_t		refcnt;	struct rcu_head		rcu;	struct hlist_node	destroy_ht_node;}; struct qdisc_skb_cb {	unsigned int		pkt_len;	u16			pkt_segs;	u16			tc_classid;#define QDISC_CB_PRIV_LEN 20	unsigned char		data[QDISC_CB_PRIV_LEN]; 	u16			slave_dev_queue_mapping;	u8			post_ct:1;	u8			post_ct_snat:1;	u8			post_ct_dnat:1;}; typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); struct tcf_chain {	/* Protects filter_chain. */	struct mutex filter_chain_lock;	struct tcf_proto __rcu *filter_chain;	struct list_head list;	struct tcf_block *block;	u32 index; /* chain index */	unsigned int refcnt;	unsigned int action_refcnt;	bool explicitly_created;	bool flushing;	const struct tcf_proto_ops *tmplt_ops;	void *tmplt_priv;	struct rcu_head rcu;}; struct tcf_block {	struct xarray ports; /* datapath accessible */	/* Lock protects tcf_block and lifetime-management data of chains	 * attached to the block (refcnt, action_refcnt, explicitly_created).	 */	struct mutex lock;	struct list_head chain_list;	u32 index; /* block index for shared blocks */	u32 classid; /* which class this block belongs to */	refcount_t refcnt;	struct net *net;	struct Qdisc *q;	struct rw_semaphore cb_lock; /* protects cb_list and offload counters */	struct flow_block flow_block;	struct list_head owner_list;	bool keep_dst;

Lines 1–500 of 1542.