xref: /openbmc/linux/include/net/pkt_sched.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds #ifndef __NET_PKT_SCHED_H
31da177e4SLinus Torvalds #define __NET_PKT_SCHED_H
41da177e4SLinus Torvalds 
5538e43a4SPatrick McHardy #include <linux/jiffies.h>
6641b9e0eSPatrick McHardy #include <linux/ktime.h>
7d8b9605dSJiri Pirko #include <linux/if_vlan.h>
8855319beSJiri Pirko #include <linux/netdevice.h>
91da177e4SLinus Torvalds #include <net/sch_generic.h>
10855319beSJiri Pirko #include <net/net_namespace.h>
11861932ecSJiri Pirko #include <uapi/linux/pkt_sched.h>
121da177e4SLinus Torvalds 
13d0a81f67SJesper Dangaard Brouer #define DEFAULT_TX_QUEUE_LEN	1000
14b193e15aS王贇 #define STAB_SIZE_LOG_MAX	30
15d0a81f67SJesper Dangaard Brouer 
16fd2c3ef7SEric Dumazet struct qdisc_walker {
171da177e4SLinus Torvalds 	int	stop;
181da177e4SLinus Torvalds 	int	skip;
191da177e4SLinus Torvalds 	int	count;
201da177e4SLinus Torvalds 	int	(*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
211da177e4SLinus Torvalds };
221da177e4SLinus Torvalds 
qdisc_priv(struct Qdisc * q)231da177e4SLinus Torvalds static inline void *qdisc_priv(struct Qdisc *q)
241da177e4SLinus Torvalds {
25846e463aSEric Dumazet 	return &q->privdata;
261da177e4SLinus Torvalds }
271da177e4SLinus Torvalds 
qdisc_from_priv(void * priv)286e1978a9SAllen Pais static inline struct Qdisc *qdisc_from_priv(void *priv)
296e1978a9SAllen Pais {
306e1978a9SAllen Pais 	return container_of(priv, struct Qdisc, privdata);
316e1978a9SAllen Pais }
326e1978a9SAllen Pais 
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds    Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds    Normal IP packet size ~ 512byte, hence:
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds    0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
391da177e4SLinus Torvalds    10Mbit ethernet.
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds    10msec resolution -> <50Kbit/sec.
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds    The result: [34]86 is not good choice for QoS router :-(
441da177e4SLinus Torvalds 
4525985edcSLucas De Marchi    The things are not so bad, because we may use artificial
461da177e4SLinus Torvalds    clock evaluated by integration of network data flow
471da177e4SLinus Torvalds    in the most critical places.
481da177e4SLinus Torvalds  */
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds typedef u64	psched_time_t;
511da177e4SLinus Torvalds typedef long	psched_tdiff_t;
521da177e4SLinus Torvalds 
53a4a710c4SJarek Poplawski /* Avoid doing 64 bit divide */
54a4a710c4SJarek Poplawski #define PSCHED_SHIFT			6
55ca44d6e6SJarek Poplawski #define PSCHED_TICKS2NS(x)		((s64)(x) << PSCHED_SHIFT)
56ca44d6e6SJarek Poplawski #define PSCHED_NS2TICKS(x)		((x) >> PSCHED_SHIFT)
571da177e4SLinus Torvalds 
58ca44d6e6SJarek Poplawski #define PSCHED_TICKS_PER_SEC		PSCHED_NS2TICKS(NSEC_PER_SEC)
59a084980dSPatrick McHardy #define PSCHED_PASTPERFECT		0
601da177e4SLinus Torvalds 
psched_get_time(void)613bebcda2SPatrick McHardy static inline psched_time_t psched_get_time(void)
623bebcda2SPatrick McHardy {
63d2de875cSEric Dumazet 	return PSCHED_NS2TICKS(ktime_get_ns());
643bebcda2SPatrick McHardy }
653bebcda2SPatrick McHardy 
664179477fSPatrick McHardy struct qdisc_watchdog {
674179477fSPatrick McHardy 	struct hrtimer	timer;
684179477fSPatrick McHardy 	struct Qdisc	*qdisc;
694179477fSPatrick McHardy };
704179477fSPatrick McHardy 
71860b642bSVinicius Costa Gomes void qdisc_watchdog_init_clockid(struct qdisc_watchdog *wd, struct Qdisc *qdisc,
72860b642bSVinicius Costa Gomes 				 clockid_t clockid);
735c15257fSJoe Perches void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc);
74efe074c2SEric Dumazet 
75efe074c2SEric Dumazet void qdisc_watchdog_schedule_range_ns(struct qdisc_watchdog *wd, u64 expires,
76efe074c2SEric Dumazet 				      u64 delta_ns);
77efe074c2SEric Dumazet 
qdisc_watchdog_schedule_ns(struct qdisc_watchdog * wd,u64 expires)78efe074c2SEric Dumazet static inline void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd,
79efe074c2SEric Dumazet 					      u64 expires)
80efe074c2SEric Dumazet {
81efe074c2SEric Dumazet 	return qdisc_watchdog_schedule_range_ns(wd, expires, 0ULL);
82efe074c2SEric Dumazet }
8334c5d292SJiri Pirko 
qdisc_watchdog_schedule(struct qdisc_watchdog * wd,psched_time_t expires)8434c5d292SJiri Pirko static inline void qdisc_watchdog_schedule(struct qdisc_watchdog *wd,
8534c5d292SJiri Pirko 					   psched_time_t expires)
8634c5d292SJiri Pirko {
8745f50bedSEric Dumazet 	qdisc_watchdog_schedule_ns(wd, PSCHED_TICKS2NS(expires));
8834c5d292SJiri Pirko }
8934c5d292SJiri Pirko 
905c15257fSJoe Perches void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
914179477fSPatrick McHardy 
921da177e4SLinus Torvalds extern struct Qdisc_ops pfifo_qdisc_ops;
931da177e4SLinus Torvalds extern struct Qdisc_ops bfifo_qdisc_ops;
9457dbb2d8SHagen Paul Pfeifer extern struct Qdisc_ops pfifo_head_drop_qdisc_ops;
951da177e4SLinus Torvalds 
965c15257fSJoe Perches int fifo_set_limit(struct Qdisc *q, unsigned int limit);
975c15257fSJoe Perches struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
98a38a9882SAlexander Aring 			       unsigned int limit,
99a38a9882SAlexander Aring 			       struct netlink_ext_ack *extack);
100fb0305ceSPatrick McHardy 
1015c15257fSJoe Perches int register_qdisc(struct Qdisc_ops *qops);
10252327d2eSZhengchao Shao void unregister_qdisc(struct Qdisc_ops *qops);
1036da7c8fcSstephen hemminger void qdisc_get_default(char *id, size_t len);
1046da7c8fcSstephen hemminger int qdisc_set_default(const char *id);
1056da7c8fcSstephen hemminger 
10649b49971SJiri Kosina void qdisc_hash_add(struct Qdisc *q, bool invisible);
10759cc1f61SJiri Kosina void qdisc_hash_del(struct Qdisc *q);
1085c15257fSJoe Perches struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
1093a7d0d07SVlad Buslov struct Qdisc *qdisc_lookup_rcu(struct net_device *dev, u32 handle);
1105c15257fSJoe Perches struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
111e9bc3fa2SAlexander Aring 					struct nlattr *tab,
112e9bc3fa2SAlexander Aring 					struct netlink_ext_ack *extack);
1135c15257fSJoe Perches void qdisc_put_rtab(struct qdisc_rate_table *tab);
1145c15257fSJoe Perches void qdisc_put_stab(struct qdisc_size_table *tab);
1156e765a00SFlorian Westphal void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc);
11629b86cdaSJohn Fastabend bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
117bbd8a0d3SKrishna Kumar 		     struct net_device *dev, struct netdev_queue *txq,
11855a93b3eSEric Dumazet 		     spinlock_t *root_lock, bool validate);
1191da177e4SLinus Torvalds 
1205c15257fSJoe Perches void __qdisc_run(struct Qdisc *q);
1211da177e4SLinus Torvalds 
qdisc_run(struct Qdisc * q)12237437bb2SDavid S. Miller static inline void qdisc_run(struct Qdisc *q)
1231da177e4SLinus Torvalds {
1246c148184SJohn Fastabend 	if (qdisc_run_begin(q)) {
12537437bb2SDavid S. Miller 		__qdisc_run(q);
1266c148184SJohn Fastabend 		qdisc_run_end(q);
1276c148184SJohn Fastabend 	}
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds 
130886bc7d6SEric Dumazet extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1];
131886bc7d6SEric Dumazet 
1321da177e4SLinus Torvalds /* Calculate maximal size of packet seen by hard_start_xmit
1331da177e4SLinus Torvalds    routine of this device.
1341da177e4SLinus Torvalds  */
psched_mtu(const struct net_device * dev)13595c96174SEric Dumazet static inline unsigned int psched_mtu(const struct net_device *dev)
1361da177e4SLinus Torvalds {
137*150e33e6SPedro Tammela 	return READ_ONCE(dev->mtu) + dev->hard_header_len;
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds 
qdisc_net(struct Qdisc * q)140855319beSJiri Pirko static inline struct net *qdisc_net(struct Qdisc *q)
141855319beSJiri Pirko {
142855319beSJiri Pirko 	return dev_net(q->dev_queue->dev);
143855319beSJiri Pirko }
144855319beSJiri Pirko 
145aac4daa8SVladimir Oltean struct tc_query_caps_base {
146aac4daa8SVladimir Oltean 	enum tc_setup_type type;
147aac4daa8SVladimir Oltean 	void *caps;
148aac4daa8SVladimir Oltean };
149aac4daa8SVladimir Oltean 
1503d0bd028SVinicius Costa Gomes struct tc_cbs_qopt_offload {
1513d0bd028SVinicius Costa Gomes 	u8 enable;
1523d0bd028SVinicius Costa Gomes 	s32 queue;
1533d0bd028SVinicius Costa Gomes 	s32 hicredit;
1543d0bd028SVinicius Costa Gomes 	s32 locredit;
1553d0bd028SVinicius Costa Gomes 	s32 idleslope;
1563d0bd028SVinicius Costa Gomes 	s32 sendslope;
1573d0bd028SVinicius Costa Gomes };
1583d0bd028SVinicius Costa Gomes 
15988cab771SJesus Sanchez-Palencia struct tc_etf_qopt_offload {
16088cab771SJesus Sanchez-Palencia 	u8 enable;
16188cab771SJesus Sanchez-Palencia 	s32 queue;
16288cab771SJesus Sanchez-Palencia };
16388cab771SJesus Sanchez-Palencia 
16419278d76SVladimir Oltean struct tc_mqprio_caps {
16519278d76SVladimir Oltean 	bool validate_queue_counts:1;
16619278d76SVladimir Oltean };
16719278d76SVladimir Oltean 
1689adafe2bSVladimir Oltean struct tc_mqprio_qopt_offload {
1699adafe2bSVladimir Oltean 	/* struct tc_mqprio_qopt must always be the first element */
1709adafe2bSVladimir Oltean 	struct tc_mqprio_qopt qopt;
171c54876cdSVladimir Oltean 	struct netlink_ext_ack *extack;
1729adafe2bSVladimir Oltean 	u16 mode;
1739adafe2bSVladimir Oltean 	u16 shaper;
1749adafe2bSVladimir Oltean 	u32 flags;
1759adafe2bSVladimir Oltean 	u64 min_rate[TC_QOPT_MAX_QUEUE];
1769adafe2bSVladimir Oltean 	u64 max_rate[TC_QOPT_MAX_QUEUE];
177f62af20bSVladimir Oltean 	unsigned long preemptible_tcs;
1789adafe2bSVladimir Oltean };
1799adafe2bSVladimir Oltean 
180a54fc09eSVladimir Oltean struct tc_taprio_caps {
181a54fc09eSVladimir Oltean 	bool supports_queue_max_sdu:1;
182522d15eaSVladimir Oltean 	bool gate_mask_per_txq:1;
1832f530df7SVladimir Oltean 	/* Device expects lower TXQ numbers to have higher priority over higher
1842f530df7SVladimir Oltean 	 * TXQs, regardless of their TC mapping. DO NOT USE FOR NEW DRIVERS,
1852f530df7SVladimir Oltean 	 * INSTEAD ENFORCE A PROPER TC:TXQ MAPPING COMING FROM USER SPACE.
1862f530df7SVladimir Oltean 	 */
1872f530df7SVladimir Oltean 	bool broken_mqprio:1;
188a54fc09eSVladimir Oltean };
189a54fc09eSVladimir Oltean 
1902d800bc5SVladimir Oltean enum tc_taprio_qopt_cmd {
1912d800bc5SVladimir Oltean 	TAPRIO_CMD_REPLACE,
1922d800bc5SVladimir Oltean 	TAPRIO_CMD_DESTROY,
1936c1adb65SVladimir Oltean 	TAPRIO_CMD_STATS,
1942b84960fSVladimir Oltean 	TAPRIO_CMD_QUEUE_STATS,
1956c1adb65SVladimir Oltean };
1966c1adb65SVladimir Oltean 
1976c1adb65SVladimir Oltean /**
1986c1adb65SVladimir Oltean  * struct tc_taprio_qopt_stats - IEEE 802.1Qbv statistics
1996c1adb65SVladimir Oltean  * @window_drops: Frames that were dropped because they were too large to be
2006c1adb65SVladimir Oltean  *	transmitted in any of the allotted time windows (open gates) for their
2016c1adb65SVladimir Oltean  *	traffic class.
2026c1adb65SVladimir Oltean  * @tx_overruns: Frames still being transmitted by the MAC after the
2036c1adb65SVladimir Oltean  *	transmission gate associated with their traffic class has closed.
2046c1adb65SVladimir Oltean  *	Equivalent to `12.29.1.1.2 TransmissionOverrun` from 802.1Q-2018.
2056c1adb65SVladimir Oltean  */
2066c1adb65SVladimir Oltean struct tc_taprio_qopt_stats {
2076c1adb65SVladimir Oltean 	u64 window_drops;
2086c1adb65SVladimir Oltean 	u64 tx_overruns;
2096c1adb65SVladimir Oltean };
2106c1adb65SVladimir Oltean 
2112b84960fSVladimir Oltean struct tc_taprio_qopt_queue_stats {
2122b84960fSVladimir Oltean 	int queue;
2136c1adb65SVladimir Oltean 	struct tc_taprio_qopt_stats stats;
2142d800bc5SVladimir Oltean };
2152d800bc5SVladimir Oltean 
2169c66d156SVinicius Costa Gomes struct tc_taprio_sched_entry {
2179c66d156SVinicius Costa Gomes 	u8 command; /* TC_TAPRIO_CMD_* */
2189c66d156SVinicius Costa Gomes 
2199c66d156SVinicius Costa Gomes 	/* The gate_mask in the offloading side refers to traffic classes */
2209c66d156SVinicius Costa Gomes 	u32 gate_mask;
2219c66d156SVinicius Costa Gomes 	u32 interval;
2229c66d156SVinicius Costa Gomes };
2239c66d156SVinicius Costa Gomes 
2249c66d156SVinicius Costa Gomes struct tc_taprio_qopt_offload {
2256c1adb65SVladimir Oltean 	enum tc_taprio_qopt_cmd cmd;
2266c1adb65SVladimir Oltean 
2276c1adb65SVladimir Oltean 	union {
2286c1adb65SVladimir Oltean 		/* TAPRIO_CMD_STATS */
2296c1adb65SVladimir Oltean 		struct tc_taprio_qopt_stats stats;
2302b84960fSVladimir Oltean 		/* TAPRIO_CMD_QUEUE_STATS */
2312b84960fSVladimir Oltean 		struct tc_taprio_qopt_queue_stats queue_stats;
2326c1adb65SVladimir Oltean 		/* TAPRIO_CMD_REPLACE */
2336c1adb65SVladimir Oltean 		struct {
23409c794c0SVladimir Oltean 			struct tc_mqprio_qopt_offload mqprio;
235c54876cdSVladimir Oltean 			struct netlink_ext_ack *extack;
2369c66d156SVinicius Costa Gomes 			ktime_t base_time;
2379c66d156SVinicius Costa Gomes 			u64 cycle_time;
2389c66d156SVinicius Costa Gomes 			u64 cycle_time_extension;
239a54fc09eSVladimir Oltean 			u32 max_sdu[TC_MAX_QUEUE];
2409c66d156SVinicius Costa Gomes 
2419c66d156SVinicius Costa Gomes 			size_t num_entries;
242b90feaffSGustavo A. R. Silva 			struct tc_taprio_sched_entry entries[];
2439c66d156SVinicius Costa Gomes 		};
2446c1adb65SVladimir Oltean 	};
2456c1adb65SVladimir Oltean };
2469c66d156SVinicius Costa Gomes 
247d7be266aSVladimir Oltean #if IS_ENABLED(CONFIG_NET_SCH_TAPRIO)
248d7be266aSVladimir Oltean 
2499c66d156SVinicius Costa Gomes /* Reference counting */
2509c66d156SVinicius Costa Gomes struct tc_taprio_qopt_offload *taprio_offload_get(struct tc_taprio_qopt_offload
2519c66d156SVinicius Costa Gomes 						  *offload);
2529c66d156SVinicius Costa Gomes void taprio_offload_free(struct tc_taprio_qopt_offload *offload);
2539c66d156SVinicius Costa Gomes 
254d7be266aSVladimir Oltean #else
255d7be266aSVladimir Oltean 
256d7be266aSVladimir Oltean /* Reference counting */
257d7be266aSVladimir Oltean static inline struct tc_taprio_qopt_offload *
taprio_offload_get(struct tc_taprio_qopt_offload * offload)258d7be266aSVladimir Oltean taprio_offload_get(struct tc_taprio_qopt_offload *offload)
259d7be266aSVladimir Oltean {
260d7be266aSVladimir Oltean 	return NULL;
261d7be266aSVladimir Oltean }
262d7be266aSVladimir Oltean 
taprio_offload_free(struct tc_taprio_qopt_offload * offload)263d7be266aSVladimir Oltean static inline void taprio_offload_free(struct tc_taprio_qopt_offload *offload)
264d7be266aSVladimir Oltean {
265d7be266aSVladimir Oltean }
266d7be266aSVladimir Oltean 
267d7be266aSVladimir Oltean #endif
268d7be266aSVladimir Oltean 
269847cbfc0SVladimir Oltean /* Ensure skb_mstamp_ns, which might have been populated with the txtime, is
270847cbfc0SVladimir Oltean  * not mistaken for a software timestamp, because this will otherwise prevent
271847cbfc0SVladimir Oltean  * the dispatch of hardware timestamps to the socket.
272847cbfc0SVladimir Oltean  */
skb_txtime_consumed(struct sk_buff * skb)273847cbfc0SVladimir Oltean static inline void skb_txtime_consumed(struct sk_buff *skb)
274847cbfc0SVladimir Oltean {
275847cbfc0SVladimir Oltean 	skb->tstamp = ktime_set(0, 0);
276847cbfc0SVladimir Oltean }
277847cbfc0SVladimir Oltean 
278ec624fe7SPaul Blakey struct tc_skb_cb {
279ec624fe7SPaul Blakey 	struct qdisc_skb_cb qdisc_cb;
280ec624fe7SPaul Blakey 
281ec624fe7SPaul Blakey 	u16 mru;
2826f022c2dSPaul Blakey 	u8 post_ct:1;
2836f022c2dSPaul Blakey 	u8 post_ct_snat:1;
2846f022c2dSPaul Blakey 	u8 post_ct_dnat:1;
28538495958SPaul Blakey 	u16 zone; /* Only valid if post_ct = true */
286ec624fe7SPaul Blakey };
287ec624fe7SPaul Blakey 
tc_skb_cb(const struct sk_buff * skb)288ec624fe7SPaul Blakey static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb)
289ec624fe7SPaul Blakey {
290ec624fe7SPaul Blakey 	struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb;
291ec624fe7SPaul Blakey 
292ec624fe7SPaul Blakey 	BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb));
293ec624fe7SPaul Blakey 	return cb;
294ec624fe7SPaul Blakey }
295ec624fe7SPaul Blakey 
tc_qdisc_stats_dump(struct Qdisc * sch,unsigned long cl,struct qdisc_walker * arg)296d7a68e56SZhengchao Shao static inline bool tc_qdisc_stats_dump(struct Qdisc *sch,
297d7a68e56SZhengchao Shao 				       unsigned long cl,
298d7a68e56SZhengchao Shao 				       struct qdisc_walker *arg)
299d7a68e56SZhengchao Shao {
300d7a68e56SZhengchao Shao 	if (arg->count >= arg->skip && arg->fn(sch, cl, arg) < 0) {
301d7a68e56SZhengchao Shao 		arg->stop = 1;
302d7a68e56SZhengchao Shao 		return false;
303d7a68e56SZhengchao Shao 	}
304d7a68e56SZhengchao Shao 
305d7a68e56SZhengchao Shao 	arg->count++;
306d7a68e56SZhengchao Shao 	return true;
307d7a68e56SZhengchao Shao }
308d7a68e56SZhengchao Shao 
3091da177e4SLinus Torvalds #endif
310