192a0637fSLawrence Stewart /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro F. Giffuni * 492a0637fSLawrence Stewart * Copyright (c) 2009-2013 592a0637fSLawrence Stewart * Swinburne University of Technology, Melbourne, Australia 692a0637fSLawrence Stewart * All rights reserved. 792a0637fSLawrence Stewart * 892a0637fSLawrence Stewart * This software was developed at the Centre for Advanced Internet 992a0637fSLawrence Stewart * Architectures, Swinburne University of Technology, by David Hayes, made 1092a0637fSLawrence Stewart * possible in part by a gift from The Cisco University Research Program Fund, 1192a0637fSLawrence Stewart * a corporate advised fund of Silicon Valley Community Foundation. Development 1292a0637fSLawrence Stewart * and testing were further assisted by a grant from the FreeBSD Foundation. 1392a0637fSLawrence Stewart * 1492a0637fSLawrence Stewart * Redistribution and use in source and binary forms, with or without 1592a0637fSLawrence Stewart * modification, are permitted provided that the following conditions 1692a0637fSLawrence Stewart * are met: 1792a0637fSLawrence Stewart * 1. Redistributions of source code must retain the above copyright 1892a0637fSLawrence Stewart * notice, this list of conditions and the following disclaimer. 1992a0637fSLawrence Stewart * 2. Redistributions in binary form must reproduce the above copyright 2092a0637fSLawrence Stewart * notice, this list of conditions and the following disclaimer in the 2192a0637fSLawrence Stewart * documentation and/or other materials provided with the distribution. 2292a0637fSLawrence Stewart * 2392a0637fSLawrence Stewart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2492a0637fSLawrence Stewart * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2592a0637fSLawrence Stewart * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2692a0637fSLawrence Stewart * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2792a0637fSLawrence Stewart * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2892a0637fSLawrence Stewart * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2992a0637fSLawrence Stewart * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3092a0637fSLawrence Stewart * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3192a0637fSLawrence Stewart * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3292a0637fSLawrence Stewart * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3392a0637fSLawrence Stewart * SUCH DAMAGE. 3492a0637fSLawrence Stewart */ 3592a0637fSLawrence Stewart 3692a0637fSLawrence Stewart /* 3792a0637fSLawrence Stewart * CAIA Delay-Gradient (CDG) congestion control algorithm 3892a0637fSLawrence Stewart * 3992a0637fSLawrence Stewart * An implemention of the delay-gradient congestion control algorithm proposed 4092a0637fSLawrence Stewart * in the following paper: 4192a0637fSLawrence Stewart * 4292a0637fSLawrence Stewart * D. A. Hayes and G. Armitage, "Revisiting TCP Congestion Control using Delay 4392a0637fSLawrence Stewart * Gradients", in IFIP Networking, Valencia, Spain, 9-13 May 2011. 4492a0637fSLawrence Stewart * 4592a0637fSLawrence Stewart * Developed as part of the NewTCP research project at Swinburne University of 4692a0637fSLawrence Stewart * Technology's Centre for Advanced Internet Architectures, Melbourne, 4792a0637fSLawrence Stewart * Australia. More details are available at: 4892a0637fSLawrence Stewart * http://caia.swin.edu.au/urp/newtcp/ 4992a0637fSLawrence Stewart */ 5092a0637fSLawrence Stewart 5192a0637fSLawrence Stewart #include <sys/param.h> 5292a0637fSLawrence Stewart #include <sys/hhook.h> 5392a0637fSLawrence Stewart #include <sys/kernel.h> 5492a0637fSLawrence Stewart #include <sys/khelp.h> 5592a0637fSLawrence Stewart #include <sys/limits.h> 5692a0637fSLawrence Stewart #include <sys/lock.h> 5792a0637fSLawrence Stewart #include <sys/malloc.h> 5892a0637fSLawrence Stewart #include <sys/module.h> 5992a0637fSLawrence Stewart #include <sys/queue.h> 60674956e1SHenrich Hartzer #include <sys/prng.h> 6192a0637fSLawrence Stewart #include <sys/socket.h> 6292a0637fSLawrence Stewart #include <sys/socketvar.h> 6392a0637fSLawrence Stewart #include <sys/sysctl.h> 6492a0637fSLawrence Stewart #include <sys/systm.h> 6592a0637fSLawrence Stewart 6692a0637fSLawrence Stewart #include <net/vnet.h> 6792a0637fSLawrence Stewart 68b8d60729SRandall Stewart #include <net/route.h> 69b8d60729SRandall Stewart #include <net/route/nhop.h> 70b8d60729SRandall Stewart 71b8d60729SRandall Stewart #include <netinet/in_pcb.h> 722de3e790SGleb Smirnoff #include <netinet/tcp.h> 7392a0637fSLawrence Stewart #include <netinet/tcp_seq.h> 7492a0637fSLawrence Stewart #include <netinet/tcp_timer.h> 7592a0637fSLawrence Stewart #include <netinet/tcp_var.h> 764644fda3SGleb Smirnoff #include <netinet/cc/cc.h> 7792a0637fSLawrence Stewart #include <netinet/cc/cc_module.h> 7892a0637fSLawrence Stewart 7992a0637fSLawrence Stewart #include <netinet/khelp/h_ertt.h> 8092a0637fSLawrence Stewart 8192a0637fSLawrence Stewart #include <vm/uma.h> 8292a0637fSLawrence Stewart 8392a0637fSLawrence Stewart #define CDG_VERSION "0.1" 8492a0637fSLawrence Stewart 8592a0637fSLawrence Stewart /* Private delay-gradient induced congestion control signal. */ 8692a0637fSLawrence Stewart #define CC_CDG_DELAY 0x01000000 8792a0637fSLawrence Stewart 8892a0637fSLawrence Stewart /* NewReno window deflation factor on loss (as a percentage). */ 8992a0637fSLawrence Stewart #define RENO_BETA 50 9092a0637fSLawrence Stewart 9192a0637fSLawrence Stewart /* Queue states. */ 9292a0637fSLawrence Stewart #define CDG_Q_EMPTY 1 9392a0637fSLawrence Stewart #define CDG_Q_RISING 2 9492a0637fSLawrence Stewart #define CDG_Q_FALLING 3 9592a0637fSLawrence Stewart #define CDG_Q_FULL 4 9692a0637fSLawrence Stewart #define CDG_Q_UNKNOWN 9999 9792a0637fSLawrence Stewart 9892a0637fSLawrence Stewart /* Number of bit shifts used in probexp lookup table. */ 9992a0637fSLawrence Stewart #define EXP_PREC 15 10092a0637fSLawrence Stewart 10192a0637fSLawrence Stewart /* Largest gradient represented in probexp lookup table. */ 10292a0637fSLawrence Stewart #define MAXGRAD 5 10392a0637fSLawrence Stewart 10492a0637fSLawrence Stewart /* 10592a0637fSLawrence Stewart * Delay Precision Enhance - number of bit shifts used for qtrend related 10692a0637fSLawrence Stewart * integer arithmetic precision. 10792a0637fSLawrence Stewart */ 10892a0637fSLawrence Stewart #define D_P_E 7 10992a0637fSLawrence Stewart 11092a0637fSLawrence Stewart struct qdiff_sample { 11192a0637fSLawrence Stewart long qdiff; 11292a0637fSLawrence Stewart STAILQ_ENTRY(qdiff_sample) qdiff_lnk; 11392a0637fSLawrence Stewart }; 11492a0637fSLawrence Stewart 11592a0637fSLawrence Stewart struct cdg { 11692a0637fSLawrence Stewart long max_qtrend; 11792a0637fSLawrence Stewart long min_qtrend; 11892a0637fSLawrence Stewart STAILQ_HEAD(minrtts_head, qdiff_sample) qdiffmin_q; 11992a0637fSLawrence Stewart STAILQ_HEAD(maxrtts_head, qdiff_sample) qdiffmax_q; 12092a0637fSLawrence Stewart long window_incr; 12192a0637fSLawrence Stewart /* rttcount for window increase when in congestion avoidance */ 12292a0637fSLawrence Stewart long rtt_count; 12392a0637fSLawrence Stewart /* maximum measured rtt within an rtt period */ 12492a0637fSLawrence Stewart int maxrtt_in_rtt; 12592a0637fSLawrence Stewart /* maximum measured rtt within prev rtt period */ 12692a0637fSLawrence Stewart int maxrtt_in_prevrtt; 12792a0637fSLawrence Stewart /* minimum measured rtt within an rtt period */ 12892a0637fSLawrence Stewart int minrtt_in_rtt; 12992a0637fSLawrence Stewart /* minimum measured rtt within prev rtt period */ 13092a0637fSLawrence Stewart int minrtt_in_prevrtt; 13192a0637fSLawrence Stewart /* consecutive congestion episode counter */ 13292a0637fSLawrence Stewart uint32_t consec_cong_cnt; 13392a0637fSLawrence Stewart /* when tracking a new reno type loss window */ 13492a0637fSLawrence Stewart uint32_t shadow_w; 13592a0637fSLawrence Stewart /* maximum number of samples in the moving average queue */ 13692a0637fSLawrence Stewart int sample_q_size; 13792a0637fSLawrence Stewart /* number of samples in the moving average queue */ 13892a0637fSLawrence Stewart int num_samples; 13992a0637fSLawrence Stewart /* estimate of the queue state of the path */ 14092a0637fSLawrence Stewart int queue_state; 14192a0637fSLawrence Stewart }; 14292a0637fSLawrence Stewart 14392a0637fSLawrence Stewart /* 14492a0637fSLawrence Stewart * Lookup table for: 14592a0637fSLawrence Stewart * (1 - exp(-x)) << EXP_PREC, where x = [0,MAXGRAD] in 2^-7 increments 14692a0637fSLawrence Stewart * 14792a0637fSLawrence Stewart * Note: probexp[0] is set to 10 (not 0) as a safety for very low increase 14892a0637fSLawrence Stewart * gradients. 14992a0637fSLawrence Stewart */ 15092a0637fSLawrence Stewart static const int probexp[641] = { 15192a0637fSLawrence Stewart 10,255,508,759,1008,1255,1501,1744,1985,2225,2463,2698,2932,3165,3395,3624, 15292a0637fSLawrence Stewart 3850,4075,4299,4520,4740,4958,5175,5389,5602,5814,6024,6232,6438,6643,6846, 15392a0637fSLawrence Stewart 7048,7248,7447,7644,7839,8033,8226,8417,8606,8794,8981,9166,9350,9532,9713, 15492a0637fSLawrence Stewart 9892,10070,10247,10422,10596,10769,10940,11110,11278,11445,11611,11776,11939, 15592a0637fSLawrence Stewart 12101,12262,12422,12580,12737,12893,13048,13201,13354,13505,13655,13803,13951, 15692a0637fSLawrence Stewart 14097,14243,14387,14530,14672,14813,14952,15091,15229,15365,15500,15635,15768, 15792a0637fSLawrence Stewart 15900,16032,16162,16291,16419,16547,16673,16798,16922,17046,17168,17289,17410, 15892a0637fSLawrence Stewart 17529,17648,17766,17882,17998,18113,18227,18340,18453,18564,18675,18784,18893, 15992a0637fSLawrence Stewart 19001,19108,19215,19320,19425,19529,19632,19734,19835,19936,20036,20135,20233, 16092a0637fSLawrence Stewart 20331,20427,20523,20619,20713,20807,20900,20993,21084,21175,21265,21355,21444, 16192a0637fSLawrence Stewart 21532,21619,21706,21792,21878,21962,22046,22130,22213,22295,22376,22457,22537, 16292a0637fSLawrence Stewart 22617,22696,22774,22852,22929,23006,23082,23157,23232,23306,23380,23453,23525, 16392a0637fSLawrence Stewart 23597,23669,23739,23810,23879,23949,24017,24085,24153,24220,24286,24352,24418, 16492a0637fSLawrence Stewart 24483,24547,24611,24675,24738,24800,24862,24924,24985,25045,25106,25165,25224, 16592a0637fSLawrence Stewart 25283,25341,25399,25456,25513,25570,25626,25681,25737,25791,25846,25899,25953, 16692a0637fSLawrence Stewart 26006,26059,26111,26163,26214,26265,26316,26366,26416,26465,26514,26563,26611, 16792a0637fSLawrence Stewart 26659,26707,26754,26801,26847,26893,26939,26984,27029,27074,27118,27162,27206, 16892a0637fSLawrence Stewart 27249,27292,27335,27377,27419,27460,27502,27543,27583,27624,27664,27703,27743, 16992a0637fSLawrence Stewart 27782,27821,27859,27897,27935,27973,28010,28047,28084,28121,28157,28193,28228, 17092a0637fSLawrence Stewart 28263,28299,28333,28368,28402,28436,28470,28503,28536,28569,28602,28634,28667, 17192a0637fSLawrence Stewart 28699,28730,28762,28793,28824,28854,28885,28915,28945,28975,29004,29034,29063, 17292a0637fSLawrence Stewart 29092,29120,29149,29177,29205,29232,29260,29287,29314,29341,29368,29394,29421, 17392a0637fSLawrence Stewart 29447,29472,29498,29524,29549,29574,29599,29623,29648,29672,29696,29720,29744, 17492a0637fSLawrence Stewart 29767,29791,29814,29837,29860,29882,29905,29927,29949,29971,29993,30014,30036, 17592a0637fSLawrence Stewart 30057,30078,30099,30120,30141,30161,30181,30201,30221,30241,30261,30280,30300, 17692a0637fSLawrence Stewart 30319,30338,30357,30376,30394,30413,30431,30449,30467,30485,30503,30521,30538, 17792a0637fSLawrence Stewart 30555,30573,30590,30607,30624,30640,30657,30673,30690,30706,30722,30738,30753, 17892a0637fSLawrence Stewart 30769,30785,30800,30815,30831,30846,30861,30876,30890,30905,30919,30934,30948, 17992a0637fSLawrence Stewart 30962,30976,30990,31004,31018,31031,31045,31058,31072,31085,31098,31111,31124, 18092a0637fSLawrence Stewart 31137,31149,31162,31174,31187,31199,31211,31223,31235,31247,31259,31271,31283, 18192a0637fSLawrence Stewart 31294,31306,31317,31328,31339,31351,31362,31373,31383,31394,31405,31416,31426, 18292a0637fSLawrence Stewart 31436,31447,31457,31467,31477,31487,31497,31507,31517,31527,31537,31546,31556, 18392a0637fSLawrence Stewart 31565,31574,31584,31593,31602,31611,31620,31629,31638,31647,31655,31664,31673, 18492a0637fSLawrence Stewart 31681,31690,31698,31706,31715,31723,31731,31739,31747,31755,31763,31771,31778, 18592a0637fSLawrence Stewart 31786,31794,31801,31809,31816,31824,31831,31838,31846,31853,31860,31867,31874, 18692a0637fSLawrence Stewart 31881,31888,31895,31902,31908,31915,31922,31928,31935,31941,31948,31954,31960, 18792a0637fSLawrence Stewart 31967,31973,31979,31985,31991,31997,32003,32009,32015,32021,32027,32033,32038, 18892a0637fSLawrence Stewart 32044,32050,32055,32061,32066,32072,32077,32083,32088,32093,32098,32104,32109, 18992a0637fSLawrence Stewart 32114,32119,32124,32129,32134,32139,32144,32149,32154,32158,32163,32168,32173, 19092a0637fSLawrence Stewart 32177,32182,32186,32191,32195,32200,32204,32209,32213,32217,32222,32226,32230, 19192a0637fSLawrence Stewart 32234,32238,32242,32247,32251,32255,32259,32263,32267,32270,32274,32278,32282, 19292a0637fSLawrence Stewart 32286,32290,32293,32297,32301,32304,32308,32311,32315,32318,32322,32325,32329, 19392a0637fSLawrence Stewart 32332,32336,32339,32342,32346,32349,32352,32356,32359,32362,32365,32368,32371, 19492a0637fSLawrence Stewart 32374,32377,32381,32384,32387,32389,32392,32395,32398,32401,32404,32407,32410, 19592a0637fSLawrence Stewart 32412,32415,32418,32421,32423,32426,32429,32431,32434,32437,32439,32442,32444, 19692a0637fSLawrence Stewart 32447,32449,32452,32454,32457,32459,32461,32464,32466,32469,32471,32473,32476, 19792a0637fSLawrence Stewart 32478,32480,32482,32485,32487,32489,32491,32493,32495,32497,32500,32502,32504, 19892a0637fSLawrence Stewart 32506,32508,32510,32512,32514,32516,32518,32520,32522,32524,32526,32527,32529, 19992a0637fSLawrence Stewart 32531,32533,32535,32537,32538,32540,32542,32544,32545,32547}; 20092a0637fSLawrence Stewart 20192a0637fSLawrence Stewart static uma_zone_t qdiffsample_zone; 20292a0637fSLawrence Stewart static int ertt_id; 20392a0637fSLawrence Stewart 2045f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_alpha_inc); 2055f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_beta_delay); 2065f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_beta_loss); 2075f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_smoothing_factor); 2085f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_exp_backoff_scale); 2095f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_consec_cong); 2105f901c92SAndrew Turner VNET_DEFINE_STATIC(uint32_t, cdg_hold_backoff); 21192a0637fSLawrence Stewart #define V_cdg_alpha_inc VNET(cdg_alpha_inc) 21292a0637fSLawrence Stewart #define V_cdg_beta_delay VNET(cdg_beta_delay) 21392a0637fSLawrence Stewart #define V_cdg_beta_loss VNET(cdg_beta_loss) 21492a0637fSLawrence Stewart #define V_cdg_smoothing_factor VNET(cdg_smoothing_factor) 21592a0637fSLawrence Stewart #define V_cdg_exp_backoff_scale VNET(cdg_exp_backoff_scale) 21692a0637fSLawrence Stewart #define V_cdg_consec_cong VNET(cdg_consec_cong) 21792a0637fSLawrence Stewart #define V_cdg_hold_backoff VNET(cdg_hold_backoff) 21892a0637fSLawrence Stewart 21992a0637fSLawrence Stewart /* Function prototypes. */ 22092a0637fSLawrence Stewart static int cdg_mod_init(void); 2218b0fe327SLawrence Stewart static int cdg_mod_destroy(void); 22292a0637fSLawrence Stewart static void cdg_conn_init(struct cc_var *ccv); 223b8d60729SRandall Stewart static int cdg_cb_init(struct cc_var *ccv, void *ptr); 22492a0637fSLawrence Stewart static void cdg_cb_destroy(struct cc_var *ccv); 225f74352fbSRichard Scheffenegger static void cdg_cong_signal(struct cc_var *ccv, ccsignal_t signal_type); 226f74352fbSRichard Scheffenegger static void cdg_ack_received(struct cc_var *ccv, ccsignal_t ack_type); 227b8d60729SRandall Stewart static size_t cdg_data_sz(void); 22892a0637fSLawrence Stewart 22992a0637fSLawrence Stewart struct cc_algo cdg_cc_algo = { 23092a0637fSLawrence Stewart .name = "cdg", 23192a0637fSLawrence Stewart .mod_init = cdg_mod_init, 23292a0637fSLawrence Stewart .ack_received = cdg_ack_received, 23392a0637fSLawrence Stewart .cb_destroy = cdg_cb_destroy, 23492a0637fSLawrence Stewart .cb_init = cdg_cb_init, 23592a0637fSLawrence Stewart .conn_init = cdg_conn_init, 2368b0fe327SLawrence Stewart .cong_signal = cdg_cong_signal, 237b8d60729SRandall Stewart .mod_destroy = cdg_mod_destroy, 238b8d60729SRandall Stewart .cc_data_sz = cdg_data_sz, 239b8d60729SRandall Stewart .post_recovery = newreno_cc_post_recovery, 240b8d60729SRandall Stewart .after_idle = newreno_cc_after_idle, 24192a0637fSLawrence Stewart }; 24292a0637fSLawrence Stewart 24392a0637fSLawrence Stewart /* Vnet created and being initialised. */ 24492a0637fSLawrence Stewart static void 24592a0637fSLawrence Stewart cdg_init_vnet(const void *unused __unused) 24692a0637fSLawrence Stewart { 24792a0637fSLawrence Stewart 24892a0637fSLawrence Stewart V_cdg_alpha_inc = 0; 24992a0637fSLawrence Stewart V_cdg_beta_delay = 70; 25092a0637fSLawrence Stewart V_cdg_beta_loss = 50; 25192a0637fSLawrence Stewart V_cdg_smoothing_factor = 8; 25292a0637fSLawrence Stewart V_cdg_exp_backoff_scale = 3; 25392a0637fSLawrence Stewart V_cdg_consec_cong = 5; 25492a0637fSLawrence Stewart V_cdg_hold_backoff = 5; 25592a0637fSLawrence Stewart } 25692a0637fSLawrence Stewart 25792a0637fSLawrence Stewart static int 25892a0637fSLawrence Stewart cdg_mod_init(void) 25992a0637fSLawrence Stewart { 26092a0637fSLawrence Stewart VNET_ITERATOR_DECL(v); 26192a0637fSLawrence Stewart 26292a0637fSLawrence Stewart ertt_id = khelp_get_id("ertt"); 26392a0637fSLawrence Stewart if (ertt_id <= 0) 26492a0637fSLawrence Stewart return (EINVAL); 26592a0637fSLawrence Stewart 26692a0637fSLawrence Stewart qdiffsample_zone = uma_zcreate("cdg_qdiffsample", 26792a0637fSLawrence Stewart sizeof(struct qdiff_sample), NULL, NULL, NULL, NULL, 0, 0); 26892a0637fSLawrence Stewart 26992a0637fSLawrence Stewart VNET_LIST_RLOCK(); 27092a0637fSLawrence Stewart VNET_FOREACH(v) { 27192a0637fSLawrence Stewart CURVNET_SET(v); 27292a0637fSLawrence Stewart cdg_init_vnet(NULL); 27392a0637fSLawrence Stewart CURVNET_RESTORE(); 27492a0637fSLawrence Stewart } 27592a0637fSLawrence Stewart VNET_LIST_RUNLOCK(); 27692a0637fSLawrence Stewart return (0); 27792a0637fSLawrence Stewart } 27892a0637fSLawrence Stewart 27992a0637fSLawrence Stewart static int 2808b0fe327SLawrence Stewart cdg_mod_destroy(void) 2818b0fe327SLawrence Stewart { 2828b0fe327SLawrence Stewart 2838b0fe327SLawrence Stewart uma_zdestroy(qdiffsample_zone); 2848b0fe327SLawrence Stewart return (0); 2858b0fe327SLawrence Stewart } 2868b0fe327SLawrence Stewart 287b8d60729SRandall Stewart static size_t 288b8d60729SRandall Stewart cdg_data_sz(void) 289b8d60729SRandall Stewart { 290b8d60729SRandall Stewart return (sizeof(struct cdg)); 291b8d60729SRandall Stewart } 292b8d60729SRandall Stewart 2938b0fe327SLawrence Stewart static int 294b8d60729SRandall Stewart cdg_cb_init(struct cc_var *ccv, void *ptr) 29592a0637fSLawrence Stewart { 29692a0637fSLawrence Stewart struct cdg *cdg_data; 29792a0637fSLawrence Stewart 29800d3b744SMichael Tuexen INP_WLOCK_ASSERT(tptoinpcb(ccv->tp)); 299b8d60729SRandall Stewart if (ptr == NULL) { 300b8d60729SRandall Stewart cdg_data = malloc(sizeof(struct cdg), M_CC_MEM, M_NOWAIT); 30192a0637fSLawrence Stewart if (cdg_data == NULL) 30292a0637fSLawrence Stewart return (ENOMEM); 303b8d60729SRandall Stewart } else { 304b8d60729SRandall Stewart cdg_data = ptr; 305b8d60729SRandall Stewart } 30692a0637fSLawrence Stewart cdg_data->shadow_w = 0; 30792a0637fSLawrence Stewart cdg_data->max_qtrend = 0; 30892a0637fSLawrence Stewart cdg_data->min_qtrend = 0; 30992a0637fSLawrence Stewart cdg_data->queue_state = CDG_Q_UNKNOWN; 31092a0637fSLawrence Stewart cdg_data->maxrtt_in_rtt = 0; 31192a0637fSLawrence Stewart cdg_data->maxrtt_in_prevrtt = 0; 31292a0637fSLawrence Stewart cdg_data->minrtt_in_rtt = INT_MAX; 31392a0637fSLawrence Stewart cdg_data->minrtt_in_prevrtt = 0; 31492a0637fSLawrence Stewart cdg_data->window_incr = 0; 31592a0637fSLawrence Stewart cdg_data->rtt_count = 0; 31692a0637fSLawrence Stewart cdg_data->consec_cong_cnt = 0; 31792a0637fSLawrence Stewart cdg_data->sample_q_size = V_cdg_smoothing_factor; 31892a0637fSLawrence Stewart cdg_data->num_samples = 0; 31992a0637fSLawrence Stewart STAILQ_INIT(&cdg_data->qdiffmin_q); 32092a0637fSLawrence Stewart STAILQ_INIT(&cdg_data->qdiffmax_q); 32192a0637fSLawrence Stewart 32292a0637fSLawrence Stewart ccv->cc_data = cdg_data; 32392a0637fSLawrence Stewart 32492a0637fSLawrence Stewart return (0); 32592a0637fSLawrence Stewart } 32692a0637fSLawrence Stewart 32792a0637fSLawrence Stewart static void 32892a0637fSLawrence Stewart cdg_conn_init(struct cc_var *ccv) 32992a0637fSLawrence Stewart { 33092a0637fSLawrence Stewart struct cdg *cdg_data = ccv->cc_data; 33192a0637fSLawrence Stewart 33292a0637fSLawrence Stewart /* 33392a0637fSLawrence Stewart * Initialise the shadow_cwnd in case we are competing with loss based 33492a0637fSLawrence Stewart * flows from the start 33592a0637fSLawrence Stewart */ 33692a0637fSLawrence Stewart cdg_data->shadow_w = CCV(ccv, snd_cwnd); 33792a0637fSLawrence Stewart } 33892a0637fSLawrence Stewart 33992a0637fSLawrence Stewart static void 34092a0637fSLawrence Stewart cdg_cb_destroy(struct cc_var *ccv) 34192a0637fSLawrence Stewart { 34292a0637fSLawrence Stewart struct cdg *cdg_data; 34392a0637fSLawrence Stewart struct qdiff_sample *qds, *qds_n; 34492a0637fSLawrence Stewart 34592a0637fSLawrence Stewart cdg_data = ccv->cc_data; 34692a0637fSLawrence Stewart 34792a0637fSLawrence Stewart qds = STAILQ_FIRST(&cdg_data->qdiffmin_q); 34892a0637fSLawrence Stewart while (qds != NULL) { 34992a0637fSLawrence Stewart qds_n = STAILQ_NEXT(qds, qdiff_lnk); 35092a0637fSLawrence Stewart uma_zfree(qdiffsample_zone,qds); 35192a0637fSLawrence Stewart qds = qds_n; 35292a0637fSLawrence Stewart } 35392a0637fSLawrence Stewart 35492a0637fSLawrence Stewart qds = STAILQ_FIRST(&cdg_data->qdiffmax_q); 35592a0637fSLawrence Stewart while (qds != NULL) { 35692a0637fSLawrence Stewart qds_n = STAILQ_NEXT(qds, qdiff_lnk); 35792a0637fSLawrence Stewart uma_zfree(qdiffsample_zone,qds); 35892a0637fSLawrence Stewart qds = qds_n; 35992a0637fSLawrence Stewart } 36092a0637fSLawrence Stewart 361b8d60729SRandall Stewart free(ccv->cc_data, M_CC_MEM); 36292a0637fSLawrence Stewart } 36392a0637fSLawrence Stewart 36492a0637fSLawrence Stewart static int 36592a0637fSLawrence Stewart cdg_beta_handler(SYSCTL_HANDLER_ARGS) 36692a0637fSLawrence Stewart { 367855acb84SBrooks Davis int error; 368855acb84SBrooks Davis uint32_t new; 36992a0637fSLawrence Stewart 370855acb84SBrooks Davis new = *(uint32_t *)arg1; 371855acb84SBrooks Davis error = sysctl_handle_int(oidp, &new, 0, req); 372855acb84SBrooks Davis if (error == 0 && req->newptr != NULL) { 373855acb84SBrooks Davis if (new == 0 || new > 100) 374855acb84SBrooks Davis error = EINVAL; 375855acb84SBrooks Davis else 376855acb84SBrooks Davis *(uint32_t *)arg1 = new; 377855acb84SBrooks Davis } 37892a0637fSLawrence Stewart 379855acb84SBrooks Davis return (error); 38092a0637fSLawrence Stewart } 38192a0637fSLawrence Stewart 38292a0637fSLawrence Stewart static int 38392a0637fSLawrence Stewart cdg_exp_backoff_scale_handler(SYSCTL_HANDLER_ARGS) 38492a0637fSLawrence Stewart { 385855acb84SBrooks Davis int error; 386855acb84SBrooks Davis uint32_t new; 38792a0637fSLawrence Stewart 388855acb84SBrooks Davis new = *(uint32_t *)arg1; 389855acb84SBrooks Davis error = sysctl_handle_int(oidp, &new, 0, req); 390855acb84SBrooks Davis if (error == 0 && req->newptr != NULL) { 391855acb84SBrooks Davis if (new < 1) 392855acb84SBrooks Davis error = EINVAL; 393855acb84SBrooks Davis else 394855acb84SBrooks Davis *(uint32_t *)arg1 = new; 395855acb84SBrooks Davis } 39692a0637fSLawrence Stewart 397855acb84SBrooks Davis return (error); 39892a0637fSLawrence Stewart } 39992a0637fSLawrence Stewart 4003ac12506SJonathan T. Looney static inline uint32_t 40192a0637fSLawrence Stewart cdg_window_decrease(struct cc_var *ccv, unsigned long owin, unsigned int beta) 40292a0637fSLawrence Stewart { 40392a0637fSLawrence Stewart 40492a0637fSLawrence Stewart return ((ulmin(CCV(ccv, snd_wnd), owin) * beta) / 100); 40592a0637fSLawrence Stewart } 40692a0637fSLawrence Stewart 40792a0637fSLawrence Stewart /* 40892a0637fSLawrence Stewart * Window increase function 40992a0637fSLawrence Stewart * This window increase function is independent of the initial window size 41092a0637fSLawrence Stewart * to ensure small window flows are not discriminated against (i.e. fairness). 41192a0637fSLawrence Stewart * It increases at 1pkt/rtt like Reno for alpha_inc rtts, and then 2pkts/rtt for 41292a0637fSLawrence Stewart * the next alpha_inc rtts, etc. 41392a0637fSLawrence Stewart */ 41492a0637fSLawrence Stewart static void 41592a0637fSLawrence Stewart cdg_window_increase(struct cc_var *ccv, int new_measurement) 41692a0637fSLawrence Stewart { 41792a0637fSLawrence Stewart struct cdg *cdg_data; 41892a0637fSLawrence Stewart int incr, s_w_incr; 419*22dcc812SRichard Scheffenegger uint32_t mss = tcp_fixed_maxseg(ccv->tp); 42092a0637fSLawrence Stewart 42192a0637fSLawrence Stewart cdg_data = ccv->cc_data; 42292a0637fSLawrence Stewart incr = s_w_incr = 0; 42392a0637fSLawrence Stewart 42492a0637fSLawrence Stewart if (CCV(ccv, snd_cwnd) <= CCV(ccv, snd_ssthresh)) { 42592a0637fSLawrence Stewart /* Slow start. */ 426*22dcc812SRichard Scheffenegger incr = mss; 42792a0637fSLawrence Stewart s_w_incr = incr; 42892a0637fSLawrence Stewart cdg_data->window_incr = cdg_data->rtt_count = 0; 42992a0637fSLawrence Stewart } else { 43092a0637fSLawrence Stewart /* Congestion avoidance. */ 43192a0637fSLawrence Stewart if (new_measurement) { 432*22dcc812SRichard Scheffenegger s_w_incr = mss; 43392a0637fSLawrence Stewart if (V_cdg_alpha_inc == 0) { 434*22dcc812SRichard Scheffenegger incr = mss; 43592a0637fSLawrence Stewart } else { 43692a0637fSLawrence Stewart if (++cdg_data->rtt_count >= V_cdg_alpha_inc) { 43792a0637fSLawrence Stewart cdg_data->window_incr++; 43892a0637fSLawrence Stewart cdg_data->rtt_count = 0; 43992a0637fSLawrence Stewart } 440*22dcc812SRichard Scheffenegger incr = mss * 44192a0637fSLawrence Stewart cdg_data->window_incr; 44292a0637fSLawrence Stewart } 44392a0637fSLawrence Stewart } 44492a0637fSLawrence Stewart } 44592a0637fSLawrence Stewart 44692a0637fSLawrence Stewart if (cdg_data->shadow_w > 0) 44792a0637fSLawrence Stewart cdg_data->shadow_w = ulmin(cdg_data->shadow_w + s_w_incr, 44892a0637fSLawrence Stewart TCP_MAXWIN << CCV(ccv, snd_scale)); 44992a0637fSLawrence Stewart 45092a0637fSLawrence Stewart CCV(ccv, snd_cwnd) = ulmin(CCV(ccv, snd_cwnd) + incr, 45192a0637fSLawrence Stewart TCP_MAXWIN << CCV(ccv, snd_scale)); 45292a0637fSLawrence Stewart } 45392a0637fSLawrence Stewart 45492a0637fSLawrence Stewart static void 455f74352fbSRichard Scheffenegger cdg_cong_signal(struct cc_var *ccv, ccsignal_t signal_type) 45692a0637fSLawrence Stewart { 45792a0637fSLawrence Stewart struct cdg *cdg_data = ccv->cc_data; 45892a0637fSLawrence Stewart 459f74352fbSRichard Scheffenegger switch((int)signal_type) { 46092a0637fSLawrence Stewart case CC_CDG_DELAY: 46192a0637fSLawrence Stewart CCV(ccv, snd_ssthresh) = cdg_window_decrease(ccv, 46292a0637fSLawrence Stewart CCV(ccv, snd_cwnd), V_cdg_beta_delay); 46392a0637fSLawrence Stewart CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh); 46492a0637fSLawrence Stewart CCV(ccv, snd_recover) = CCV(ccv, snd_max); 46592a0637fSLawrence Stewart cdg_data->window_incr = cdg_data->rtt_count = 0; 46692a0637fSLawrence Stewart ENTER_CONGRECOVERY(CCV(ccv, t_flags)); 46792a0637fSLawrence Stewart break; 46892a0637fSLawrence Stewart case CC_NDUPACK: 46992a0637fSLawrence Stewart /* 47092a0637fSLawrence Stewart * If already responding to congestion OR we have guessed no 47192a0637fSLawrence Stewart * queue in the path is full. 47292a0637fSLawrence Stewart */ 47392a0637fSLawrence Stewart if (IN_CONGRECOVERY(CCV(ccv, t_flags)) || 47492a0637fSLawrence Stewart cdg_data->queue_state < CDG_Q_FULL) { 47543053c12SSean Bruno CCV(ccv, snd_ssthresh) = CCV(ccv, snd_cwnd); 47692a0637fSLawrence Stewart CCV(ccv, snd_recover) = CCV(ccv, snd_max); 47792a0637fSLawrence Stewart } else { 47892a0637fSLawrence Stewart /* 47992a0637fSLawrence Stewart * Loss is likely to be congestion related. We have 48092a0637fSLawrence Stewart * inferred a queue full state, so have shadow window 48192a0637fSLawrence Stewart * react to loss as NewReno would. 48292a0637fSLawrence Stewart */ 48392a0637fSLawrence Stewart if (cdg_data->shadow_w > 0) 48492a0637fSLawrence Stewart cdg_data->shadow_w = cdg_window_decrease(ccv, 48592a0637fSLawrence Stewart cdg_data->shadow_w, RENO_BETA); 48692a0637fSLawrence Stewart 4873ac12506SJonathan T. Looney CCV(ccv, snd_ssthresh) = max(cdg_data->shadow_w, 48843053c12SSean Bruno cdg_window_decrease(ccv, CCV(ccv, snd_cwnd), 48943053c12SSean Bruno V_cdg_beta_loss)); 49092a0637fSLawrence Stewart 49192a0637fSLawrence Stewart cdg_data->window_incr = cdg_data->rtt_count = 0; 49292a0637fSLawrence Stewart } 49392a0637fSLawrence Stewart ENTER_RECOVERY(CCV(ccv, t_flags)); 49492a0637fSLawrence Stewart break; 49592a0637fSLawrence Stewart default: 496b8d60729SRandall Stewart newreno_cc_cong_signal(ccv, signal_type); 49792a0637fSLawrence Stewart break; 49892a0637fSLawrence Stewart } 49992a0637fSLawrence Stewart } 50092a0637fSLawrence Stewart 50192a0637fSLawrence Stewart /* 50292a0637fSLawrence Stewart * Using a negative exponential probabilistic backoff so that sources with 50392a0637fSLawrence Stewart * varying RTTs which share the same link will, on average, have the same 50492a0637fSLawrence Stewart * probability of backoff over time. 50592a0637fSLawrence Stewart * 50692a0637fSLawrence Stewart * Prob_backoff = 1 - exp(-qtrend / V_cdg_exp_backoff_scale), where 50792a0637fSLawrence Stewart * V_cdg_exp_backoff_scale is the average qtrend for the exponential backoff. 50892a0637fSLawrence Stewart */ 50992a0637fSLawrence Stewart static inline int 51092a0637fSLawrence Stewart prob_backoff(long qtrend) 51192a0637fSLawrence Stewart { 512674956e1SHenrich Hartzer int backoff, idx; 513674956e1SHenrich Hartzer uint32_t p; 51492a0637fSLawrence Stewart 51592a0637fSLawrence Stewart backoff = (qtrend > ((MAXGRAD * V_cdg_exp_backoff_scale) << D_P_E)); 51692a0637fSLawrence Stewart 51792a0637fSLawrence Stewart if (!backoff) { 51892a0637fSLawrence Stewart if (V_cdg_exp_backoff_scale > 1) 51992a0637fSLawrence Stewart idx = (qtrend + V_cdg_exp_backoff_scale / 2) / 52092a0637fSLawrence Stewart V_cdg_exp_backoff_scale; 52192a0637fSLawrence Stewart else 52292a0637fSLawrence Stewart idx = qtrend; 52392a0637fSLawrence Stewart 52492a0637fSLawrence Stewart /* Backoff probability proportional to rate of queue growth. */ 525674956e1SHenrich Hartzer p = (UINT32_MAX / (1 << EXP_PREC)) * probexp[idx]; 526674956e1SHenrich Hartzer backoff = (prng32() < p); 52792a0637fSLawrence Stewart } 52892a0637fSLawrence Stewart 52992a0637fSLawrence Stewart return (backoff); 53092a0637fSLawrence Stewart } 53192a0637fSLawrence Stewart 53292a0637fSLawrence Stewart static inline void 53392a0637fSLawrence Stewart calc_moving_average(struct cdg *cdg_data, long qdiff_max, long qdiff_min) 53492a0637fSLawrence Stewart { 53592a0637fSLawrence Stewart struct qdiff_sample *qds; 53692a0637fSLawrence Stewart 53792a0637fSLawrence Stewart ++cdg_data->num_samples; 53892a0637fSLawrence Stewart if (cdg_data->num_samples > cdg_data->sample_q_size) { 53992a0637fSLawrence Stewart /* Minimum RTT. */ 54092a0637fSLawrence Stewart qds = STAILQ_FIRST(&cdg_data->qdiffmin_q); 54192a0637fSLawrence Stewart cdg_data->min_qtrend = cdg_data->min_qtrend + 54292a0637fSLawrence Stewart (qdiff_min - qds->qdiff) / cdg_data->sample_q_size; 54392a0637fSLawrence Stewart STAILQ_REMOVE_HEAD(&cdg_data->qdiffmin_q, qdiff_lnk); 54492a0637fSLawrence Stewart qds->qdiff = qdiff_min; 54592a0637fSLawrence Stewart STAILQ_INSERT_TAIL(&cdg_data->qdiffmin_q, qds, qdiff_lnk); 54692a0637fSLawrence Stewart 54792a0637fSLawrence Stewart /* Maximum RTT. */ 54892a0637fSLawrence Stewart qds = STAILQ_FIRST(&cdg_data->qdiffmax_q); 54992a0637fSLawrence Stewart cdg_data->max_qtrend = cdg_data->max_qtrend + 55092a0637fSLawrence Stewart (qdiff_max - qds->qdiff) / cdg_data->sample_q_size; 55192a0637fSLawrence Stewart STAILQ_REMOVE_HEAD(&cdg_data->qdiffmax_q, qdiff_lnk); 55292a0637fSLawrence Stewart qds->qdiff = qdiff_max; 55392a0637fSLawrence Stewart STAILQ_INSERT_TAIL(&cdg_data->qdiffmax_q, qds, qdiff_lnk); 55492a0637fSLawrence Stewart --cdg_data->num_samples; 55592a0637fSLawrence Stewart } else { 55692a0637fSLawrence Stewart qds = uma_zalloc(qdiffsample_zone, M_NOWAIT); 55792a0637fSLawrence Stewart if (qds != NULL) { 55892a0637fSLawrence Stewart cdg_data->min_qtrend = cdg_data->min_qtrend + 55992a0637fSLawrence Stewart qdiff_min / cdg_data->sample_q_size; 56092a0637fSLawrence Stewart qds->qdiff = qdiff_min; 56192a0637fSLawrence Stewart STAILQ_INSERT_TAIL(&cdg_data->qdiffmin_q, qds, 56292a0637fSLawrence Stewart qdiff_lnk); 56392a0637fSLawrence Stewart } 56492a0637fSLawrence Stewart 56592a0637fSLawrence Stewart qds = uma_zalloc(qdiffsample_zone, M_NOWAIT); 56692a0637fSLawrence Stewart if (qds) { 56792a0637fSLawrence Stewart cdg_data->max_qtrend = cdg_data->max_qtrend + 56892a0637fSLawrence Stewart qdiff_max / cdg_data->sample_q_size; 56992a0637fSLawrence Stewart qds->qdiff = qdiff_max; 57092a0637fSLawrence Stewart STAILQ_INSERT_TAIL(&cdg_data->qdiffmax_q, qds, 57192a0637fSLawrence Stewart qdiff_lnk); 57292a0637fSLawrence Stewart } 57392a0637fSLawrence Stewart } 57492a0637fSLawrence Stewart } 57592a0637fSLawrence Stewart 57692a0637fSLawrence Stewart static void 577f74352fbSRichard Scheffenegger cdg_ack_received(struct cc_var *ccv, ccsignal_t ack_type) 57892a0637fSLawrence Stewart { 57992a0637fSLawrence Stewart struct cdg *cdg_data; 58092a0637fSLawrence Stewart struct ertt *e_t; 58192a0637fSLawrence Stewart long qdiff_max, qdiff_min; 58292a0637fSLawrence Stewart int congestion, new_measurement, slowstart; 58392a0637fSLawrence Stewart 58492a0637fSLawrence Stewart cdg_data = ccv->cc_data; 585e68b3792SGleb Smirnoff e_t = (struct ertt *)khelp_get_osd(&CCV(ccv, t_osd), ertt_id); 58692a0637fSLawrence Stewart new_measurement = e_t->flags & ERTT_NEW_MEASUREMENT; 58792a0637fSLawrence Stewart congestion = 0; 58892a0637fSLawrence Stewart cdg_data->maxrtt_in_rtt = imax(e_t->rtt, cdg_data->maxrtt_in_rtt); 58992a0637fSLawrence Stewart cdg_data->minrtt_in_rtt = imin(e_t->rtt, cdg_data->minrtt_in_rtt); 59092a0637fSLawrence Stewart 59192a0637fSLawrence Stewart if (new_measurement) { 59292a0637fSLawrence Stewart slowstart = (CCV(ccv, snd_cwnd) <= CCV(ccv, snd_ssthresh)); 59392a0637fSLawrence Stewart /* 59492a0637fSLawrence Stewart * Update smoothed gradient measurements. Since we are only 59592a0637fSLawrence Stewart * using one measurement per RTT, use max or min rtt_in_rtt. 59692a0637fSLawrence Stewart * This is also less noisy than a sample RTT measurement. Max 59792a0637fSLawrence Stewart * RTT measurements can have trouble due to OS issues. 59892a0637fSLawrence Stewart */ 59992a0637fSLawrence Stewart if (cdg_data->maxrtt_in_prevrtt) { 60092a0637fSLawrence Stewart qdiff_max = ((long)(cdg_data->maxrtt_in_rtt - 60192a0637fSLawrence Stewart cdg_data->maxrtt_in_prevrtt) << D_P_E ); 60292a0637fSLawrence Stewart qdiff_min = ((long)(cdg_data->minrtt_in_rtt - 60392a0637fSLawrence Stewart cdg_data->minrtt_in_prevrtt) << D_P_E ); 60492a0637fSLawrence Stewart 605aa36fbd6SMichael Tuexen if (cdg_data->sample_q_size == 0) { 606aa36fbd6SMichael Tuexen cdg_data->max_qtrend = qdiff_max; 607aa36fbd6SMichael Tuexen cdg_data->min_qtrend = qdiff_min; 608aa36fbd6SMichael Tuexen } else 60992a0637fSLawrence Stewart calc_moving_average(cdg_data, qdiff_max, qdiff_min); 61092a0637fSLawrence Stewart 61192a0637fSLawrence Stewart /* Probabilistic backoff with respect to gradient. */ 61292a0637fSLawrence Stewart if (slowstart && qdiff_min > 0) 61392a0637fSLawrence Stewart congestion = prob_backoff(qdiff_min); 61492a0637fSLawrence Stewart else if (cdg_data->min_qtrend > 0) 61592a0637fSLawrence Stewart congestion = prob_backoff(cdg_data->min_qtrend); 61692a0637fSLawrence Stewart else if (slowstart && qdiff_max > 0) 61792a0637fSLawrence Stewart congestion = prob_backoff(qdiff_max); 61892a0637fSLawrence Stewart else if (cdg_data->max_qtrend > 0) 61992a0637fSLawrence Stewart congestion = prob_backoff(cdg_data->max_qtrend); 62092a0637fSLawrence Stewart 62192a0637fSLawrence Stewart /* Update estimate of queue state. */ 62292a0637fSLawrence Stewart if (cdg_data->min_qtrend > 0 && 62392a0637fSLawrence Stewart cdg_data->max_qtrend <= 0) { 62492a0637fSLawrence Stewart cdg_data->queue_state = CDG_Q_FULL; 62592a0637fSLawrence Stewart } else if (cdg_data->min_qtrend >= 0 && 62692a0637fSLawrence Stewart cdg_data->max_qtrend < 0) { 62792a0637fSLawrence Stewart cdg_data->queue_state = CDG_Q_EMPTY; 62892a0637fSLawrence Stewart cdg_data->shadow_w = 0; 62992a0637fSLawrence Stewart } else if (cdg_data->min_qtrend > 0 && 63092a0637fSLawrence Stewart cdg_data->max_qtrend > 0) { 63192a0637fSLawrence Stewart cdg_data->queue_state = CDG_Q_RISING; 63292a0637fSLawrence Stewart } else if (cdg_data->min_qtrend < 0 && 63392a0637fSLawrence Stewart cdg_data->max_qtrend < 0) { 63492a0637fSLawrence Stewart cdg_data->queue_state = CDG_Q_FALLING; 63592a0637fSLawrence Stewart } 63692a0637fSLawrence Stewart 63792a0637fSLawrence Stewart if (cdg_data->min_qtrend < 0 || 63892a0637fSLawrence Stewart cdg_data->max_qtrend < 0) 63992a0637fSLawrence Stewart cdg_data->consec_cong_cnt = 0; 64092a0637fSLawrence Stewart } 64192a0637fSLawrence Stewart 64292a0637fSLawrence Stewart cdg_data->minrtt_in_prevrtt = cdg_data->minrtt_in_rtt; 64392a0637fSLawrence Stewart cdg_data->minrtt_in_rtt = INT_MAX; 64492a0637fSLawrence Stewart cdg_data->maxrtt_in_prevrtt = cdg_data->maxrtt_in_rtt; 64592a0637fSLawrence Stewart cdg_data->maxrtt_in_rtt = 0; 64692a0637fSLawrence Stewart e_t->flags &= ~ERTT_NEW_MEASUREMENT; 64792a0637fSLawrence Stewart } 64892a0637fSLawrence Stewart 64992a0637fSLawrence Stewart if (congestion) { 65092a0637fSLawrence Stewart cdg_data->consec_cong_cnt++; 65192a0637fSLawrence Stewart if (!IN_RECOVERY(CCV(ccv, t_flags))) { 65292a0637fSLawrence Stewart if (cdg_data->consec_cong_cnt <= V_cdg_consec_cong) 65392a0637fSLawrence Stewart cdg_cong_signal(ccv, CC_CDG_DELAY); 65492a0637fSLawrence Stewart else 65592a0637fSLawrence Stewart /* 65692a0637fSLawrence Stewart * We have been backing off but the queue is not 65792a0637fSLawrence Stewart * falling. Assume we are competing with 65892a0637fSLawrence Stewart * loss-based flows and don't back off for the 65992a0637fSLawrence Stewart * next V_cdg_hold_backoff RTT periods. 66092a0637fSLawrence Stewart */ 66192a0637fSLawrence Stewart if (cdg_data->consec_cong_cnt >= 66292a0637fSLawrence Stewart V_cdg_consec_cong + V_cdg_hold_backoff) 66392a0637fSLawrence Stewart cdg_data->consec_cong_cnt = 0; 66492a0637fSLawrence Stewart 66592a0637fSLawrence Stewart /* Won't see effect until 2nd RTT. */ 66692a0637fSLawrence Stewart cdg_data->maxrtt_in_prevrtt = 0; 66792a0637fSLawrence Stewart /* 66892a0637fSLawrence Stewart * Resync shadow window in case we are competing with a 66992a0637fSLawrence Stewart * loss based flow 67092a0637fSLawrence Stewart */ 67192a0637fSLawrence Stewart cdg_data->shadow_w = ulmax(CCV(ccv, snd_cwnd), 67292a0637fSLawrence Stewart cdg_data->shadow_w); 67392a0637fSLawrence Stewart } 67492a0637fSLawrence Stewart } else if (ack_type == CC_ACK) 67592a0637fSLawrence Stewart cdg_window_increase(ccv, new_measurement); 67692a0637fSLawrence Stewart } 67792a0637fSLawrence Stewart 67892a0637fSLawrence Stewart /* When a vnet is created and being initialised, init the per-stack CDG vars. */ 67992a0637fSLawrence Stewart VNET_SYSINIT(cdg_init_vnet, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, 68092a0637fSLawrence Stewart cdg_init_vnet, NULL); 68192a0637fSLawrence Stewart 68292a0637fSLawrence Stewart SYSCTL_DECL(_net_inet_tcp_cc_cdg); 6837029da5cSPawel Biernacki SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, cdg, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 68492a0637fSLawrence Stewart "CAIA delay-gradient congestion control related settings"); 68592a0637fSLawrence Stewart 68692a0637fSLawrence Stewart SYSCTL_STRING(_net_inet_tcp_cc_cdg, OID_AUTO, version, 68792a0637fSLawrence Stewart CTLFLAG_RD, CDG_VERSION, sizeof(CDG_VERSION) - 1, 68892a0637fSLawrence Stewart "Current algorithm/implementation version number"); 68992a0637fSLawrence Stewart 6906df8a710SGleb Smirnoff SYSCTL_UINT(_net_inet_tcp_cc_cdg, OID_AUTO, alpha_inc, 6916df8a710SGleb Smirnoff CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(cdg_alpha_inc), 0, 69292a0637fSLawrence Stewart "Increment the window increase factor alpha by 1 MSS segment every " 69392a0637fSLawrence Stewart "alpha_inc RTTs during congestion avoidance mode."); 69492a0637fSLawrence Stewart 6956df8a710SGleb Smirnoff SYSCTL_PROC(_net_inet_tcp_cc_cdg, OID_AUTO, beta_delay, 6967029da5cSPawel Biernacki CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 6977029da5cSPawel Biernacki &VNET_NAME(cdg_beta_delay), 70, &cdg_beta_handler, "IU", 69892a0637fSLawrence Stewart "Delay-based window decrease factor as a percentage " 69992a0637fSLawrence Stewart "(on delay-based backoff, w = w * beta_delay / 100)"); 70092a0637fSLawrence Stewart 7016df8a710SGleb Smirnoff SYSCTL_PROC(_net_inet_tcp_cc_cdg, OID_AUTO, beta_loss, 7027029da5cSPawel Biernacki CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7037029da5cSPawel Biernacki &VNET_NAME(cdg_beta_loss), 50, &cdg_beta_handler, "IU", 70492a0637fSLawrence Stewart "Loss-based window decrease factor as a percentage " 70592a0637fSLawrence Stewart "(on loss-based backoff, w = w * beta_loss / 100)"); 70692a0637fSLawrence Stewart 7076df8a710SGleb Smirnoff SYSCTL_PROC(_net_inet_tcp_cc_cdg, OID_AUTO, exp_backoff_scale, 7087029da5cSPawel Biernacki CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7096df8a710SGleb Smirnoff &VNET_NAME(cdg_exp_backoff_scale), 2, &cdg_exp_backoff_scale_handler, "IU", 71092a0637fSLawrence Stewart "Scaling parameter for the probabilistic exponential backoff"); 71192a0637fSLawrence Stewart 7126df8a710SGleb Smirnoff SYSCTL_UINT(_net_inet_tcp_cc_cdg, OID_AUTO, smoothing_factor, 7136df8a710SGleb Smirnoff CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(cdg_smoothing_factor), 8, 71492a0637fSLawrence Stewart "Number of samples used for moving average smoothing (0 = no smoothing)"); 71592a0637fSLawrence Stewart 7166df8a710SGleb Smirnoff SYSCTL_UINT(_net_inet_tcp_cc_cdg, OID_AUTO, loss_compete_consec_cong, 7176df8a710SGleb Smirnoff CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(cdg_consec_cong), 5, 71892a0637fSLawrence Stewart "Number of consecutive delay-gradient based congestion episodes which will " 71992a0637fSLawrence Stewart "trigger loss based CC compatibility"); 72092a0637fSLawrence Stewart 7216df8a710SGleb Smirnoff SYSCTL_UINT(_net_inet_tcp_cc_cdg, OID_AUTO, loss_compete_hold_backoff, 7226df8a710SGleb Smirnoff CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(cdg_hold_backoff), 5, 72392a0637fSLawrence Stewart "Number of consecutive delay-gradient based congestion episodes to hold " 72492a0637fSLawrence Stewart "the window backoff for loss based CC compatibility"); 72592a0637fSLawrence Stewart 72692a0637fSLawrence Stewart DECLARE_CC_MODULE(cdg, &cdg_cc_algo); 727b8d60729SRandall Stewart MODULE_VERSION(cdg, 2); 72892a0637fSLawrence Stewart MODULE_DEPEND(cdg, ertt, 1, 1, 1); 729