xref: /openbmc/linux/include/net/codel.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
176e3cc12SEric Dumazet #ifndef __NET_SCHED_CODEL_H
276e3cc12SEric Dumazet #define __NET_SCHED_CODEL_H
376e3cc12SEric Dumazet 
476e3cc12SEric Dumazet /*
576e3cc12SEric Dumazet  * Codel - The Controlled-Delay Active Queue Management algorithm
676e3cc12SEric Dumazet  *
776e3cc12SEric Dumazet  *  Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
876e3cc12SEric Dumazet  *  Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
976e3cc12SEric Dumazet  *  Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
1080ba92faSEric Dumazet  *  Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
1176e3cc12SEric Dumazet  *
1276e3cc12SEric Dumazet  * Redistribution and use in source and binary forms, with or without
1376e3cc12SEric Dumazet  * modification, are permitted provided that the following conditions
1476e3cc12SEric Dumazet  * are met:
1576e3cc12SEric Dumazet  * 1. Redistributions of source code must retain the above copyright
1676e3cc12SEric Dumazet  *    notice, this list of conditions, and the following disclaimer,
1776e3cc12SEric Dumazet  *    without modification.
1876e3cc12SEric Dumazet  * 2. Redistributions in binary form must reproduce the above copyright
1976e3cc12SEric Dumazet  *    notice, this list of conditions and the following disclaimer in the
2076e3cc12SEric Dumazet  *    documentation and/or other materials provided with the distribution.
2176e3cc12SEric Dumazet  * 3. The names of the authors may not be used to endorse or promote products
2276e3cc12SEric Dumazet  *    derived from this software without specific prior written permission.
2376e3cc12SEric Dumazet  *
2476e3cc12SEric Dumazet  * Alternatively, provided that this notice is retained in full, this
2576e3cc12SEric Dumazet  * software may be distributed under the terms of the GNU General
2676e3cc12SEric Dumazet  * Public License ("GPL") version 2, in which case the provisions of the
2776e3cc12SEric Dumazet  * GPL apply INSTEAD OF those given above.
2876e3cc12SEric Dumazet  *
2976e3cc12SEric Dumazet  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3076e3cc12SEric Dumazet  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3176e3cc12SEric Dumazet  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3276e3cc12SEric Dumazet  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3376e3cc12SEric Dumazet  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3476e3cc12SEric Dumazet  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3576e3cc12SEric Dumazet  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3676e3cc12SEric Dumazet  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3776e3cc12SEric Dumazet  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3876e3cc12SEric Dumazet  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3976e3cc12SEric Dumazet  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4076e3cc12SEric Dumazet  * DAMAGE.
4176e3cc12SEric Dumazet  *
4276e3cc12SEric Dumazet  */
4376e3cc12SEric Dumazet 
4476e3cc12SEric Dumazet #include <linux/types.h>
4576e3cc12SEric Dumazet #include <linux/ktime.h>
4676e3cc12SEric Dumazet #include <linux/skbuff.h>
4776e3cc12SEric Dumazet 
4876e3cc12SEric Dumazet /* Controlling Queue Delay (CoDel) algorithm
4976e3cc12SEric Dumazet  * =========================================
5076e3cc12SEric Dumazet  * Source : Kathleen Nichols and Van Jacobson
5176e3cc12SEric Dumazet  * http://queue.acm.org/detail.cfm?id=2209336
5276e3cc12SEric Dumazet  *
5376e3cc12SEric Dumazet  * Implemented on linux by Dave Taht and Eric Dumazet
5476e3cc12SEric Dumazet  */
5576e3cc12SEric Dumazet 
5676e3cc12SEric Dumazet 
5776e3cc12SEric Dumazet /* CoDel uses a 1024 nsec clock, encoded in u32
5876e3cc12SEric Dumazet  * This gives a range of 2199 seconds, because of signed compares
5976e3cc12SEric Dumazet  */
6076e3cc12SEric Dumazet typedef u32 codel_time_t;
6176e3cc12SEric Dumazet typedef s32 codel_tdiff_t;
6276e3cc12SEric Dumazet #define CODEL_SHIFT 10
6376e3cc12SEric Dumazet #define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
6476e3cc12SEric Dumazet 
codel_get_time(void)6576e3cc12SEric Dumazet static inline codel_time_t codel_get_time(void)
6676e3cc12SEric Dumazet {
67d2de875cSEric Dumazet 	u64 ns = ktime_get_ns();
6876e3cc12SEric Dumazet 
6976e3cc12SEric Dumazet 	return ns >> CODEL_SHIFT;
7076e3cc12SEric Dumazet }
7176e3cc12SEric Dumazet 
721ba3aab3SJesper Dangaard Brouer /* Dealing with timer wrapping, according to RFC 1982, as desc in wikipedia:
731ba3aab3SJesper Dangaard Brouer  *  https://en.wikipedia.org/wiki/Serial_number_arithmetic#General_Solution
741ba3aab3SJesper Dangaard Brouer  * codel_time_after(a,b) returns true if the time a is after time b.
751ba3aab3SJesper Dangaard Brouer  */
761ba3aab3SJesper Dangaard Brouer #define codel_time_after(a, b)						\
771ba3aab3SJesper Dangaard Brouer 	(typecheck(codel_time_t, a) &&					\
781ba3aab3SJesper Dangaard Brouer 	 typecheck(codel_time_t, b) &&					\
791ba3aab3SJesper Dangaard Brouer 	 ((s32)((a) - (b)) > 0))
801ba3aab3SJesper Dangaard Brouer #define codel_time_before(a, b) 	codel_time_after(b, a)
811ba3aab3SJesper Dangaard Brouer 
821ba3aab3SJesper Dangaard Brouer #define codel_time_after_eq(a, b)					\
831ba3aab3SJesper Dangaard Brouer 	(typecheck(codel_time_t, a) &&					\
841ba3aab3SJesper Dangaard Brouer 	 typecheck(codel_time_t, b) &&					\
851ba3aab3SJesper Dangaard Brouer 	 ((s32)((a) - (b)) >= 0))
861ba3aab3SJesper Dangaard Brouer #define codel_time_before_eq(a, b)	codel_time_after_eq(b, a)
8776e3cc12SEric Dumazet 
codel_time_to_us(codel_time_t val)8876e3cc12SEric Dumazet static inline u32 codel_time_to_us(codel_time_t val)
8976e3cc12SEric Dumazet {
9076e3cc12SEric Dumazet 	u64 valns = ((u64)val << CODEL_SHIFT);
9176e3cc12SEric Dumazet 
9276e3cc12SEric Dumazet 	do_div(valns, NSEC_PER_USEC);
9376e3cc12SEric Dumazet 	return (u32)valns;
9476e3cc12SEric Dumazet }
9576e3cc12SEric Dumazet 
9676e3cc12SEric Dumazet /**
9776e3cc12SEric Dumazet  * struct codel_params - contains codel parameters
9876e3cc12SEric Dumazet  * @target:	target queue size (in time units)
9980ba92faSEric Dumazet  * @ce_threshold:  threshold for marking packets with ECN CE
10076e3cc12SEric Dumazet  * @interval:	width of moving time window
101a5d28090SEric Dumazet  * @mtu:	device mtu, or minimal queue backlog in bytes.
10276e3cc12SEric Dumazet  * @ecn:	is Explicit Congestion Notification enabled
103dfcb63ceSToke Høiland-Jørgensen  * @ce_threshold_selector: apply ce_threshold to packets matching this value
104dfcb63ceSToke Høiland-Jørgensen  *                         in the diffserv/ECN byte of the IP header
105dfcb63ceSToke Høiland-Jørgensen  * @ce_threshold_mask: mask to apply to ce_threshold_selector comparison
10676e3cc12SEric Dumazet  */
10776e3cc12SEric Dumazet struct codel_params {
10876e3cc12SEric Dumazet 	codel_time_t	target;
10980ba92faSEric Dumazet 	codel_time_t	ce_threshold;
11076e3cc12SEric Dumazet 	codel_time_t	interval;
111a5d28090SEric Dumazet 	u32		mtu;
11276e3cc12SEric Dumazet 	bool		ecn;
113dfcb63ceSToke Høiland-Jørgensen 	u8		ce_threshold_selector;
114dfcb63ceSToke Høiland-Jørgensen 	u8		ce_threshold_mask;
11576e3cc12SEric Dumazet };
11676e3cc12SEric Dumazet 
11776e3cc12SEric Dumazet /**
11876e3cc12SEric Dumazet  * struct codel_vars - contains codel variables
11976e3cc12SEric Dumazet  * @count:		how many drops we've done since the last time we
12076e3cc12SEric Dumazet  *			entered dropping state
12176e3cc12SEric Dumazet  * @lastcount:		count at entry to dropping state
12276e3cc12SEric Dumazet  * @dropping:		set to true if in dropping state
123536edd67SEric Dumazet  * @rec_inv_sqrt:	reciprocal value of sqrt(count) >> 1
12476e3cc12SEric Dumazet  * @first_above_time:	when we went (or will go) continuously above target
12576e3cc12SEric Dumazet  *			for interval
12676e3cc12SEric Dumazet  * @drop_next:		time to drop next packet, or when we dropped last
12776e3cc12SEric Dumazet  * @ldelay:		sojourn time of last dequeued packet
12876e3cc12SEric Dumazet  */
12976e3cc12SEric Dumazet struct codel_vars {
13076e3cc12SEric Dumazet 	u32		count;
13176e3cc12SEric Dumazet 	u32		lastcount;
1326ff272c9SEric Dumazet 	bool		dropping;
1336ff272c9SEric Dumazet 	u16		rec_inv_sqrt;
13476e3cc12SEric Dumazet 	codel_time_t	first_above_time;
13576e3cc12SEric Dumazet 	codel_time_t	drop_next;
13676e3cc12SEric Dumazet 	codel_time_t	ldelay;
13776e3cc12SEric Dumazet };
13876e3cc12SEric Dumazet 
1396ff272c9SEric Dumazet #define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
1406ff272c9SEric Dumazet /* needed shift to get a Q0.32 number from rec_inv_sqrt */
1416ff272c9SEric Dumazet #define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
1426ff272c9SEric Dumazet 
14376e3cc12SEric Dumazet /**
14476e3cc12SEric Dumazet  * struct codel_stats - contains codel shared variables and stats
14576e3cc12SEric Dumazet  * @maxpacket:	largest packet we've seen so far
14676e3cc12SEric Dumazet  * @drop_count:	temp count of dropped packets in dequeue()
1472ccccf5fSWANG Cong  * @drop_len:	bytes of dropped packets in dequeue()
148*cfe57122SRandy Dunlap  * @ecn_mark:	number of packets we ECN marked instead of dropping
149*cfe57122SRandy Dunlap  * @ce_mark:	number of packets CE marked because sojourn time was above ce_threshold
15076e3cc12SEric Dumazet  */
15176e3cc12SEric Dumazet struct codel_stats {
15276e3cc12SEric Dumazet 	u32		maxpacket;
15376e3cc12SEric Dumazet 	u32		drop_count;
1542ccccf5fSWANG Cong 	u32		drop_len;
15576e3cc12SEric Dumazet 	u32		ecn_mark;
15680ba92faSEric Dumazet 	u32		ce_mark;
15776e3cc12SEric Dumazet };
15876e3cc12SEric Dumazet 
15980ba92faSEric Dumazet #define CODEL_DISABLED_THRESHOLD INT_MAX
16080ba92faSEric Dumazet 
16179bdc4c8SMichal Kazior typedef u32 (*codel_skb_len_t)(const struct sk_buff *skb);
16279bdc4c8SMichal Kazior typedef codel_time_t (*codel_skb_time_t)(const struct sk_buff *skb);
16379bdc4c8SMichal Kazior typedef void (*codel_skb_drop_t)(struct sk_buff *skb, void *ctx);
16479bdc4c8SMichal Kazior typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
16579bdc4c8SMichal Kazior 						void *ctx);
16679bdc4c8SMichal Kazior 
16776e3cc12SEric Dumazet #endif
168