sctp_cc_functions.c 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493
  1. /*-
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
  5. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
  6. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. *
  11. * a) Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. *
  14. * b) Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the distribution.
  17. *
  18. * c) Neither the name of Cisco Systems, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived
  20. * from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  24. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #if defined(__FreeBSD__) && !defined(__Userspace__)
  35. #include <sys/cdefs.h>
  36. __FBSDID("$FreeBSD$");
  37. #endif
  38. #include <netinet/sctp_os.h>
  39. #include <netinet/sctp_var.h>
  40. #include <netinet/sctp_sysctl.h>
  41. #include <netinet/sctp_pcb.h>
  42. #include <netinet/sctp_header.h>
  43. #include <netinet/sctputil.h>
  44. #include <netinet/sctp_output.h>
  45. #include <netinet/sctp_input.h>
  46. #include <netinet/sctp_indata.h>
  47. #include <netinet/sctp_uio.h>
  48. #include <netinet/sctp_timer.h>
  49. #include <netinet/sctp_auth.h>
  50. #include <netinet/sctp_asconf.h>
  51. #if defined(__FreeBSD__) && !defined(__Userspace__)
  52. #include <netinet/sctp_kdtrace.h>
  53. #endif
  54. #define SHIFT_MPTCP_MULTI_N 40
  55. #define SHIFT_MPTCP_MULTI_Z 16
  56. #define SHIFT_MPTCP_MULTI 8
  57. static void
  58. sctp_enforce_cwnd_limit(struct sctp_association *assoc, struct sctp_nets *net)
  59. {
  60. if ((assoc->max_cwnd > 0) &&
  61. (net->cwnd > assoc->max_cwnd) &&
  62. (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
  63. net->cwnd = assoc->max_cwnd;
  64. if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
  65. net->cwnd = net->mtu - sizeof(struct sctphdr);
  66. }
  67. }
  68. }
  69. static void
  70. sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
  71. {
  72. struct sctp_association *assoc;
  73. uint32_t cwnd_in_mtu;
  74. assoc = &stcb->asoc;
  75. cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
  76. if (cwnd_in_mtu == 0) {
  77. /* Using 0 means that the value of RFC 4960 is used. */
  78. net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
  79. } else {
  80. /*
  81. * We take the minimum of the burst limit and the
  82. * initial congestion window.
  83. */
  84. if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
  85. cwnd_in_mtu = assoc->max_burst;
  86. net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
  87. }
  88. if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
  89. (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
  90. /* In case of resource pooling initialize appropriately */
  91. net->cwnd /= assoc->numnets;
  92. if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
  93. net->cwnd = net->mtu - sizeof(struct sctphdr);
  94. }
  95. }
  96. sctp_enforce_cwnd_limit(assoc, net);
  97. net->ssthresh = assoc->peers_rwnd;
  98. #if defined(__FreeBSD__) && !defined(__Userspace__)
  99. SDT_PROBE5(sctp, cwnd, net, init,
  100. stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
  101. 0, net->cwnd);
  102. #endif
  103. if (SCTP_BASE_SYSCTL(sctp_logging_level) &
  104. (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
  105. sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
  106. }
  107. }
  108. static void
  109. sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
  110. struct sctp_association *asoc)
  111. {
  112. struct sctp_nets *net;
  113. uint32_t t_ssthresh, t_cwnd;
  114. uint64_t t_ucwnd_sbw;
  115. /* MT FIXME: Don't compute this over and over again */
  116. t_ssthresh = 0;
  117. t_cwnd = 0;
  118. t_ucwnd_sbw = 0;
  119. if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
  120. (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
  121. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  122. t_ssthresh += net->ssthresh;
  123. t_cwnd += net->cwnd;
  124. if (net->lastsa > 0) {
  125. t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)net->lastsa;
  126. }
  127. }
  128. if (t_ucwnd_sbw == 0) {
  129. t_ucwnd_sbw = 1;
  130. }
  131. }
  132. /*-
  133. * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
  134. * (net->fast_retran_loss_recovery == 0)))
  135. */
  136. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  137. if ((asoc->fast_retran_loss_recovery == 0) ||
  138. (asoc->sctp_cmt_on_off > 0)) {
  139. /* out of a RFC2582 Fast recovery window? */
  140. if (net->net_ack > 0) {
  141. /*
  142. * per section 7.2.3, are there any
  143. * destinations that had a fast retransmit
  144. * to them. If so what we need to do is
  145. * adjust ssthresh and cwnd.
  146. */
  147. struct sctp_tmit_chunk *lchk;
  148. int old_cwnd = net->cwnd;
  149. if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
  150. (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
  151. if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
  152. net->ssthresh = (uint32_t)(((uint64_t)4 *
  153. (uint64_t)net->mtu *
  154. (uint64_t)net->ssthresh) /
  155. (uint64_t)t_ssthresh);
  156. }
  157. if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
  158. uint32_t srtt;
  159. srtt = net->lastsa;
  160. /* lastsa>>3; we don't need to devide ...*/
  161. if (srtt == 0) {
  162. srtt = 1;
  163. }
  164. /* Short Version => Equal to Contel Version MBe */
  165. net->ssthresh = (uint32_t) (((uint64_t)4 *
  166. (uint64_t)net->mtu *
  167. (uint64_t)net->cwnd) /
  168. ((uint64_t)srtt *
  169. t_ucwnd_sbw));
  170. /* INCREASE FACTOR */;
  171. }
  172. if ((net->cwnd > t_cwnd / 2) &&
  173. (net->ssthresh < net->cwnd - t_cwnd / 2)) {
  174. net->ssthresh = net->cwnd - t_cwnd / 2;
  175. }
  176. if (net->ssthresh < net->mtu) {
  177. net->ssthresh = net->mtu;
  178. }
  179. } else {
  180. net->ssthresh = net->cwnd / 2;
  181. if (net->ssthresh < (net->mtu * 2)) {
  182. net->ssthresh = 2 * net->mtu;
  183. }
  184. }
  185. net->cwnd = net->ssthresh;
  186. sctp_enforce_cwnd_limit(asoc, net);
  187. #if defined(__FreeBSD__) && !defined(__Userspace__)
  188. SDT_PROBE5(sctp, cwnd, net, fr,
  189. stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
  190. old_cwnd, net->cwnd);
  191. #endif
  192. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  193. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
  194. SCTP_CWND_LOG_FROM_FR);
  195. }
  196. lchk = TAILQ_FIRST(&asoc->send_queue);
  197. net->partial_bytes_acked = 0;
  198. /* Turn on fast recovery window */
  199. asoc->fast_retran_loss_recovery = 1;
  200. if (lchk == NULL) {
  201. /* Mark end of the window */
  202. asoc->fast_recovery_tsn = asoc->sending_seq - 1;
  203. } else {
  204. asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  205. }
  206. /*
  207. * CMT fast recovery -- per destination
  208. * recovery variable.
  209. */
  210. net->fast_retran_loss_recovery = 1;
  211. if (lchk == NULL) {
  212. /* Mark end of the window */
  213. net->fast_recovery_tsn = asoc->sending_seq - 1;
  214. } else {
  215. net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  216. }
  217. sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
  218. stcb->sctp_ep, stcb, net,
  219. SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_1);
  220. sctp_timer_start(SCTP_TIMER_TYPE_SEND,
  221. stcb->sctp_ep, stcb, net);
  222. }
  223. } else if (net->net_ack > 0) {
  224. /*
  225. * Mark a peg that we WOULD have done a cwnd
  226. * reduction but RFC2582 prevented this action.
  227. */
  228. SCTP_STAT_INCR(sctps_fastretransinrtt);
  229. }
  230. }
  231. }
  232. /* Defines for instantaneous bw decisions */
  233. #define SCTP_INST_LOOSING 1 /* Losing to other flows */
  234. #define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */
  235. #define SCTP_INST_GAINING 3 /* Gaining, step down possible */
  236. #if defined(__FreeBSD__) && !defined(__Userspace__)
  237. static int
  238. cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
  239. uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
  240. #else
  241. static int
  242. cc_bw_same(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw,
  243. uint64_t rtt_offset, uint8_t inst_ind)
  244. #endif
  245. {
  246. #if defined(__FreeBSD__) && !defined(__Userspace__)
  247. uint64_t oth, probepoint;
  248. #endif
  249. #if defined(__FreeBSD__) && !defined(__Userspace__)
  250. probepoint = (((uint64_t)net->cwnd) << 32);
  251. #endif
  252. if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
  253. /*
  254. * rtt increased
  255. * we don't update bw.. so we don't
  256. * update the rtt either.
  257. */
  258. #if defined(__FreeBSD__) && !defined(__Userspace__)
  259. /* Probe point 5 */
  260. probepoint |= ((5 << 16) | 1);
  261. SDT_PROBE5(sctp, cwnd, net, rttvar,
  262. vtag,
  263. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  264. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  265. net->flight_size,
  266. probepoint);
  267. #endif
  268. if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
  269. if (net->cc_mod.rtcc.last_step_state == 5)
  270. net->cc_mod.rtcc.step_cnt++;
  271. else
  272. net->cc_mod.rtcc.step_cnt = 1;
  273. net->cc_mod.rtcc.last_step_state = 5;
  274. if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
  275. ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
  276. ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
  277. /* Try a step down */
  278. #if defined(__FreeBSD__) && !defined(__Userspace__)
  279. oth = net->cc_mod.rtcc.vol_reduce;
  280. oth <<= 16;
  281. oth |= net->cc_mod.rtcc.step_cnt;
  282. oth <<= 16;
  283. oth |= net->cc_mod.rtcc.last_step_state;
  284. SDT_PROBE5(sctp, cwnd, net, rttstep,
  285. vtag,
  286. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  287. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  288. oth,
  289. probepoint);
  290. #endif
  291. if (net->cwnd > (4 * net->mtu)) {
  292. net->cwnd -= net->mtu;
  293. net->cc_mod.rtcc.vol_reduce++;
  294. } else {
  295. net->cc_mod.rtcc.step_cnt = 0;
  296. }
  297. }
  298. }
  299. return (1);
  300. }
  301. if (net->rtt < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
  302. /*
  303. * rtt decreased, there could be more room.
  304. * we update both the bw and the rtt here to
  305. * lock this in as a good step down.
  306. */
  307. #if defined(__FreeBSD__) && !defined(__Userspace__)
  308. /* Probe point 6 */
  309. probepoint |= ((6 << 16) | 0);
  310. SDT_PROBE5(sctp, cwnd, net, rttvar,
  311. vtag,
  312. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  313. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  314. net->flight_size,
  315. probepoint);
  316. #endif
  317. if (net->cc_mod.rtcc.steady_step) {
  318. #if defined(__FreeBSD__) && !defined(__Userspace__)
  319. oth = net->cc_mod.rtcc.vol_reduce;
  320. oth <<= 16;
  321. oth |= net->cc_mod.rtcc.step_cnt;
  322. oth <<= 16;
  323. oth |= net->cc_mod.rtcc.last_step_state;
  324. SDT_PROBE5(sctp, cwnd, net, rttstep,
  325. vtag,
  326. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  327. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  328. oth,
  329. probepoint);
  330. #endif
  331. if ((net->cc_mod.rtcc.last_step_state == 5) &&
  332. (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
  333. /* Step down worked */
  334. net->cc_mod.rtcc.step_cnt = 0;
  335. return (1);
  336. } else {
  337. net->cc_mod.rtcc.last_step_state = 6;
  338. net->cc_mod.rtcc.step_cnt = 0;
  339. }
  340. }
  341. net->cc_mod.rtcc.lbw = nbw;
  342. net->cc_mod.rtcc.lbw_rtt = net->rtt;
  343. net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
  344. if (inst_ind == SCTP_INST_GAINING)
  345. return (1);
  346. else if (inst_ind == SCTP_INST_NEUTRAL)
  347. return (1);
  348. else
  349. return (0);
  350. }
  351. /* Ok bw and rtt remained the same .. no update to any
  352. */
  353. #if defined(__FreeBSD__) && !defined(__Userspace__)
  354. /* Probe point 7 */
  355. probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
  356. SDT_PROBE5(sctp, cwnd, net, rttvar,
  357. vtag,
  358. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  359. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  360. net->flight_size,
  361. probepoint);
  362. #endif
  363. if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
  364. if (net->cc_mod.rtcc.last_step_state == 5)
  365. net->cc_mod.rtcc.step_cnt++;
  366. else
  367. net->cc_mod.rtcc.step_cnt = 1;
  368. net->cc_mod.rtcc.last_step_state = 5;
  369. if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
  370. ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
  371. ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
  372. /* Try a step down */
  373. if (net->cwnd > (4 * net->mtu)) {
  374. net->cwnd -= net->mtu;
  375. net->cc_mod.rtcc.vol_reduce++;
  376. return (1);
  377. } else {
  378. net->cc_mod.rtcc.step_cnt = 0;
  379. }
  380. }
  381. }
  382. if (inst_ind == SCTP_INST_GAINING)
  383. return (1);
  384. else if (inst_ind == SCTP_INST_NEUTRAL)
  385. return (1);
  386. else
  387. return ((int)net->cc_mod.rtcc.ret_from_eq);
  388. }
  389. #if defined(__FreeBSD__) && !defined(__Userspace__)
  390. static int
  391. cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
  392. uint64_t vtag, uint8_t inst_ind)
  393. #else
  394. static int
  395. cc_bw_decrease(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
  396. uint8_t inst_ind)
  397. #endif
  398. {
  399. #if defined(__FreeBSD__) && !defined(__Userspace__)
  400. uint64_t oth, probepoint;
  401. #endif
  402. /* Bandwidth decreased.*/
  403. #if defined(__FreeBSD__) && !defined(__Userspace__)
  404. probepoint = (((uint64_t)net->cwnd) << 32);
  405. #endif
  406. if (net->rtt > net->cc_mod.rtcc.lbw_rtt+rtt_offset) {
  407. /* rtt increased */
  408. /* Did we add more */
  409. if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
  410. (inst_ind != SCTP_INST_LOOSING)) {
  411. /* We caused it maybe.. back off? */
  412. #if defined(__FreeBSD__) && !defined(__Userspace__)
  413. /* PROBE POINT 1 */
  414. probepoint |= ((1 << 16) | 1);
  415. SDT_PROBE5(sctp, cwnd, net, rttvar,
  416. vtag,
  417. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  418. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  419. net->flight_size,
  420. probepoint);
  421. #endif
  422. if (net->cc_mod.rtcc.ret_from_eq) {
  423. /* Switch over to CA if we are less aggressive */
  424. net->ssthresh = net->cwnd-1;
  425. net->partial_bytes_acked = 0;
  426. }
  427. return (1);
  428. }
  429. #if defined(__FreeBSD__) && !defined(__Userspace__)
  430. /* Probe point 2 */
  431. probepoint |= ((2 << 16) | 0);
  432. SDT_PROBE5(sctp, cwnd, net, rttvar,
  433. vtag,
  434. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  435. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  436. net->flight_size,
  437. probepoint);
  438. #endif
  439. /* Someone else - fight for more? */
  440. if (net->cc_mod.rtcc.steady_step) {
  441. #if defined(__FreeBSD__) && !defined(__Userspace__)
  442. oth = net->cc_mod.rtcc.vol_reduce;
  443. oth <<= 16;
  444. oth |= net->cc_mod.rtcc.step_cnt;
  445. oth <<= 16;
  446. oth |= net->cc_mod.rtcc.last_step_state;
  447. SDT_PROBE5(sctp, cwnd, net, rttstep,
  448. vtag,
  449. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  450. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  451. oth,
  452. probepoint);
  453. #endif
  454. /* Did we voluntarily give up some? if so take
  455. * one back please
  456. */
  457. if ((net->cc_mod.rtcc.vol_reduce) &&
  458. (inst_ind != SCTP_INST_GAINING)) {
  459. net->cwnd += net->mtu;
  460. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  461. net->cc_mod.rtcc.vol_reduce--;
  462. }
  463. net->cc_mod.rtcc.last_step_state = 2;
  464. net->cc_mod.rtcc.step_cnt = 0;
  465. }
  466. goto out_decision;
  467. } else if (net->rtt < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
  468. /* bw & rtt decreased */
  469. #if defined(__FreeBSD__) && !defined(__Userspace__)
  470. /* Probe point 3 */
  471. probepoint |= ((3 << 16) | 0);
  472. SDT_PROBE5(sctp, cwnd, net, rttvar,
  473. vtag,
  474. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  475. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  476. net->flight_size,
  477. probepoint);
  478. #endif
  479. if (net->cc_mod.rtcc.steady_step) {
  480. #if defined(__FreeBSD__) && !defined(__Userspace__)
  481. oth = net->cc_mod.rtcc.vol_reduce;
  482. oth <<= 16;
  483. oth |= net->cc_mod.rtcc.step_cnt;
  484. oth <<= 16;
  485. oth |= net->cc_mod.rtcc.last_step_state;
  486. SDT_PROBE5(sctp, cwnd, net, rttstep,
  487. vtag,
  488. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  489. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  490. oth,
  491. probepoint);
  492. #endif
  493. if ((net->cc_mod.rtcc.vol_reduce) &&
  494. (inst_ind != SCTP_INST_GAINING)) {
  495. net->cwnd += net->mtu;
  496. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  497. net->cc_mod.rtcc.vol_reduce--;
  498. }
  499. net->cc_mod.rtcc.last_step_state = 3;
  500. net->cc_mod.rtcc.step_cnt = 0;
  501. }
  502. goto out_decision;
  503. }
  504. /* The bw decreased but rtt stayed the same */
  505. #if defined(__FreeBSD__) && !defined(__Userspace__)
  506. /* Probe point 4 */
  507. probepoint |= ((4 << 16) | 0);
  508. SDT_PROBE5(sctp, cwnd, net, rttvar,
  509. vtag,
  510. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  511. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  512. net->flight_size,
  513. probepoint);
  514. #endif
  515. if (net->cc_mod.rtcc.steady_step) {
  516. #if defined(__FreeBSD__) && !defined(__Userspace__)
  517. oth = net->cc_mod.rtcc.vol_reduce;
  518. oth <<= 16;
  519. oth |= net->cc_mod.rtcc.step_cnt;
  520. oth <<= 16;
  521. oth |= net->cc_mod.rtcc.last_step_state;
  522. SDT_PROBE5(sctp, cwnd, net, rttstep,
  523. vtag,
  524. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  525. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  526. oth,
  527. probepoint);
  528. #endif
  529. if ((net->cc_mod.rtcc.vol_reduce) &&
  530. (inst_ind != SCTP_INST_GAINING)) {
  531. net->cwnd += net->mtu;
  532. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  533. net->cc_mod.rtcc.vol_reduce--;
  534. }
  535. net->cc_mod.rtcc.last_step_state = 4;
  536. net->cc_mod.rtcc.step_cnt = 0;
  537. }
  538. out_decision:
  539. net->cc_mod.rtcc.lbw = nbw;
  540. net->cc_mod.rtcc.lbw_rtt = net->rtt;
  541. net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
  542. if (inst_ind == SCTP_INST_GAINING) {
  543. return (1);
  544. } else {
  545. return (0);
  546. }
  547. }
  548. #if defined(__FreeBSD__) && !defined(__Userspace__)
  549. static int
  550. cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
  551. #else
  552. static int
  553. cc_bw_increase(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw)
  554. #endif
  555. {
  556. #if defined(__FreeBSD__) && !defined(__Userspace__)
  557. uint64_t oth, probepoint;
  558. #endif
  559. /* BW increased, so update and
  560. * return 0, since all actions in
  561. * our table say to do the normal CC
  562. * update. Note that we pay no attention to
  563. * the inst_ind since our overall sum is increasing.
  564. */
  565. #if defined(__FreeBSD__) && !defined(__Userspace__)
  566. /* PROBE POINT 0 */
  567. probepoint = (((uint64_t)net->cwnd) << 32);
  568. SDT_PROBE5(sctp, cwnd, net, rttvar,
  569. vtag,
  570. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  571. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  572. net->flight_size,
  573. probepoint);
  574. #endif
  575. if (net->cc_mod.rtcc.steady_step) {
  576. #if defined(__FreeBSD__) && !defined(__Userspace__)
  577. oth = net->cc_mod.rtcc.vol_reduce;
  578. oth <<= 16;
  579. oth |= net->cc_mod.rtcc.step_cnt;
  580. oth <<= 16;
  581. oth |= net->cc_mod.rtcc.last_step_state;
  582. SDT_PROBE5(sctp, cwnd, net, rttstep,
  583. vtag,
  584. ((net->cc_mod.rtcc.lbw << 32) | nbw),
  585. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  586. oth,
  587. probepoint);
  588. #endif
  589. net->cc_mod.rtcc.last_step_state = 0;
  590. net->cc_mod.rtcc.step_cnt = 0;
  591. net->cc_mod.rtcc.vol_reduce = 0;
  592. }
  593. net->cc_mod.rtcc.lbw = nbw;
  594. net->cc_mod.rtcc.lbw_rtt = net->rtt;
  595. net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
  596. return (0);
  597. }
  598. /* RTCC Algorithm to limit growth of cwnd, return
  599. * true if you want to NOT allow cwnd growth
  600. */
  601. static int
  602. cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
  603. {
  604. uint64_t bw_offset, rtt_offset;
  605. #if defined(__FreeBSD__) && !defined(__Userspace__)
  606. uint64_t probepoint, rtt, vtag;
  607. #endif
  608. uint64_t bytes_for_this_rtt, inst_bw;
  609. uint64_t div, inst_off;
  610. int bw_shift;
  611. uint8_t inst_ind;
  612. int ret;
  613. /*-
  614. * Here we need to see if we want
  615. * to limit cwnd growth due to increase
  616. * in overall rtt but no increase in bw.
  617. * We use the following table to figure
  618. * out what we should do. When we return
  619. * 0, cc update goes on as planned. If we
  620. * return 1, then no cc update happens and cwnd
  621. * stays where it is at.
  622. * ----------------------------------
  623. * BW | RTT | Action
  624. * *********************************
  625. * INC | INC | return 0
  626. * ----------------------------------
  627. * INC | SAME | return 0
  628. * ----------------------------------
  629. * INC | DECR | return 0
  630. * ----------------------------------
  631. * SAME | INC | return 1
  632. * ----------------------------------
  633. * SAME | SAME | return 1
  634. * ----------------------------------
  635. * SAME | DECR | return 0
  636. * ----------------------------------
  637. * DECR | INC | return 0 or 1 based on if we caused.
  638. * ----------------------------------
  639. * DECR | SAME | return 0
  640. * ----------------------------------
  641. * DECR | DECR | return 0
  642. * ----------------------------------
  643. *
  644. * We are a bit fuzz on what an increase or
  645. * decrease is. For BW it is the same if
  646. * it did not change within 1/64th. For
  647. * RTT it stayed the same if it did not
  648. * change within 1/32nd
  649. */
  650. bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
  651. #if defined(__FreeBSD__) && !defined(__Userspace__)
  652. rtt = stcb->asoc.my_vtag;
  653. vtag = (rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
  654. probepoint = (((uint64_t)net->cwnd) << 32);
  655. rtt = net->rtt;
  656. #endif
  657. if (net->cc_mod.rtcc.rtt_set_this_sack) {
  658. net->cc_mod.rtcc.rtt_set_this_sack = 0;
  659. bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
  660. net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
  661. if (net->rtt) {
  662. div = net->rtt / 1000;
  663. if (div) {
  664. inst_bw = bytes_for_this_rtt / div;
  665. inst_off = inst_bw >> bw_shift;
  666. if (inst_bw > nbw)
  667. inst_ind = SCTP_INST_GAINING;
  668. else if ((inst_bw+inst_off) < nbw)
  669. inst_ind = SCTP_INST_LOOSING;
  670. else
  671. inst_ind = SCTP_INST_NEUTRAL;
  672. #if defined(__FreeBSD__) && !defined(__Userspace__)
  673. probepoint |= ((0xb << 16) | inst_ind);
  674. #endif
  675. } else {
  676. inst_ind = net->cc_mod.rtcc.last_inst_ind;
  677. #if defined(__FreeBSD__) && !defined(__Userspace__)
  678. inst_bw = bytes_for_this_rtt / (uint64_t)(net->rtt);
  679. /* Can't determine do not change */
  680. probepoint |= ((0xc << 16) | inst_ind);
  681. #endif
  682. }
  683. } else {
  684. inst_ind = net->cc_mod.rtcc.last_inst_ind;
  685. #if defined(__FreeBSD__) && !defined(__Userspace__)
  686. inst_bw = bytes_for_this_rtt;
  687. /* Can't determine do not change */
  688. probepoint |= ((0xd << 16) | inst_ind);
  689. #endif
  690. }
  691. #if defined(__FreeBSD__) && !defined(__Userspace__)
  692. SDT_PROBE5(sctp, cwnd, net, rttvar,
  693. vtag,
  694. ((nbw << 32) | inst_bw),
  695. ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
  696. net->flight_size,
  697. probepoint);
  698. #endif
  699. } else {
  700. /* No rtt measurement, use last one */
  701. inst_ind = net->cc_mod.rtcc.last_inst_ind;
  702. }
  703. bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
  704. if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
  705. #if defined(__FreeBSD__) && !defined(__Userspace__)
  706. ret = cc_bw_increase(stcb, net, nbw, vtag);
  707. #else
  708. ret = cc_bw_increase(stcb, net, nbw);
  709. #endif
  710. goto out;
  711. }
  712. rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
  713. if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
  714. #if defined(__FreeBSD__) && !defined(__Userspace__)
  715. ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
  716. #else
  717. ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, inst_ind);
  718. #endif
  719. goto out;
  720. }
  721. /* If we reach here then
  722. * we are in a situation where
  723. * the bw stayed the same.
  724. */
  725. #if defined(__FreeBSD__) && !defined(__Userspace__)
  726. ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
  727. #else
  728. ret = cc_bw_same(stcb, net, nbw, rtt_offset, inst_ind);
  729. #endif
  730. out:
  731. net->cc_mod.rtcc.last_inst_ind = inst_ind;
  732. return (ret);
  733. }
  734. static void
  735. sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
  736. struct sctp_association *asoc,
  737. int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
  738. {
  739. struct sctp_nets *net;
  740. #if defined(__FreeBSD__) && !defined(__Userspace__)
  741. int old_cwnd;
  742. #endif
  743. uint32_t t_ssthresh, incr;
  744. uint64_t t_ucwnd_sbw;
  745. uint64_t t_path_mptcp;
  746. uint64_t mptcp_like_alpha;
  747. uint32_t srtt;
  748. uint64_t max_path;
  749. /* MT FIXME: Don't compute this over and over again */
  750. t_ssthresh = 0;
  751. t_ucwnd_sbw = 0;
  752. t_path_mptcp = 0;
  753. mptcp_like_alpha = 1;
  754. if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
  755. (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
  756. (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
  757. max_path = 0;
  758. TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  759. t_ssthresh += net->ssthresh;
  760. /* lastsa>>3; we don't need to devide ...*/
  761. srtt = net->lastsa;
  762. if (srtt > 0) {
  763. uint64_t tmp;
  764. t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)srtt;
  765. t_path_mptcp += (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
  766. (((uint64_t)net->mtu) * (uint64_t)srtt);
  767. tmp = (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_N) /
  768. ((uint64_t)net->mtu * (uint64_t)(srtt * srtt));
  769. if (tmp > max_path) {
  770. max_path = tmp;
  771. }
  772. }
  773. }
  774. if (t_path_mptcp > 0) {
  775. mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
  776. } else {
  777. mptcp_like_alpha = 1;
  778. }
  779. }
  780. if (t_ssthresh == 0) {
  781. t_ssthresh = 1;
  782. }
  783. if (t_ucwnd_sbw == 0) {
  784. t_ucwnd_sbw = 1;
  785. }
  786. /******************************/
  787. /* update cwnd and Early FR */
  788. /******************************/
  789. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  790. #ifdef JANA_CMT_FAST_RECOVERY
  791. /*
  792. * CMT fast recovery code. Need to debug.
  793. */
  794. if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
  795. if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
  796. SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
  797. net->will_exit_fast_recovery = 1;
  798. }
  799. }
  800. #endif
  801. /* if nothing was acked on this destination skip it */
  802. if (net->net_ack == 0) {
  803. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  804. sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
  805. }
  806. continue;
  807. }
  808. #ifdef JANA_CMT_FAST_RECOVERY
  809. /* CMT fast recovery code
  810. */
  811. /*
  812. if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
  813. @@@ Do something
  814. }
  815. else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
  816. */
  817. #endif
  818. if (asoc->fast_retran_loss_recovery &&
  819. (will_exit == 0) &&
  820. (asoc->sctp_cmt_on_off == 0)) {
  821. /*
  822. * If we are in loss recovery we skip any cwnd
  823. * update
  824. */
  825. return;
  826. }
  827. /*
  828. * Did any measurements go on for this network?
  829. */
  830. if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
  831. uint64_t nbw;
  832. /*
  833. * At this point our bw_bytes has been updated
  834. * by incoming sack information.
  835. *
  836. * But our bw may not yet be set.
  837. *
  838. */
  839. if ((net->cc_mod.rtcc.new_tot_time/1000) > 0) {
  840. nbw = net->cc_mod.rtcc.bw_bytes/(net->cc_mod.rtcc.new_tot_time/1000);
  841. } else {
  842. nbw = net->cc_mod.rtcc.bw_bytes;
  843. }
  844. if (net->cc_mod.rtcc.lbw) {
  845. if (cc_bw_limit(stcb, net, nbw)) {
  846. /* Hold here, no update */
  847. continue;
  848. }
  849. } else {
  850. #if defined(__FreeBSD__) && !defined(__Userspace__)
  851. uint64_t vtag, probepoint;
  852. probepoint = (((uint64_t)net->cwnd) << 32);
  853. probepoint |= ((0xa << 16) | 0);
  854. vtag = (net->rtt << 32) |
  855. (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
  856. (stcb->rport);
  857. SDT_PROBE5(sctp, cwnd, net, rttvar,
  858. vtag,
  859. nbw,
  860. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  861. net->flight_size,
  862. probepoint);
  863. #endif
  864. net->cc_mod.rtcc.lbw = nbw;
  865. net->cc_mod.rtcc.lbw_rtt = net->rtt;
  866. if (net->cc_mod.rtcc.rtt_set_this_sack) {
  867. net->cc_mod.rtcc.rtt_set_this_sack = 0;
  868. net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
  869. }
  870. }
  871. }
  872. /*
  873. * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
  874. * moved.
  875. */
  876. if (accum_moved ||
  877. ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
  878. /* If the cumulative ack moved we can proceed */
  879. if (net->cwnd <= net->ssthresh) {
  880. /* We are in slow start */
  881. if (net->flight_size + net->net_ack >= net->cwnd) {
  882. uint32_t limit;
  883. #if defined(__FreeBSD__) && !defined(__Userspace__)
  884. old_cwnd = net->cwnd;
  885. #endif
  886. switch (asoc->sctp_cmt_on_off) {
  887. case SCTP_CMT_RPV1:
  888. limit = (uint32_t)(((uint64_t)net->mtu *
  889. (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
  890. (uint64_t)net->ssthresh) /
  891. (uint64_t)t_ssthresh);
  892. incr = (uint32_t)(((uint64_t)net->net_ack *
  893. (uint64_t)net->ssthresh) /
  894. (uint64_t)t_ssthresh);
  895. if (incr > limit) {
  896. incr = limit;
  897. }
  898. if (incr == 0) {
  899. incr = 1;
  900. }
  901. break;
  902. case SCTP_CMT_RPV2:
  903. /* lastsa>>3; we don't need to divide ...*/
  904. srtt = net->lastsa;
  905. if (srtt == 0) {
  906. srtt = 1;
  907. }
  908. limit = (uint32_t)(((uint64_t)net->mtu *
  909. (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
  910. (uint64_t)net->cwnd) /
  911. ((uint64_t)srtt * t_ucwnd_sbw));
  912. /* INCREASE FACTOR */
  913. incr = (uint32_t)(((uint64_t)net->net_ack *
  914. (uint64_t)net->cwnd) /
  915. ((uint64_t)srtt * t_ucwnd_sbw));
  916. /* INCREASE FACTOR */
  917. if (incr > limit) {
  918. incr = limit;
  919. }
  920. if (incr == 0) {
  921. incr = 1;
  922. }
  923. break;
  924. case SCTP_CMT_MPTCP:
  925. limit = (uint32_t)(((uint64_t)net->mtu *
  926. mptcp_like_alpha *
  927. (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
  928. SHIFT_MPTCP_MULTI);
  929. incr = (uint32_t)(((uint64_t)net->net_ack *
  930. mptcp_like_alpha) >>
  931. SHIFT_MPTCP_MULTI);
  932. if (incr > limit) {
  933. incr = limit;
  934. }
  935. if (incr > net->net_ack) {
  936. incr = net->net_ack;
  937. }
  938. if (incr > net->mtu) {
  939. incr = net->mtu;
  940. }
  941. break;
  942. default:
  943. incr = net->net_ack;
  944. if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
  945. incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
  946. }
  947. break;
  948. }
  949. net->cwnd += incr;
  950. sctp_enforce_cwnd_limit(asoc, net);
  951. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  952. sctp_log_cwnd(stcb, net, incr,
  953. SCTP_CWND_LOG_FROM_SS);
  954. }
  955. #if defined(__FreeBSD__) && !defined(__Userspace__)
  956. SDT_PROBE5(sctp, cwnd, net, ack,
  957. stcb->asoc.my_vtag,
  958. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  959. net,
  960. old_cwnd, net->cwnd);
  961. #endif
  962. } else {
  963. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  964. sctp_log_cwnd(stcb, net, net->net_ack,
  965. SCTP_CWND_LOG_NOADV_SS);
  966. }
  967. }
  968. } else {
  969. /* We are in congestion avoidance */
  970. /*
  971. * Add to pba
  972. */
  973. net->partial_bytes_acked += net->net_ack;
  974. if ((net->flight_size + net->net_ack >= net->cwnd) &&
  975. (net->partial_bytes_acked >= net->cwnd)) {
  976. net->partial_bytes_acked -= net->cwnd;
  977. #if defined(__FreeBSD__) && !defined(__Userspace__)
  978. old_cwnd = net->cwnd;
  979. #endif
  980. switch (asoc->sctp_cmt_on_off) {
  981. case SCTP_CMT_RPV1:
  982. incr = (uint32_t)(((uint64_t)net->mtu *
  983. (uint64_t)net->ssthresh) /
  984. (uint64_t)t_ssthresh);
  985. if (incr == 0) {
  986. incr = 1;
  987. }
  988. break;
  989. case SCTP_CMT_RPV2:
  990. /* lastsa>>3; we don't need to divide ... */
  991. srtt = net->lastsa;
  992. if (srtt == 0) {
  993. srtt = 1;
  994. }
  995. incr = (uint32_t)((uint64_t)net->mtu *
  996. (uint64_t)net->cwnd /
  997. ((uint64_t)srtt *
  998. t_ucwnd_sbw));
  999. /* INCREASE FACTOR */
  1000. if (incr == 0) {
  1001. incr = 1;
  1002. }
  1003. break;
  1004. case SCTP_CMT_MPTCP:
  1005. incr = (uint32_t)((mptcp_like_alpha *
  1006. (uint64_t) net->cwnd) >>
  1007. SHIFT_MPTCP_MULTI);
  1008. if (incr > net->mtu) {
  1009. incr = net->mtu;
  1010. }
  1011. break;
  1012. default:
  1013. incr = net->mtu;
  1014. break;
  1015. }
  1016. net->cwnd += incr;
  1017. sctp_enforce_cwnd_limit(asoc, net);
  1018. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1019. SDT_PROBE5(sctp, cwnd, net, ack,
  1020. stcb->asoc.my_vtag,
  1021. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  1022. net,
  1023. old_cwnd, net->cwnd);
  1024. #endif
  1025. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1026. sctp_log_cwnd(stcb, net, net->mtu,
  1027. SCTP_CWND_LOG_FROM_CA);
  1028. }
  1029. } else {
  1030. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1031. sctp_log_cwnd(stcb, net, net->net_ack,
  1032. SCTP_CWND_LOG_NOADV_CA);
  1033. }
  1034. }
  1035. }
  1036. } else {
  1037. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1038. sctp_log_cwnd(stcb, net, net->mtu,
  1039. SCTP_CWND_LOG_NO_CUMACK);
  1040. }
  1041. }
  1042. }
  1043. }
  1044. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1045. static void
  1046. sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
  1047. #else
  1048. static void
  1049. sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net)
  1050. #endif
  1051. {
  1052. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1053. int old_cwnd;
  1054. old_cwnd = net->cwnd;
  1055. #endif
  1056. net->cwnd = net->mtu;
  1057. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1058. SDT_PROBE5(sctp, cwnd, net, ack,
  1059. stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
  1060. old_cwnd, net->cwnd);
  1061. #endif
  1062. SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
  1063. (void *)net, net->cwnd);
  1064. }
  1065. static void
  1066. sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
  1067. {
  1068. int old_cwnd = net->cwnd;
  1069. uint32_t t_ssthresh, t_cwnd;
  1070. uint64_t t_ucwnd_sbw;
  1071. /* MT FIXME: Don't compute this over and over again */
  1072. t_ssthresh = 0;
  1073. t_cwnd = 0;
  1074. if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
  1075. (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
  1076. struct sctp_nets *lnet;
  1077. uint32_t srtt;
  1078. t_ucwnd_sbw = 0;
  1079. TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
  1080. t_ssthresh += lnet->ssthresh;
  1081. t_cwnd += lnet->cwnd;
  1082. srtt = lnet->lastsa;
  1083. /* lastsa>>3; we don't need to divide ... */
  1084. if (srtt > 0) {
  1085. t_ucwnd_sbw += (uint64_t)lnet->cwnd / (uint64_t)srtt;
  1086. }
  1087. }
  1088. if (t_ssthresh < 1) {
  1089. t_ssthresh = 1;
  1090. }
  1091. if (t_ucwnd_sbw < 1) {
  1092. t_ucwnd_sbw = 1;
  1093. }
  1094. if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
  1095. net->ssthresh = (uint32_t)(((uint64_t)4 *
  1096. (uint64_t)net->mtu *
  1097. (uint64_t)net->ssthresh) /
  1098. (uint64_t)t_ssthresh);
  1099. } else {
  1100. uint64_t cc_delta;
  1101. srtt = net->lastsa;
  1102. /* lastsa>>3; we don't need to divide ... */
  1103. if (srtt == 0) {
  1104. srtt = 1;
  1105. }
  1106. cc_delta = t_ucwnd_sbw * (uint64_t)srtt / 2;
  1107. if (cc_delta < t_cwnd) {
  1108. net->ssthresh = (uint32_t)((uint64_t)t_cwnd - cc_delta);
  1109. } else {
  1110. net->ssthresh = net->mtu;
  1111. }
  1112. }
  1113. if ((net->cwnd > t_cwnd / 2) &&
  1114. (net->ssthresh < net->cwnd - t_cwnd / 2)) {
  1115. net->ssthresh = net->cwnd - t_cwnd / 2;
  1116. }
  1117. if (net->ssthresh < net->mtu) {
  1118. net->ssthresh = net->mtu;
  1119. }
  1120. } else {
  1121. net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
  1122. }
  1123. net->cwnd = net->mtu;
  1124. net->partial_bytes_acked = 0;
  1125. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1126. SDT_PROBE5(sctp, cwnd, net, to,
  1127. stcb->asoc.my_vtag,
  1128. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  1129. net,
  1130. old_cwnd, net->cwnd);
  1131. #endif
  1132. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1133. sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
  1134. }
  1135. }
  1136. static void
  1137. sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
  1138. int in_window, int num_pkt_lost, int use_rtcc)
  1139. {
  1140. int old_cwnd = net->cwnd;
  1141. if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
  1142. /* Data center Congestion Control */
  1143. if (in_window == 0) {
  1144. /* Go to CA with the cwnd at the point we sent
  1145. * the TSN that was marked with a CE.
  1146. */
  1147. if (net->ecn_prev_cwnd < net->cwnd) {
  1148. /* Restore to prev cwnd */
  1149. net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
  1150. } else {
  1151. /* Just cut in 1/2 */
  1152. net->cwnd /= 2;
  1153. }
  1154. /* Drop to CA */
  1155. net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
  1156. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1157. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
  1158. }
  1159. } else {
  1160. /* Further tuning down required over the drastic original cut */
  1161. net->ssthresh -= (net->mtu * num_pkt_lost);
  1162. net->cwnd -= (net->mtu * num_pkt_lost);
  1163. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1164. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
  1165. }
  1166. }
  1167. SCTP_STAT_INCR(sctps_ecnereducedcwnd);
  1168. } else {
  1169. if (in_window == 0) {
  1170. SCTP_STAT_INCR(sctps_ecnereducedcwnd);
  1171. net->ssthresh = net->cwnd / 2;
  1172. if (net->ssthresh < net->mtu) {
  1173. net->ssthresh = net->mtu;
  1174. /* here back off the timer as well, to slow us down */
  1175. net->RTO <<= 1;
  1176. }
  1177. net->cwnd = net->ssthresh;
  1178. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1179. SDT_PROBE5(sctp, cwnd, net, ecn,
  1180. stcb->asoc.my_vtag,
  1181. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  1182. net,
  1183. old_cwnd, net->cwnd);
  1184. #endif
  1185. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1186. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
  1187. }
  1188. }
  1189. }
  1190. }
  1191. static void
  1192. sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
  1193. struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
  1194. uint32_t *bottle_bw, uint32_t *on_queue)
  1195. {
  1196. uint32_t bw_avail;
  1197. unsigned int incr;
  1198. int old_cwnd = net->cwnd;
  1199. /* get bottle neck bw */
  1200. *bottle_bw = ntohl(cp->bottle_bw);
  1201. /* and whats on queue */
  1202. *on_queue = ntohl(cp->current_onq);
  1203. /*
  1204. * adjust the on-queue if our flight is more it could be
  1205. * that the router has not yet gotten data "in-flight" to it
  1206. */
  1207. if (*on_queue < net->flight_size) {
  1208. *on_queue = net->flight_size;
  1209. }
  1210. /* rtt is measured in micro seconds, bottle_bw in bytes per second */
  1211. bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
  1212. if (bw_avail > *bottle_bw) {
  1213. /*
  1214. * Cap the growth to no more than the bottle neck.
  1215. * This can happen as RTT slides up due to queues.
  1216. * It also means if you have more than a 1 second
  1217. * RTT with a empty queue you will be limited to the
  1218. * bottle_bw per second no matter if other points
  1219. * have 1/2 the RTT and you could get more out...
  1220. */
  1221. bw_avail = *bottle_bw;
  1222. }
  1223. if (*on_queue > bw_avail) {
  1224. /*
  1225. * No room for anything else don't allow anything
  1226. * else to be "added to the fire".
  1227. */
  1228. int seg_inflight, seg_onqueue, my_portion;
  1229. net->partial_bytes_acked = 0;
  1230. /* how much are we over queue size? */
  1231. incr = *on_queue - bw_avail;
  1232. if (stcb->asoc.seen_a_sack_this_pkt) {
  1233. /*
  1234. * undo any cwnd adjustment that the sack
  1235. * might have made
  1236. */
  1237. net->cwnd = net->prev_cwnd;
  1238. }
  1239. /* Now how much of that is mine? */
  1240. seg_inflight = net->flight_size / net->mtu;
  1241. seg_onqueue = *on_queue / net->mtu;
  1242. my_portion = (incr * seg_inflight) / seg_onqueue;
  1243. /* Have I made an adjustment already */
  1244. if (net->cwnd > net->flight_size) {
  1245. /*
  1246. * for this flight I made an adjustment we
  1247. * need to decrease the portion by a share
  1248. * our previous adjustment.
  1249. */
  1250. int diff_adj;
  1251. diff_adj = net->cwnd - net->flight_size;
  1252. if (diff_adj > my_portion)
  1253. my_portion = 0;
  1254. else
  1255. my_portion -= diff_adj;
  1256. }
  1257. /*
  1258. * back down to the previous cwnd (assume we have
  1259. * had a sack before this packet). minus what ever
  1260. * portion of the overage is my fault.
  1261. */
  1262. net->cwnd -= my_portion;
  1263. /* we will NOT back down more than 1 MTU */
  1264. if (net->cwnd <= net->mtu) {
  1265. net->cwnd = net->mtu;
  1266. }
  1267. /* force into CA */
  1268. net->ssthresh = net->cwnd - 1;
  1269. } else {
  1270. /*
  1271. * Take 1/4 of the space left or max burst up ..
  1272. * whichever is less.
  1273. */
  1274. incr = (bw_avail - *on_queue) >> 2;
  1275. if ((stcb->asoc.max_burst > 0) &&
  1276. (stcb->asoc.max_burst * net->mtu < incr)) {
  1277. incr = stcb->asoc.max_burst * net->mtu;
  1278. }
  1279. net->cwnd += incr;
  1280. }
  1281. if (net->cwnd > bw_avail) {
  1282. /* We can't exceed the pipe size */
  1283. net->cwnd = bw_avail;
  1284. }
  1285. if (net->cwnd < net->mtu) {
  1286. /* We always have 1 MTU */
  1287. net->cwnd = net->mtu;
  1288. }
  1289. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  1290. if (net->cwnd - old_cwnd != 0) {
  1291. /* log only changes */
  1292. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1293. SDT_PROBE5(sctp, cwnd, net, pd,
  1294. stcb->asoc.my_vtag,
  1295. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  1296. net,
  1297. old_cwnd, net->cwnd);
  1298. #endif
  1299. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1300. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
  1301. SCTP_CWND_LOG_FROM_SAT);
  1302. }
  1303. }
  1304. }
  1305. static void
  1306. sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
  1307. struct sctp_nets *net, int burst_limit)
  1308. {
  1309. int old_cwnd = net->cwnd;
  1310. if (net->ssthresh < net->cwnd)
  1311. net->ssthresh = net->cwnd;
  1312. if (burst_limit) {
  1313. net->cwnd = (net->flight_size + (burst_limit * net->mtu));
  1314. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  1315. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1316. SDT_PROBE5(sctp, cwnd, net, bl,
  1317. stcb->asoc.my_vtag,
  1318. ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
  1319. net,
  1320. old_cwnd, net->cwnd);
  1321. #endif
  1322. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1323. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
  1324. }
  1325. }
  1326. }
  1327. static void
  1328. sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
  1329. struct sctp_association *asoc,
  1330. int accum_moved, int reneged_all, int will_exit)
  1331. {
  1332. /* Passing a zero argument in last disables the rtcc algorithm */
  1333. sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
  1334. }
  1335. static void
  1336. sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
  1337. int in_window, int num_pkt_lost)
  1338. {
  1339. /* Passing a zero argument in last disables the rtcc algorithm */
  1340. sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
  1341. }
  1342. /* Here starts the RTCCVAR type CC invented by RRS which
  1343. * is a slight mod to RFC2581. We reuse a common routine or
  1344. * two since these algorithms are so close and need to
  1345. * remain the same.
  1346. */
  1347. static void
  1348. sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
  1349. int in_window, int num_pkt_lost)
  1350. {
  1351. sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
  1352. }
  1353. static void sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
  1354. struct sctp_tmit_chunk *tp1)
  1355. {
  1356. net->cc_mod.rtcc.bw_bytes += tp1->send_size;
  1357. }
  1358. static void
  1359. sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
  1360. struct sctp_nets *net)
  1361. {
  1362. if (net->cc_mod.rtcc.tls_needs_set > 0) {
  1363. /* We had a bw measurement going on */
  1364. struct timeval ltls;
  1365. SCTP_GETPTIME_TIMEVAL(&ltls);
  1366. timevalsub(&ltls, &net->cc_mod.rtcc.tls);
  1367. net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
  1368. }
  1369. }
  1370. static void
  1371. sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
  1372. struct sctp_nets *net)
  1373. {
  1374. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1375. uint64_t vtag, probepoint;
  1376. #endif
  1377. if (net->cc_mod.rtcc.lbw) {
  1378. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1379. /* Clear the old bw.. we went to 0 in-flight */
  1380. vtag = (net->rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
  1381. (stcb->rport);
  1382. probepoint = (((uint64_t)net->cwnd) << 32);
  1383. /* Probe point 8 */
  1384. probepoint |= ((8 << 16) | 0);
  1385. SDT_PROBE5(sctp, cwnd, net, rttvar,
  1386. vtag,
  1387. ((net->cc_mod.rtcc.lbw << 32) | 0),
  1388. ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
  1389. net->flight_size,
  1390. probepoint);
  1391. #endif
  1392. net->cc_mod.rtcc.lbw_rtt = 0;
  1393. net->cc_mod.rtcc.cwnd_at_bw_set = 0;
  1394. net->cc_mod.rtcc.lbw = 0;
  1395. net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
  1396. net->cc_mod.rtcc.vol_reduce = 0;
  1397. net->cc_mod.rtcc.bw_tot_time = 0;
  1398. net->cc_mod.rtcc.bw_bytes = 0;
  1399. net->cc_mod.rtcc.tls_needs_set = 0;
  1400. if (net->cc_mod.rtcc.steady_step) {
  1401. net->cc_mod.rtcc.vol_reduce = 0;
  1402. net->cc_mod.rtcc.step_cnt = 0;
  1403. net->cc_mod.rtcc.last_step_state = 0;
  1404. }
  1405. if (net->cc_mod.rtcc.ret_from_eq) {
  1406. /* less aggressive one - reset cwnd too */
  1407. uint32_t cwnd_in_mtu, cwnd;
  1408. cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
  1409. if (cwnd_in_mtu == 0) {
  1410. /* Using 0 means that the value of RFC 4960 is used. */
  1411. cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
  1412. } else {
  1413. /*
  1414. * We take the minimum of the burst limit and the
  1415. * initial congestion window.
  1416. */
  1417. if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
  1418. cwnd_in_mtu = stcb->asoc.max_burst;
  1419. cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
  1420. }
  1421. if (net->cwnd > cwnd) {
  1422. /* Only set if we are not a timeout (i.e. down to 1 mtu) */
  1423. net->cwnd = cwnd;
  1424. }
  1425. }
  1426. }
  1427. }
  1428. static void
  1429. sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
  1430. struct sctp_nets *net)
  1431. {
  1432. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1433. uint64_t vtag, probepoint;
  1434. #endif
  1435. sctp_set_initial_cc_param(stcb, net);
  1436. stcb->asoc.use_precise_time = 1;
  1437. #if defined(__FreeBSD__) && !defined(__Userspace__)
  1438. probepoint = (((uint64_t)net->cwnd) << 32);
  1439. probepoint |= ((9 << 16) | 0);
  1440. vtag = (net->rtt << 32) |
  1441. (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
  1442. (stcb->rport);
  1443. SDT_PROBE5(sctp, cwnd, net, rttvar,
  1444. vtag,
  1445. 0,
  1446. 0,
  1447. 0,
  1448. probepoint);
  1449. #endif
  1450. net->cc_mod.rtcc.lbw_rtt = 0;
  1451. net->cc_mod.rtcc.cwnd_at_bw_set = 0;
  1452. net->cc_mod.rtcc.vol_reduce = 0;
  1453. net->cc_mod.rtcc.lbw = 0;
  1454. net->cc_mod.rtcc.vol_reduce = 0;
  1455. net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
  1456. net->cc_mod.rtcc.bw_tot_time = 0;
  1457. net->cc_mod.rtcc.bw_bytes = 0;
  1458. net->cc_mod.rtcc.tls_needs_set = 0;
  1459. net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
  1460. net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
  1461. net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
  1462. net->cc_mod.rtcc.step_cnt = 0;
  1463. net->cc_mod.rtcc.last_step_state = 0;
  1464. }
  1465. static int
  1466. sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
  1467. struct sctp_cc_option *cc_opt)
  1468. {
  1469. struct sctp_nets *net;
  1470. if (setorget == 1) {
  1471. /* a set */
  1472. if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
  1473. if ((cc_opt->aid_value.assoc_value != 0) &&
  1474. (cc_opt->aid_value.assoc_value != 1)) {
  1475. return (EINVAL);
  1476. }
  1477. TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1478. net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
  1479. }
  1480. } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
  1481. if ((cc_opt->aid_value.assoc_value != 0) &&
  1482. (cc_opt->aid_value.assoc_value != 1)) {
  1483. return (EINVAL);
  1484. }
  1485. TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1486. net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
  1487. }
  1488. } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
  1489. TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
  1490. net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
  1491. }
  1492. } else {
  1493. return (EINVAL);
  1494. }
  1495. } else {
  1496. /* a get */
  1497. if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
  1498. net = TAILQ_FIRST(&stcb->asoc.nets);
  1499. if (net == NULL) {
  1500. return (EFAULT);
  1501. }
  1502. cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
  1503. } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
  1504. net = TAILQ_FIRST(&stcb->asoc.nets);
  1505. if (net == NULL) {
  1506. return (EFAULT);
  1507. }
  1508. cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
  1509. } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
  1510. net = TAILQ_FIRST(&stcb->asoc.nets);
  1511. if (net == NULL) {
  1512. return (EFAULT);
  1513. }
  1514. cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
  1515. } else {
  1516. return (EINVAL);
  1517. }
  1518. }
  1519. return (0);
  1520. }
  1521. static void
  1522. sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
  1523. struct sctp_nets *net)
  1524. {
  1525. if (net->cc_mod.rtcc.tls_needs_set == 0) {
  1526. SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
  1527. net->cc_mod.rtcc.tls_needs_set = 2;
  1528. }
  1529. }
  1530. static void
  1531. sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
  1532. struct sctp_association *asoc,
  1533. int accum_moved, int reneged_all, int will_exit)
  1534. {
  1535. /* Passing a one argument at the last enables the rtcc algorithm */
  1536. sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
  1537. }
  1538. static void
  1539. sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
  1540. struct sctp_nets *net,
  1541. struct timeval *now SCTP_UNUSED)
  1542. {
  1543. net->cc_mod.rtcc.rtt_set_this_sack = 1;
  1544. }
  1545. /* Here starts Sally Floyds HS-TCP */
  1546. struct sctp_hs_raise_drop {
  1547. int32_t cwnd;
  1548. int8_t increase;
  1549. int8_t drop_percent;
  1550. };
  1551. #define SCTP_HS_TABLE_SIZE 73
  1552. static const struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
  1553. {38, 1, 50}, /* 0 */
  1554. {118, 2, 44}, /* 1 */
  1555. {221, 3, 41}, /* 2 */
  1556. {347, 4, 38}, /* 3 */
  1557. {495, 5, 37}, /* 4 */
  1558. {663, 6, 35}, /* 5 */
  1559. {851, 7, 34}, /* 6 */
  1560. {1058, 8, 33}, /* 7 */
  1561. {1284, 9, 32}, /* 8 */
  1562. {1529, 10, 31}, /* 9 */
  1563. {1793, 11, 30}, /* 10 */
  1564. {2076, 12, 29}, /* 11 */
  1565. {2378, 13, 28}, /* 12 */
  1566. {2699, 14, 28}, /* 13 */
  1567. {3039, 15, 27}, /* 14 */
  1568. {3399, 16, 27}, /* 15 */
  1569. {3778, 17, 26}, /* 16 */
  1570. {4177, 18, 26}, /* 17 */
  1571. {4596, 19, 25}, /* 18 */
  1572. {5036, 20, 25}, /* 19 */
  1573. {5497, 21, 24}, /* 20 */
  1574. {5979, 22, 24}, /* 21 */
  1575. {6483, 23, 23}, /* 22 */
  1576. {7009, 24, 23}, /* 23 */
  1577. {7558, 25, 22}, /* 24 */
  1578. {8130, 26, 22}, /* 25 */
  1579. {8726, 27, 22}, /* 26 */
  1580. {9346, 28, 21}, /* 27 */
  1581. {9991, 29, 21}, /* 28 */
  1582. {10661, 30, 21}, /* 29 */
  1583. {11358, 31, 20}, /* 30 */
  1584. {12082, 32, 20}, /* 31 */
  1585. {12834, 33, 20}, /* 32 */
  1586. {13614, 34, 19}, /* 33 */
  1587. {14424, 35, 19}, /* 34 */
  1588. {15265, 36, 19}, /* 35 */
  1589. {16137, 37, 19}, /* 36 */
  1590. {17042, 38, 18}, /* 37 */
  1591. {17981, 39, 18}, /* 38 */
  1592. {18955, 40, 18}, /* 39 */
  1593. {19965, 41, 17}, /* 40 */
  1594. {21013, 42, 17}, /* 41 */
  1595. {22101, 43, 17}, /* 42 */
  1596. {23230, 44, 17}, /* 43 */
  1597. {24402, 45, 16}, /* 44 */
  1598. {25618, 46, 16}, /* 45 */
  1599. {26881, 47, 16}, /* 46 */
  1600. {28193, 48, 16}, /* 47 */
  1601. {29557, 49, 15}, /* 48 */
  1602. {30975, 50, 15}, /* 49 */
  1603. {32450, 51, 15}, /* 50 */
  1604. {33986, 52, 15}, /* 51 */
  1605. {35586, 53, 14}, /* 52 */
  1606. {37253, 54, 14}, /* 53 */
  1607. {38992, 55, 14}, /* 54 */
  1608. {40808, 56, 14}, /* 55 */
  1609. {42707, 57, 13}, /* 56 */
  1610. {44694, 58, 13}, /* 57 */
  1611. {46776, 59, 13}, /* 58 */
  1612. {48961, 60, 13}, /* 59 */
  1613. {51258, 61, 13}, /* 60 */
  1614. {53677, 62, 12}, /* 61 */
  1615. {56230, 63, 12}, /* 62 */
  1616. {58932, 64, 12}, /* 63 */
  1617. {61799, 65, 12}, /* 64 */
  1618. {64851, 66, 11}, /* 65 */
  1619. {68113, 67, 11}, /* 66 */
  1620. {71617, 68, 11}, /* 67 */
  1621. {75401, 69, 10}, /* 68 */
  1622. {79517, 70, 10}, /* 69 */
  1623. {84035, 71, 10}, /* 70 */
  1624. {89053, 72, 10}, /* 71 */
  1625. {94717, 73, 9} /* 72 */
  1626. };
  1627. static void
  1628. sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
  1629. {
  1630. int cur_val, i, indx, incr;
  1631. int old_cwnd = net->cwnd;
  1632. cur_val = net->cwnd >> 10;
  1633. indx = SCTP_HS_TABLE_SIZE - 1;
  1634. if (cur_val < sctp_cwnd_adjust[0].cwnd) {
  1635. /* normal mode */
  1636. if (net->net_ack > net->mtu) {
  1637. net->cwnd += net->mtu;
  1638. } else {
  1639. net->cwnd += net->net_ack;
  1640. }
  1641. } else {
  1642. for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
  1643. if (cur_val < sctp_cwnd_adjust[i].cwnd) {
  1644. indx = i;
  1645. break;
  1646. }
  1647. }
  1648. net->last_hs_used = indx;
  1649. incr = (((int32_t)sctp_cwnd_adjust[indx].increase) << 10);
  1650. net->cwnd += incr;
  1651. }
  1652. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  1653. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1654. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SS);
  1655. }
  1656. }
  1657. static void
  1658. sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
  1659. {
  1660. int cur_val, i, indx;
  1661. int old_cwnd = net->cwnd;
  1662. cur_val = net->cwnd >> 10;
  1663. if (cur_val < sctp_cwnd_adjust[0].cwnd) {
  1664. /* normal mode */
  1665. net->ssthresh = net->cwnd / 2;
  1666. if (net->ssthresh < (net->mtu * 2)) {
  1667. net->ssthresh = 2 * net->mtu;
  1668. }
  1669. net->cwnd = net->ssthresh;
  1670. } else {
  1671. /* drop by the proper amount */
  1672. net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
  1673. (int32_t)sctp_cwnd_adjust[net->last_hs_used].drop_percent);
  1674. net->cwnd = net->ssthresh;
  1675. /* now where are we */
  1676. indx = net->last_hs_used;
  1677. cur_val = net->cwnd >> 10;
  1678. /* reset where we are in the table */
  1679. if (cur_val < sctp_cwnd_adjust[0].cwnd) {
  1680. /* feel out of hs */
  1681. net->last_hs_used = 0;
  1682. } else {
  1683. for (i = indx; i >= 1; i--) {
  1684. if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
  1685. break;
  1686. }
  1687. }
  1688. net->last_hs_used = indx;
  1689. }
  1690. }
  1691. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  1692. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1693. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
  1694. }
  1695. }
  1696. static void
  1697. sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
  1698. struct sctp_association *asoc)
  1699. {
  1700. struct sctp_nets *net;
  1701. /*
  1702. * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
  1703. * (net->fast_retran_loss_recovery == 0)))
  1704. */
  1705. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  1706. if ((asoc->fast_retran_loss_recovery == 0) ||
  1707. (asoc->sctp_cmt_on_off > 0)) {
  1708. /* out of a RFC2582 Fast recovery window? */
  1709. if (net->net_ack > 0) {
  1710. /*
  1711. * per section 7.2.3, are there any
  1712. * destinations that had a fast retransmit
  1713. * to them. If so what we need to do is
  1714. * adjust ssthresh and cwnd.
  1715. */
  1716. struct sctp_tmit_chunk *lchk;
  1717. sctp_hs_cwnd_decrease(stcb, net);
  1718. lchk = TAILQ_FIRST(&asoc->send_queue);
  1719. net->partial_bytes_acked = 0;
  1720. /* Turn on fast recovery window */
  1721. asoc->fast_retran_loss_recovery = 1;
  1722. if (lchk == NULL) {
  1723. /* Mark end of the window */
  1724. asoc->fast_recovery_tsn = asoc->sending_seq - 1;
  1725. } else {
  1726. asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  1727. }
  1728. /*
  1729. * CMT fast recovery -- per destination
  1730. * recovery variable.
  1731. */
  1732. net->fast_retran_loss_recovery = 1;
  1733. if (lchk == NULL) {
  1734. /* Mark end of the window */
  1735. net->fast_recovery_tsn = asoc->sending_seq - 1;
  1736. } else {
  1737. net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  1738. }
  1739. sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
  1740. stcb->sctp_ep, stcb, net,
  1741. SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_2);
  1742. sctp_timer_start(SCTP_TIMER_TYPE_SEND,
  1743. stcb->sctp_ep, stcb, net);
  1744. }
  1745. } else if (net->net_ack > 0) {
  1746. /*
  1747. * Mark a peg that we WOULD have done a cwnd
  1748. * reduction but RFC2582 prevented this action.
  1749. */
  1750. SCTP_STAT_INCR(sctps_fastretransinrtt);
  1751. }
  1752. }
  1753. }
  1754. static void
  1755. sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
  1756. struct sctp_association *asoc,
  1757. int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
  1758. {
  1759. struct sctp_nets *net;
  1760. /******************************/
  1761. /* update cwnd and Early FR */
  1762. /******************************/
  1763. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  1764. #ifdef JANA_CMT_FAST_RECOVERY
  1765. /*
  1766. * CMT fast recovery code. Need to debug.
  1767. */
  1768. if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
  1769. if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
  1770. SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
  1771. net->will_exit_fast_recovery = 1;
  1772. }
  1773. }
  1774. #endif
  1775. /* if nothing was acked on this destination skip it */
  1776. if (net->net_ack == 0) {
  1777. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1778. sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
  1779. }
  1780. continue;
  1781. }
  1782. #ifdef JANA_CMT_FAST_RECOVERY
  1783. /* CMT fast recovery code
  1784. */
  1785. /*
  1786. if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
  1787. @@@ Do something
  1788. }
  1789. else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
  1790. */
  1791. #endif
  1792. if (asoc->fast_retran_loss_recovery &&
  1793. (will_exit == 0) &&
  1794. (asoc->sctp_cmt_on_off == 0)) {
  1795. /*
  1796. * If we are in loss recovery we skip any cwnd
  1797. * update
  1798. */
  1799. return;
  1800. }
  1801. /*
  1802. * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
  1803. * moved.
  1804. */
  1805. if (accum_moved ||
  1806. ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
  1807. /* If the cumulative ack moved we can proceed */
  1808. if (net->cwnd <= net->ssthresh) {
  1809. /* We are in slow start */
  1810. if (net->flight_size + net->net_ack >= net->cwnd) {
  1811. sctp_hs_cwnd_increase(stcb, net);
  1812. } else {
  1813. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1814. sctp_log_cwnd(stcb, net, net->net_ack,
  1815. SCTP_CWND_LOG_NOADV_SS);
  1816. }
  1817. }
  1818. } else {
  1819. /* We are in congestion avoidance */
  1820. net->partial_bytes_acked += net->net_ack;
  1821. if ((net->flight_size + net->net_ack >= net->cwnd) &&
  1822. (net->partial_bytes_acked >= net->cwnd)) {
  1823. net->partial_bytes_acked -= net->cwnd;
  1824. net->cwnd += net->mtu;
  1825. sctp_enforce_cwnd_limit(asoc, net);
  1826. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  1827. sctp_log_cwnd(stcb, net, net->mtu,
  1828. SCTP_CWND_LOG_FROM_CA);
  1829. }
  1830. } else {
  1831. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1832. sctp_log_cwnd(stcb, net, net->net_ack,
  1833. SCTP_CWND_LOG_NOADV_CA);
  1834. }
  1835. }
  1836. }
  1837. } else {
  1838. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  1839. sctp_log_cwnd(stcb, net, net->mtu,
  1840. SCTP_CWND_LOG_NO_CUMACK);
  1841. }
  1842. }
  1843. }
  1844. }
  1845. /*
  1846. * H-TCP congestion control. The algorithm is detailed in:
  1847. * R.N.Shorten, D.J.Leith:
  1848. * "H-TCP: TCP for high-speed and long-distance networks"
  1849. * Proc. PFLDnet, Argonne, 2004.
  1850. * http://www.hamilton.ie/net/htcp3.pdf
  1851. */
  1852. static int use_rtt_scaling = 1;
  1853. static int use_bandwidth_switch = 1;
  1854. static inline int
  1855. between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
  1856. {
  1857. return (seq3 - seq2 >= seq1 - seq2);
  1858. }
  1859. static inline uint32_t
  1860. htcp_cong_time(struct htcp *ca)
  1861. {
  1862. return (sctp_get_tick_count() - ca->last_cong);
  1863. }
  1864. static inline uint32_t
  1865. htcp_ccount(struct htcp *ca)
  1866. {
  1867. return (ca->minRTT == 0 ? htcp_cong_time(ca) : htcp_cong_time(ca)/ca->minRTT);
  1868. }
  1869. static inline void
  1870. htcp_reset(struct htcp *ca)
  1871. {
  1872. ca->undo_last_cong = ca->last_cong;
  1873. ca->undo_maxRTT = ca->maxRTT;
  1874. ca->undo_old_maxB = ca->old_maxB;
  1875. ca->last_cong = sctp_get_tick_count();
  1876. }
  1877. #ifdef SCTP_NOT_USED
  1878. static uint32_t
  1879. htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
  1880. {
  1881. net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
  1882. net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
  1883. net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
  1884. return (max(net->cwnd, ((net->ssthresh/net->mtu<<7)/net->cc_mod.htcp_ca.beta)*net->mtu));
  1885. }
  1886. #endif
  1887. static inline void
  1888. measure_rtt(struct sctp_nets *net)
  1889. {
  1890. uint32_t srtt = net->lastsa>>SCTP_RTT_SHIFT;
  1891. /* keep track of minimum RTT seen so far, minRTT is zero at first */
  1892. if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
  1893. net->cc_mod.htcp_ca.minRTT = srtt;
  1894. /* max RTT */
  1895. if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
  1896. if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
  1897. net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
  1898. if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT+sctp_msecs_to_ticks(20))
  1899. net->cc_mod.htcp_ca.maxRTT = srtt;
  1900. }
  1901. }
  1902. static void
  1903. measure_achieved_throughput(struct sctp_nets *net)
  1904. {
  1905. uint32_t now = sctp_get_tick_count();
  1906. if (net->fast_retran_ip == 0)
  1907. net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
  1908. if (!use_bandwidth_switch)
  1909. return;
  1910. /* achieved throughput calculations */
  1911. /* JRS - not 100% sure of this statement */
  1912. if (net->fast_retran_ip == 1) {
  1913. net->cc_mod.htcp_ca.bytecount = 0;
  1914. net->cc_mod.htcp_ca.lasttime = now;
  1915. return;
  1916. }
  1917. net->cc_mod.htcp_ca.bytecount += net->net_ack;
  1918. if ((net->cc_mod.htcp_ca.bytecount >= net->cwnd - (((net->cc_mod.htcp_ca.alpha >> 7) ? (net->cc_mod.htcp_ca.alpha >> 7) : 1) * net->mtu)) &&
  1919. (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
  1920. (net->cc_mod.htcp_ca.minRTT > 0)) {
  1921. uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount/net->mtu*hz/(now - net->cc_mod.htcp_ca.lasttime);
  1922. if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
  1923. /* just after backoff */
  1924. net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
  1925. } else {
  1926. net->cc_mod.htcp_ca.Bi = (3*net->cc_mod.htcp_ca.Bi + cur_Bi)/4;
  1927. if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
  1928. net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
  1929. if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
  1930. net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
  1931. }
  1932. net->cc_mod.htcp_ca.bytecount = 0;
  1933. net->cc_mod.htcp_ca.lasttime = now;
  1934. }
  1935. }
  1936. static inline void
  1937. htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
  1938. {
  1939. if (use_bandwidth_switch) {
  1940. uint32_t maxB = ca->maxB;
  1941. uint32_t old_maxB = ca->old_maxB;
  1942. ca->old_maxB = ca->maxB;
  1943. if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
  1944. ca->beta = BETA_MIN;
  1945. ca->modeswitch = 0;
  1946. return;
  1947. }
  1948. }
  1949. if (ca->modeswitch && minRTT > sctp_msecs_to_ticks(10) && maxRTT) {
  1950. ca->beta = (minRTT<<7)/maxRTT;
  1951. if (ca->beta < BETA_MIN)
  1952. ca->beta = BETA_MIN;
  1953. else if (ca->beta > BETA_MAX)
  1954. ca->beta = BETA_MAX;
  1955. } else {
  1956. ca->beta = BETA_MIN;
  1957. ca->modeswitch = 1;
  1958. }
  1959. }
  1960. static inline void
  1961. htcp_alpha_update(struct htcp *ca)
  1962. {
  1963. uint32_t minRTT = ca->minRTT;
  1964. uint32_t factor = 1;
  1965. uint32_t diff = htcp_cong_time(ca);
  1966. if (diff > (uint32_t)hz) {
  1967. diff -= hz;
  1968. factor = 1+ (10 * diff + ((diff / 2) * (diff / 2) / hz)) / hz;
  1969. }
  1970. if (use_rtt_scaling && minRTT) {
  1971. uint32_t scale = (hz << 3) / (10 * minRTT);
  1972. scale = min(max(scale, 1U << 2), 10U << 3); /* clamping ratio to interval [0.5,10]<<3 */
  1973. factor = (factor << 3) / scale;
  1974. if (factor != 0)
  1975. factor = 1;
  1976. }
  1977. ca->alpha = 2 * factor * ((1 << 7) - ca->beta);
  1978. if (ca->alpha != 0)
  1979. ca->alpha = ALPHA_BASE;
  1980. }
  1981. /* After we have the rtt data to calculate beta, we'd still prefer to wait one
  1982. * rtt before we adjust our beta to ensure we are working from a consistent
  1983. * data.
  1984. *
  1985. * This function should be called when we hit a congestion event since only at
  1986. * that point do we really have a real sense of maxRTT (the queues en route
  1987. * were getting just too full now).
  1988. */
  1989. static void
  1990. htcp_param_update(struct sctp_nets *net)
  1991. {
  1992. uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
  1993. uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
  1994. htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
  1995. htcp_alpha_update(&net->cc_mod.htcp_ca);
  1996. /* add slowly fading memory for maxRTT to accommodate routing changes etc */
  1997. if (minRTT > 0 && maxRTT > minRTT)
  1998. net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
  1999. }
  2000. static uint32_t
  2001. htcp_recalc_ssthresh(struct sctp_nets *net)
  2002. {
  2003. htcp_param_update(net);
  2004. return (max(((net->cwnd/net->mtu * net->cc_mod.htcp_ca.beta) >> 7)*net->mtu, 2U*net->mtu));
  2005. }
  2006. static void
  2007. htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
  2008. {
  2009. /*-
  2010. * How to handle these functions?
  2011. * if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
  2012. * return;
  2013. */
  2014. if (net->cwnd <= net->ssthresh) {
  2015. /* We are in slow start */
  2016. if (net->flight_size + net->net_ack >= net->cwnd) {
  2017. if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
  2018. net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
  2019. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2020. sctp_log_cwnd(stcb, net, net->mtu,
  2021. SCTP_CWND_LOG_FROM_SS);
  2022. }
  2023. } else {
  2024. net->cwnd += net->net_ack;
  2025. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2026. sctp_log_cwnd(stcb, net, net->net_ack,
  2027. SCTP_CWND_LOG_FROM_SS);
  2028. }
  2029. }
  2030. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  2031. } else {
  2032. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  2033. sctp_log_cwnd(stcb, net, net->net_ack,
  2034. SCTP_CWND_LOG_NOADV_SS);
  2035. }
  2036. }
  2037. } else {
  2038. measure_rtt(net);
  2039. /* In dangerous area, increase slowly.
  2040. * In theory this is net->cwnd += alpha / net->cwnd
  2041. */
  2042. /* What is snd_cwnd_cnt?? */
  2043. if (((net->partial_bytes_acked/net->mtu * net->cc_mod.htcp_ca.alpha) >> 7)*net->mtu >= net->cwnd) {
  2044. /*-
  2045. * Does SCTP have a cwnd clamp?
  2046. * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
  2047. */
  2048. net->cwnd += net->mtu;
  2049. net->partial_bytes_acked = 0;
  2050. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  2051. htcp_alpha_update(&net->cc_mod.htcp_ca);
  2052. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2053. sctp_log_cwnd(stcb, net, net->mtu,
  2054. SCTP_CWND_LOG_FROM_CA);
  2055. }
  2056. } else {
  2057. net->partial_bytes_acked += net->net_ack;
  2058. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  2059. sctp_log_cwnd(stcb, net, net->net_ack,
  2060. SCTP_CWND_LOG_NOADV_CA);
  2061. }
  2062. }
  2063. net->cc_mod.htcp_ca.bytes_acked = net->mtu;
  2064. }
  2065. }
  2066. #ifdef SCTP_NOT_USED
  2067. /* Lower bound on congestion window. */
  2068. static uint32_t
  2069. htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
  2070. {
  2071. return (net->ssthresh);
  2072. }
  2073. #endif
  2074. static void
  2075. htcp_init(struct sctp_nets *net)
  2076. {
  2077. memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
  2078. net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
  2079. net->cc_mod.htcp_ca.beta = BETA_MIN;
  2080. net->cc_mod.htcp_ca.bytes_acked = net->mtu;
  2081. net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
  2082. }
  2083. static void
  2084. sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
  2085. {
  2086. /*
  2087. * We take the max of the burst limit times a MTU or the
  2088. * INITIAL_CWND. We then limit this to 4 MTU's of sending.
  2089. */
  2090. net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
  2091. net->ssthresh = stcb->asoc.peers_rwnd;
  2092. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  2093. htcp_init(net);
  2094. if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
  2095. sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
  2096. }
  2097. }
  2098. static void
  2099. sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
  2100. struct sctp_association *asoc,
  2101. int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
  2102. {
  2103. struct sctp_nets *net;
  2104. /******************************/
  2105. /* update cwnd and Early FR */
  2106. /******************************/
  2107. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  2108. #ifdef JANA_CMT_FAST_RECOVERY
  2109. /*
  2110. * CMT fast recovery code. Need to debug.
  2111. */
  2112. if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
  2113. if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
  2114. SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
  2115. net->will_exit_fast_recovery = 1;
  2116. }
  2117. }
  2118. #endif
  2119. /* if nothing was acked on this destination skip it */
  2120. if (net->net_ack == 0) {
  2121. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  2122. sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
  2123. }
  2124. continue;
  2125. }
  2126. #ifdef JANA_CMT_FAST_RECOVERY
  2127. /* CMT fast recovery code
  2128. */
  2129. /*
  2130. if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
  2131. @@@ Do something
  2132. }
  2133. else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
  2134. */
  2135. #endif
  2136. if (asoc->fast_retran_loss_recovery &&
  2137. will_exit == 0 &&
  2138. (asoc->sctp_cmt_on_off == 0)) {
  2139. /*
  2140. * If we are in loss recovery we skip any cwnd
  2141. * update
  2142. */
  2143. return;
  2144. }
  2145. /*
  2146. * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
  2147. * moved.
  2148. */
  2149. if (accum_moved ||
  2150. ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
  2151. htcp_cong_avoid(stcb, net);
  2152. measure_achieved_throughput(net);
  2153. } else {
  2154. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
  2155. sctp_log_cwnd(stcb, net, net->mtu,
  2156. SCTP_CWND_LOG_NO_CUMACK);
  2157. }
  2158. }
  2159. }
  2160. }
  2161. static void
  2162. sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
  2163. struct sctp_association *asoc)
  2164. {
  2165. struct sctp_nets *net;
  2166. /*
  2167. * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
  2168. * (net->fast_retran_loss_recovery == 0)))
  2169. */
  2170. TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
  2171. if ((asoc->fast_retran_loss_recovery == 0) ||
  2172. (asoc->sctp_cmt_on_off > 0)) {
  2173. /* out of a RFC2582 Fast recovery window? */
  2174. if (net->net_ack > 0) {
  2175. /*
  2176. * per section 7.2.3, are there any
  2177. * destinations that had a fast retransmit
  2178. * to them. If so what we need to do is
  2179. * adjust ssthresh and cwnd.
  2180. */
  2181. struct sctp_tmit_chunk *lchk;
  2182. int old_cwnd = net->cwnd;
  2183. /* JRS - reset as if state were changed */
  2184. htcp_reset(&net->cc_mod.htcp_ca);
  2185. net->ssthresh = htcp_recalc_ssthresh(net);
  2186. net->cwnd = net->ssthresh;
  2187. sctp_enforce_cwnd_limit(asoc, net);
  2188. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2189. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
  2190. SCTP_CWND_LOG_FROM_FR);
  2191. }
  2192. lchk = TAILQ_FIRST(&asoc->send_queue);
  2193. net->partial_bytes_acked = 0;
  2194. /* Turn on fast recovery window */
  2195. asoc->fast_retran_loss_recovery = 1;
  2196. if (lchk == NULL) {
  2197. /* Mark end of the window */
  2198. asoc->fast_recovery_tsn = asoc->sending_seq - 1;
  2199. } else {
  2200. asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  2201. }
  2202. /*
  2203. * CMT fast recovery -- per destination
  2204. * recovery variable.
  2205. */
  2206. net->fast_retran_loss_recovery = 1;
  2207. if (lchk == NULL) {
  2208. /* Mark end of the window */
  2209. net->fast_recovery_tsn = asoc->sending_seq - 1;
  2210. } else {
  2211. net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
  2212. }
  2213. sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
  2214. stcb->sctp_ep, stcb, net,
  2215. SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_3);
  2216. sctp_timer_start(SCTP_TIMER_TYPE_SEND,
  2217. stcb->sctp_ep, stcb, net);
  2218. }
  2219. } else if (net->net_ack > 0) {
  2220. /*
  2221. * Mark a peg that we WOULD have done a cwnd
  2222. * reduction but RFC2582 prevented this action.
  2223. */
  2224. SCTP_STAT_INCR(sctps_fastretransinrtt);
  2225. }
  2226. }
  2227. }
  2228. static void
  2229. sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
  2230. struct sctp_nets *net)
  2231. {
  2232. int old_cwnd = net->cwnd;
  2233. /* JRS - reset as if the state were being changed to timeout */
  2234. htcp_reset(&net->cc_mod.htcp_ca);
  2235. net->ssthresh = htcp_recalc_ssthresh(net);
  2236. net->cwnd = net->mtu;
  2237. net->partial_bytes_acked = 0;
  2238. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2239. sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
  2240. }
  2241. }
  2242. static void
  2243. sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
  2244. struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
  2245. {
  2246. int old_cwnd;
  2247. old_cwnd = net->cwnd;
  2248. /* JRS - reset hctp as if state changed */
  2249. if (in_window == 0) {
  2250. htcp_reset(&net->cc_mod.htcp_ca);
  2251. SCTP_STAT_INCR(sctps_ecnereducedcwnd);
  2252. net->ssthresh = htcp_recalc_ssthresh(net);
  2253. if (net->ssthresh < net->mtu) {
  2254. net->ssthresh = net->mtu;
  2255. /* here back off the timer as well, to slow us down */
  2256. net->RTO <<= 1;
  2257. }
  2258. net->cwnd = net->ssthresh;
  2259. sctp_enforce_cwnd_limit(&stcb->asoc, net);
  2260. if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
  2261. sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
  2262. }
  2263. }
  2264. }
  2265. const struct sctp_cc_functions sctp_cc_functions[] = {
  2266. {
  2267. #if defined(_WIN32) && !defined(__MINGW32__)
  2268. sctp_set_initial_cc_param,
  2269. sctp_cwnd_update_after_sack,
  2270. sctp_cwnd_update_exit_pf_common,
  2271. sctp_cwnd_update_after_fr,
  2272. sctp_cwnd_update_after_timeout,
  2273. sctp_cwnd_update_after_ecn_echo,
  2274. sctp_cwnd_update_after_packet_dropped,
  2275. sctp_cwnd_update_after_output,
  2276. #else
  2277. .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
  2278. .sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
  2279. .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
  2280. .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
  2281. .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
  2282. .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
  2283. .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
  2284. .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
  2285. #endif
  2286. },
  2287. {
  2288. #if defined(_WIN32) && !defined(__MINGW32__)
  2289. sctp_set_initial_cc_param,
  2290. sctp_hs_cwnd_update_after_sack,
  2291. sctp_cwnd_update_exit_pf_common,
  2292. sctp_hs_cwnd_update_after_fr,
  2293. sctp_cwnd_update_after_timeout,
  2294. sctp_cwnd_update_after_ecn_echo,
  2295. sctp_cwnd_update_after_packet_dropped,
  2296. sctp_cwnd_update_after_output,
  2297. #else
  2298. .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
  2299. .sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
  2300. .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
  2301. .sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
  2302. .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
  2303. .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
  2304. .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
  2305. .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
  2306. #endif
  2307. },
  2308. {
  2309. #if defined(_WIN32) && !defined(__MINGW32__)
  2310. sctp_htcp_set_initial_cc_param,
  2311. sctp_htcp_cwnd_update_after_sack,
  2312. sctp_cwnd_update_exit_pf_common,
  2313. sctp_htcp_cwnd_update_after_fr,
  2314. sctp_htcp_cwnd_update_after_timeout,
  2315. sctp_htcp_cwnd_update_after_ecn_echo,
  2316. sctp_cwnd_update_after_packet_dropped,
  2317. sctp_cwnd_update_after_output,
  2318. #else
  2319. .sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
  2320. .sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
  2321. .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
  2322. .sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
  2323. .sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
  2324. .sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
  2325. .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
  2326. .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
  2327. #endif
  2328. },
  2329. {
  2330. #if defined(_WIN32) && !defined(__MINGW32__)
  2331. sctp_set_rtcc_initial_cc_param,
  2332. sctp_cwnd_update_rtcc_after_sack,
  2333. sctp_cwnd_update_exit_pf_common,
  2334. sctp_cwnd_update_after_fr,
  2335. sctp_cwnd_update_after_timeout,
  2336. sctp_cwnd_update_rtcc_after_ecn_echo,
  2337. sctp_cwnd_update_after_packet_dropped,
  2338. sctp_cwnd_update_after_output,
  2339. sctp_cwnd_update_rtcc_packet_transmitted,
  2340. sctp_cwnd_update_rtcc_tsn_acknowledged,
  2341. sctp_cwnd_new_rtcc_transmission_begins,
  2342. sctp_cwnd_prepare_rtcc_net_for_sack,
  2343. sctp_cwnd_rtcc_socket_option,
  2344. sctp_rtt_rtcc_calculated
  2345. #else
  2346. .sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
  2347. .sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
  2348. .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
  2349. .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
  2350. .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
  2351. .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
  2352. .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
  2353. .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
  2354. .sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
  2355. .sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
  2356. .sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
  2357. .sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
  2358. .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
  2359. .sctp_rtt_calculated = sctp_rtt_rtcc_calculated
  2360. #endif
  2361. }
  2362. };