^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #ifndef __NET_SCHED_CODEL_IMPL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #define __NET_SCHED_CODEL_IMPL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Codel - The Controlled-Delay Active Queue Management algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * notice, this list of conditions, and the following disclaimer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * without modification.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 2. Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * notice, this list of conditions and the following disclaimer in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * documentation and/or other materials provided with the distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * 3. The names of the authors may not be used to endorse or promote products
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * derived from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Alternatively, provided that this notice is retained in full, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * software may be distributed under the terms of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Public License ("GPL") version 2, in which case the provisions of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * GPL apply INSTEAD OF those given above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Controlling Queue Delay (CoDel) algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * =========================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Source : Kathleen Nichols and Van Jacobson
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * http://queue.acm.org/detail.cfm?id=2209336
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Implemented on linux by Dave Taht and Eric Dumazet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static void codel_params_init(struct codel_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) params->interval = MS2TIME(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) params->target = MS2TIME(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) params->ce_threshold = CODEL_DISABLED_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) params->ecn = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static void codel_vars_init(struct codel_vars *vars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) memset(vars, 0, sizeof(*vars));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void codel_stats_init(struct codel_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) stats->maxpacket = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void codel_Newton_step(struct codel_vars *vars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) val >>= 2; /* avoid overflow in following multiply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) val = (val * invsqrt) >> (32 - 2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * CoDel control_law is t + interval/sqrt(count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * both sqrt() and divide operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static codel_time_t codel_control_law(codel_time_t t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) codel_time_t interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 rec_inv_sqrt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static bool codel_should_drop(const struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct codel_vars *vars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct codel_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct codel_stats *stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) codel_skb_len_t skb_len_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) codel_skb_time_t skb_time_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 *backlog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) codel_time_t now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) bool ok_to_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 skb_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) vars->first_above_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) skb_len = skb_len_func(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) vars->ldelay = now - skb_time_func(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (unlikely(skb_len > stats->maxpacket))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) stats->maxpacket = skb_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (codel_time_before(vars->ldelay, params->target) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *backlog <= params->mtu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* went below - stay below for at least interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) vars->first_above_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ok_to_drop = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (vars->first_above_time == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* just went above from below. If we stay above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * for at least interval we'll say it's ok to drop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) vars->first_above_time = now + params->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) } else if (codel_time_after(now, vars->first_above_time)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ok_to_drop = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return ok_to_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct sk_buff *codel_dequeue(void *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u32 *backlog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct codel_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct codel_vars *vars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct codel_stats *stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) codel_skb_len_t skb_len_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) codel_skb_time_t skb_time_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) codel_skb_drop_t drop_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) codel_skb_dequeue_t dequeue_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct sk_buff *skb = dequeue_func(vars, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) codel_time_t now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bool drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) vars->dropping = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) now = codel_get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) drop = codel_should_drop(skb, ctx, vars, params, stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) skb_len_func, skb_time_func, backlog, now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (vars->dropping) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!drop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* sojourn time below target - leave dropping state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) vars->dropping = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } else if (codel_time_after_eq(now, vars->drop_next)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* It's time for the next drop. Drop the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * packet and dequeue the next. The dequeue might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * take us out of dropping state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * If not, schedule the next drop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * A large backlog might result in drop rates so high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * that the next drop should happen now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * hence the while loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) while (vars->dropping &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) codel_time_after_eq(now, vars->drop_next)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) vars->count++; /* dont care of possible wrap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * since there is no more divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) codel_Newton_step(vars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (params->ecn && INET_ECN_set_ce(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) stats->ecn_mark++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) vars->drop_next =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) codel_control_law(vars->drop_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) params->interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) vars->rec_inv_sqrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) stats->drop_len += skb_len_func(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) drop_func(skb, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) stats->drop_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) skb = dequeue_func(vars, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!codel_should_drop(skb, ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) vars, params, stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) skb_len_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) skb_time_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) backlog, now)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* leave dropping state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) vars->dropping = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* and schedule the next drop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) vars->drop_next =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) codel_control_law(vars->drop_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) params->interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) vars->rec_inv_sqrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) } else if (drop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (params->ecn && INET_ECN_set_ce(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) stats->ecn_mark++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) stats->drop_len += skb_len_func(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) drop_func(skb, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) stats->drop_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) skb = dequeue_func(vars, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) drop = codel_should_drop(skb, ctx, vars, params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) stats, skb_len_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) skb_time_func, backlog, now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) vars->dropping = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* if min went above target close to when we last went below it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * assume that the drop rate that controlled the queue on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * last cycle is a good starting point to control it now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) delta = vars->count - vars->lastcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (delta > 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) codel_time_before(now - vars->drop_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 16 * params->interval)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) vars->count = delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* we dont care if rec_inv_sqrt approximation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * is not very precise :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Next Newton steps will correct it quadratically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) codel_Newton_step(vars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) vars->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) vars->lastcount = vars->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) vars->drop_next = codel_control_law(now, params->interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) vars->rec_inv_sqrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (skb && codel_time_after(vars->ldelay, params->ce_threshold) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) INET_ECN_set_ce(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) stats->ce_mark++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) #endif