18c2ecf20Sopenharmony_ci#ifndef __NET_SCHED_CODEL_H 28c2ecf20Sopenharmony_ci#define __NET_SCHED_CODEL_H 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * Codel - The Controlled-Delay Active Queue Management algorithm 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com> 88c2ecf20Sopenharmony_ci * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net> 98c2ecf20Sopenharmony_ci * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net> 108c2ecf20Sopenharmony_ci * Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com> 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 138c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 148c2ecf20Sopenharmony_ci * are met: 158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 168c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 178c2ecf20Sopenharmony_ci * without modification. 188c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 198c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 208c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 218c2ecf20Sopenharmony_ci * 3. The names of the authors may not be used to endorse or promote products 228c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Alternatively, provided that this notice is retained in full, this 258c2ecf20Sopenharmony_ci * software may be distributed under the terms of the GNU General 268c2ecf20Sopenharmony_ci * Public License ("GPL") version 2, in which case the provisions of the 278c2ecf20Sopenharmony_ci * GPL apply INSTEAD OF those given above. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 308c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 318c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 328c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 338c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 348c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 358c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 368c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 378c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 388c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 398c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 408c2ecf20Sopenharmony_ci * DAMAGE. 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <linux/types.h> 458c2ecf20Sopenharmony_ci#include <linux/ktime.h> 468c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 478c2ecf20Sopenharmony_ci#include <net/pkt_sched.h> 488c2ecf20Sopenharmony_ci#include <net/inet_ecn.h> 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* Controlling Queue Delay (CoDel) algorithm 518c2ecf20Sopenharmony_ci * ========================================= 528c2ecf20Sopenharmony_ci * Source : Kathleen Nichols and Van Jacobson 538c2ecf20Sopenharmony_ci * http://queue.acm.org/detail.cfm?id=2209336 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * Implemented on linux by Dave Taht and Eric Dumazet 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* CoDel uses a 1024 nsec clock, encoded in u32 608c2ecf20Sopenharmony_ci * This gives a range of 2199 seconds, because of signed compares 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_citypedef u32 codel_time_t; 638c2ecf20Sopenharmony_citypedef s32 codel_tdiff_t; 648c2ecf20Sopenharmony_ci#define CODEL_SHIFT 10 658c2ecf20Sopenharmony_ci#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic inline codel_time_t codel_get_time(void) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci u64 ns = ktime_get_ns(); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return ns >> CODEL_SHIFT; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* Dealing with timer wrapping, according to RFC 1982, as desc in wikipedia: 758c2ecf20Sopenharmony_ci * https://en.wikipedia.org/wiki/Serial_number_arithmetic#General_Solution 768c2ecf20Sopenharmony_ci * codel_time_after(a,b) returns true if the time a is after time b. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci#define codel_time_after(a, b) \ 798c2ecf20Sopenharmony_ci (typecheck(codel_time_t, a) && \ 808c2ecf20Sopenharmony_ci typecheck(codel_time_t, b) && \ 818c2ecf20Sopenharmony_ci ((s32)((a) - (b)) > 0)) 828c2ecf20Sopenharmony_ci#define codel_time_before(a, b) codel_time_after(b, a) 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define codel_time_after_eq(a, b) \ 858c2ecf20Sopenharmony_ci (typecheck(codel_time_t, a) && \ 868c2ecf20Sopenharmony_ci typecheck(codel_time_t, b) && \ 878c2ecf20Sopenharmony_ci ((s32)((a) - (b)) >= 0)) 888c2ecf20Sopenharmony_ci#define codel_time_before_eq(a, b) codel_time_after_eq(b, a) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline u32 codel_time_to_us(codel_time_t val) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci u64 valns = ((u64)val << CODEL_SHIFT); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci do_div(valns, NSEC_PER_USEC); 958c2ecf20Sopenharmony_ci return (u32)valns; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/** 998c2ecf20Sopenharmony_ci * struct codel_params - contains codel parameters 1008c2ecf20Sopenharmony_ci * @target: target queue size (in time units) 1018c2ecf20Sopenharmony_ci * @ce_threshold: threshold for marking packets with ECN CE 1028c2ecf20Sopenharmony_ci * @interval: width of moving time window 1038c2ecf20Sopenharmony_ci * @mtu: device mtu, or minimal queue backlog in bytes. 1048c2ecf20Sopenharmony_ci * @ecn: is Explicit Congestion Notification enabled 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_cistruct codel_params { 1078c2ecf20Sopenharmony_ci codel_time_t target; 1088c2ecf20Sopenharmony_ci codel_time_t ce_threshold; 1098c2ecf20Sopenharmony_ci codel_time_t interval; 1108c2ecf20Sopenharmony_ci u32 mtu; 1118c2ecf20Sopenharmony_ci bool ecn; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/** 1158c2ecf20Sopenharmony_ci * struct codel_vars - contains codel variables 1168c2ecf20Sopenharmony_ci * @count: how many drops we've done since the last time we 1178c2ecf20Sopenharmony_ci * entered dropping state 1188c2ecf20Sopenharmony_ci * @lastcount: count at entry to dropping state 1198c2ecf20Sopenharmony_ci * @dropping: set to true if in dropping state 1208c2ecf20Sopenharmony_ci * @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1 1218c2ecf20Sopenharmony_ci * @first_above_time: when we went (or will go) continuously above target 1228c2ecf20Sopenharmony_ci * for interval 1238c2ecf20Sopenharmony_ci * @drop_next: time to drop next packet, or when we dropped last 1248c2ecf20Sopenharmony_ci * @ldelay: sojourn time of last dequeued packet 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistruct codel_vars { 1278c2ecf20Sopenharmony_ci u32 count; 1288c2ecf20Sopenharmony_ci u32 lastcount; 1298c2ecf20Sopenharmony_ci bool dropping; 1308c2ecf20Sopenharmony_ci u16 rec_inv_sqrt; 1318c2ecf20Sopenharmony_ci codel_time_t first_above_time; 1328c2ecf20Sopenharmony_ci codel_time_t drop_next; 1338c2ecf20Sopenharmony_ci codel_time_t ldelay; 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */ 1378c2ecf20Sopenharmony_ci/* needed shift to get a Q0.32 number from rec_inv_sqrt */ 1388c2ecf20Sopenharmony_ci#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS) 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/** 1418c2ecf20Sopenharmony_ci * struct codel_stats - contains codel shared variables and stats 1428c2ecf20Sopenharmony_ci * @maxpacket: largest packet we've seen so far 1438c2ecf20Sopenharmony_ci * @drop_count: temp count of dropped packets in dequeue() 1448c2ecf20Sopenharmony_ci * @drop_len: bytes of dropped packets in dequeue() 1458c2ecf20Sopenharmony_ci * ecn_mark: number of packets we ECN marked instead of dropping 1468c2ecf20Sopenharmony_ci * ce_mark: number of packets CE marked because sojourn time was above ce_threshold 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_cistruct codel_stats { 1498c2ecf20Sopenharmony_ci u32 maxpacket; 1508c2ecf20Sopenharmony_ci u32 drop_count; 1518c2ecf20Sopenharmony_ci u32 drop_len; 1528c2ecf20Sopenharmony_ci u32 ecn_mark; 1538c2ecf20Sopenharmony_ci u32 ce_mark; 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define CODEL_DISABLED_THRESHOLD INT_MAX 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_citypedef u32 (*codel_skb_len_t)(const struct sk_buff *skb); 1598c2ecf20Sopenharmony_citypedef codel_time_t (*codel_skb_time_t)(const struct sk_buff *skb); 1608c2ecf20Sopenharmony_citypedef void (*codel_skb_drop_t)(struct sk_buff *skb, void *ctx); 1618c2ecf20Sopenharmony_citypedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars, 1628c2ecf20Sopenharmony_ci void *ctx); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#endif 165