Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

660 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996,1997 Microsoft Corporation
  3. Module Name:
  4. STATS.C
  5. Abstract:
  6. Session Statistics routines
  7. Author:
  8. Aaron Ogus (aarono)
  9. Environment:
  10. Win32/COM
  11. Revision History:
  12. Date Author Description
  13. ====== ====== ============================================================
  14. 7/30/97 aarono Original
  15. 6/6/98 aarono Turn on throttling and windowing
  16. --*/
  17. #include <windows.h>
  18. #include "newdpf.h"
  19. #include <dplay.h>
  20. #include <dplaysp.h>
  21. #include <dplaypr.h>
  22. #include "mydebug.h"
  23. #include "arpd.h"
  24. #include "arpdint.h"
  25. #include "protocol.h"
  26. #include "macros.h"
  27. #include "command.h"
  28. #define STARTING_LONG_LATENCY 1 /* 1 ms (intentionally low so first sample fills) */
  29. #define STARTING_SHORT_LATENCY 15000 /* 15 seconds (intentionally high so first sample fills) */
  30. #define STARTING_AVERAGE_LATENCY 2000 /* 2 seconds (good start for internet) */
  31. #define STARTING_AVERAGE_DEVIATION 0
  32. #define STARTING_MAXRETRY 16 /* Maximum number of retries */
  33. #define STARTING_MINDROPTIME 15000 /* Minimum time to retry before dropping connection (ms) */
  34. #define STARTING_MAXDROPTIME 60000 /* Maximum time to retry before dropping connection (ms) */
  35. #define STARTING_BANDWIDTH (28800/10) /* 28 kbps modem */
  36. #define LATENCY_SHORT_BITS 4
  37. #define LATENCY_LONG_BITS 7
  38. #define STAT_LOCAL_LATENCY_SAMPLES 2^(LATENCY_SHORT_BITS) /* 2^4 */
  39. #define STAT_LONG_LATENCY_SAMPLES 2^(LATENCY_LONG_BITS) /* 2^7 */
  40. #define TARGET_CLOCK_OFFSET 10000000
  41. #define Fp(_x) ((_x)<<8)
  42. #define unFp(_x)((_x)>>8)
  43. // Latency Averages and deviation averages are stored as fixed point 24.8
  44. VOID InitSessionStats(PSESSION pSession)
  45. {
  46. pSession->ShortestLatency = STARTING_SHORT_LATENCY;
  47. pSession->LongestLatency = STARTING_LONG_LATENCY;
  48. pSession->FpAverageLatency = 1000;
  49. pSession->FpLocalAverageLatency = 1000;
  50. pSession->FpLocalAvgDeviation = 300;
  51. pSession->FpAvgDeviation = 300;
  52. pSession->Bandwidth = 28800/10;
  53. pSession->HighestBandwidth=28800/10;
  54. pSession->MaxRetry = STARTING_MAXRETRY;
  55. pSession->MinDropTime = STARTING_MINDROPTIME;
  56. pSession->MaxDropTime = STARTING_MAXDROPTIME;
  57. }
  58. // called with SESSIONLOCK.
  59. VOID UpdateSessionStats(PSESSION pSession, PSENDSTAT pStat, PCMDINFO pCmdInfo, BOOL fBadDrop)
  60. {
  61. DWORD tLatency;
  62. DWORD nBytesReceived;
  63. DWORD tDeviation;
  64. DWORD BytesLost=0;
  65. DWORD BackLog=0;
  66. DWORD fThrottleAdjusted=FALSE;
  67. DWORD tRemoteDelta; // change in time on remote from last received ACK until this was ACKed.
  68. DWORD tBiasedDelta; // a biased difference in local and remote clocks.
  69. INT tDelta; // the unbiased difference (signed)
  70. static DWORD cBiasReset;
  71. // Get the statistics information we need.
  72. tLatency = pCmdInfo->tReceived-pStat->tSent;
  73. ASSERT((int)tLatency >= 0);
  74. if(!tLatency){
  75. DPF(8,"0ms observed latency, using 1ms\n");
  76. tLatency=1;
  77. }
  78. Lock(&pSession->SessionStatLock);
  79. // Calculates the number of bytes received at remote since this send was done.
  80. pSession->RemoteBytesReceived = pCmdInfo->bytes;
  81. pSession->tRemoteBytesReceived = pCmdInfo->tRemoteACK;
  82. nBytesReceived = pSession->RemoteBytesReceived - pStat->RemoteBytesReceived;
  83. BytesLost = pStat->LocalBytesSent-(pSession->RemoteBytesReceived+pSession->BytesLost);
  84. if((int)BytesLost >= 0){
  85. pSession->BytesLost += BytesLost;
  86. // Note, Backlog may be as little as 1/2 this value.
  87. BackLog = pSession->BytesSent -( pSession->RemoteBytesReceived + pSession->BytesLost );
  88. if((int)BackLog < 0){
  89. DPF(8,"Hmmm, upside down backlog?\n");
  90. DPF(8,"pSession->BytesSent %d\n",pSession->BytesSent);
  91. DPF(8,"pSession->RemoteBytesReceived %d\n",pSession->RemoteBytesReceived);
  92. DPF(8,"pSession->BytesLost %d\n",pSession->BytesLost);
  93. DPF(8,"Calculated BackLog %d\n",BackLog);
  94. BackLog=0;
  95. }
  96. } else if((int)BytesLost < 0){
  97. // Can be caused by out of order receives
  98. DPF(1,"Out of order remote receive lots of these may affect throttling...\n");
  99. DPF(8,"Hmmm, upside down byte counting?\n");
  100. DPF(8,"pStat->LocalBytesSent %d\n",pStat->LocalBytesSent);
  101. DPF(8,"pSession->RemoteBytesReceived %d\n",pSession->RemoteBytesReceived);
  102. DPF(8,"pSession->BytesLost %d\n",pSession->BytesLost);
  103. DPF(8,"Calculated Bytes Lost %d\n",BytesLost);
  104. BytesLost=0;
  105. // fixup lost count.
  106. pSession->BytesLost=pSession->RemoteBytesReceived-pStat->LocalBytesSent;
  107. }
  108. Unlock(&pSession->SessionStatLock);
  109. if(pSession->MaxCSends==1){
  110. DWORD Bias;
  111. // 1st ACK, adjust windows to normal operation.
  112. pSession->MaxCSends = MAX_SMALL_CSENDS;
  113. pSession->MaxCDGSends = MAX_SMALL_DG_CSENDS;
  114. pSession->WindowSize = MAX_SMALL_WINDOW;
  115. pSession->DGWindowSize = MAX_SMALL_WINDOW;
  116. pSession->FpAverageLatency = 2*tLatency; // start high to avoid overthrottle
  117. pSession->FpLocalAverageLatency = 2*tLatency;
  118. pSession->FpLocalAvgDeviation = 1+tLatency/3;
  119. pSession->FpAvgDeviation = 1+tLatency/3;
  120. Bias = pCmdInfo->tRemoteACK - pStat->tSent;
  121. if(Bias > TARGET_CLOCK_OFFSET){
  122. Bias = -1*(Bias-TARGET_CLOCK_OFFSET);
  123. } else {
  124. Bias = TARGET_CLOCK_OFFSET - Bias;
  125. }
  126. pSession->RemAvgACKBias = Bias;
  127. pSession->RemAvgACKDelta = (pCmdInfo->tRemoteACK - pStat->tSent)+pSession->RemAvgACKBias;
  128. ASSERT(pSession->RemAvgACKDelta == TARGET_CLOCK_OFFSET);
  129. }
  130. //
  131. // Calculate shift in outbound latency.
  132. //
  133. tBiasedDelta = (pCmdInfo->tRemoteACK - pStat->tSent)+pSession->RemAvgACKBias;
  134. tDelta = tBiasedDelta-TARGET_CLOCK_OFFSET;
  135. if(tDelta < 0 || pStat->bResetBias || tDelta > (int)tLatency){
  136. DWORD Bias;
  137. // Either clock drift or lower server load shows latency down, so reset baseline.
  138. Bias = pCmdInfo->tRemoteACK - pStat->tSent;
  139. if(Bias > TARGET_CLOCK_OFFSET){
  140. Bias = -1*(Bias-TARGET_CLOCK_OFFSET);
  141. } else {
  142. Bias = TARGET_CLOCK_OFFSET - Bias;
  143. }
  144. cBiasReset++;
  145. pSession->RemAvgACKBias = Bias;
  146. tBiasedDelta = (pCmdInfo->tRemoteACK - pStat->tSent)+pSession->RemAvgACKBias;
  147. tDelta = tBiasedDelta-TARGET_CLOCK_OFFSET;
  148. }
  149. pSession->RemAvgACKDelta -= pSession->RemAvgACKDelta >> 7; // -1/128th
  150. pSession->RemAvgACKDelta += tBiasedDelta >> 7; // +1/128th of new value
  151. // keep the residue so we don't creep down due to rounding error.
  152. pSession->RemAvgACKDeltaResidue += tBiasedDelta & 0x7f;
  153. if(pSession->RemAvgACKDeltaResidue>>7){
  154. pSession->RemAvgACKDelta += pSession->RemAvgACKDeltaResidue>>7;
  155. pSession->RemAvgACKDeltaResidue &= 0x7f;
  156. }
  157. DPF(8,"tRemoteACK %d tSent %d Bias %d tBiasedDelta %d tDelta %d\n", pCmdInfo->tRemoteACK, pStat->tSent,
  158. pSession->RemAvgACKBias, tBiasedDelta, tDelta);
  159. //
  160. // Update latency statistics
  161. //
  162. ASSERT(!(nBytesReceived & 0x80000000)); // received in interval +ve
  163. ASSERT(!(tLatency & 0x80000000)); // latency is +ve
  164. if(tLatency < pSession->ShortestLatency){
  165. pSession->ShortestLatency=tLatency;
  166. DPF(8,"Shortest Latency %d ms\n",tLatency);
  167. }
  168. if(tLatency > pSession->LongestLatency){
  169. pSession->LongestLatency=tLatency;
  170. DPF(8,"Longest Latency %d ms\n", tLatency);
  171. }
  172. pSession->LastLatency=tLatency;
  173. // Throw out 1/16 of local latency and add in the new statistic.
  174. // Note we only use local latency for retry calculations.
  175. if(pSession->FpLocalAverageLatency){
  176. if(Fp(tLatency) > pSession->FpAverageLatency){
  177. pSession->FpLocalAverageLatency -= (pSession->FpLocalAverageLatency >> LATENCY_SHORT_BITS);
  178. pSession->FpLocalAverageLatency += (tLatency << (8-LATENCY_SHORT_BITS));
  179. } else {
  180. // Ratched down when we get a latency that is below average, so we can better
  181. // detect backlog due to latency.
  182. pSession->FpLocalAverageLatency = Fp(tLatency);
  183. }
  184. } else {
  185. // this only happens once at startup.
  186. pSession->FpLocalAverageLatency = Fp(tLatency);
  187. pSession->FpAverageLatency = Fp(tLatency);
  188. }
  189. if(Fp(tLatency) > pSession->FpAverageLatency){
  190. // Thow out 1/128 of average latency and add in the new statistic.
  191. pSession->FpAverageLatency -= (pSession->FpAverageLatency >> LATENCY_LONG_BITS);
  192. pSession->FpAverageLatency += (tLatency << (8-LATENCY_LONG_BITS));
  193. } else {
  194. // Ratched down when we get a latency that is below average, so we can better
  195. // detect backlog due to latency.
  196. pSession->FpAverageLatency = Fp(tLatency);
  197. }
  198. tDeviation=unFp(pSession->FpLocalAverageLatency)-tLatency;
  199. if((int)tDeviation < 0){
  200. tDeviation = 0-tDeviation;
  201. }
  202. pSession->FpLocalAvgDeviation -= (pSession->FpLocalAvgDeviation >> LATENCY_SHORT_BITS);
  203. pSession->FpLocalAvgDeviation += (tDeviation << (8-LATENCY_SHORT_BITS));
  204. pSession->FpAvgDeviation -= (pSession->FpAvgDeviation >> LATENCY_LONG_BITS);
  205. pSession->FpAvgDeviation += (tDeviation << (8-LATENCY_LONG_BITS));
  206. DPF(8,"Got ACK, tLat: %d Avg: %d.%d Dev: %d AvgDev: %d.%d \n",
  207. tLatency, pSession->FpLocalAverageLatency >> 8, ((pSession->FpLocalAverageLatency&0xFF)*100)/256,
  208. tDeviation, pSession->FpLocalAvgDeviation >> 8, ((pSession->FpLocalAvgDeviation&0xFF)*100)/256);
  209. //
  210. // Do Bandwidth calculations
  211. //
  212. tRemoteDelta= pCmdInfo->tRemoteACK - pStat->tRemoteBytesReceived;
  213. if(!tRemoteDelta){
  214. tRemoteDelta=1;
  215. }
  216. if(pStat->tRemoteBytesReceived){
  217. pSession->Bandwidth = (1000*nBytesReceived)/(tRemoteDelta);
  218. // could adjust throttle here if Bandwidth is higher, but this
  219. // might pimp high speed links. (BUGBUG:).
  220. } else {
  221. // backup calculation, not as good. Only used early in the link
  222. // before we have received an ACK from the remote prior to issuing
  223. // a send.
  224. pSession->Bandwidth = (2000*nBytesReceived)/tLatency; // 2000, not 1000 since tLatency is round trip.
  225. }
  226. if(pSession->Bandwidth > pSession->HighestBandwidth){
  227. pSession->HighestBandwidth = pSession->Bandwidth;
  228. }
  229. DPF(8,"tRemoteDelta %d Remote bytes Received %d\n",tRemoteDelta,nBytesReceived);
  230. // Adjust sending...
  231. if ( BackLog && pSession->Bandwidth)
  232. {
  233. DWORD tAvgLat;
  234. DWORD tBackLog;
  235. DWORD ExcessBackLog; // amount of backlog (bytes) we need to clear before hitting avg latency again.
  236. DWORD tLatCheck;
  237. DWORD AvgLat133; // 133% of local average latency (tolerance for slow links)
  238. DWORD AvgLat200; // 200% of local average latency (tolerance for fast links)
  239. if(pSession->fFastLink){
  240. tAvgLat=unFp(pSession->FpAverageLatency);
  241. tLatCheck = (tAvgLat*3)/2;
  242. AvgLat133 = max(100,3*unFp(pSession->FpAvgDeviation)+(unFp(pSession->FpAverageLatency)*4)/3); // don't throttle <100ms lat
  243. AvgLat200 = max(100,3*unFp(pSession->FpAvgDeviation)+unFp(pSession->FpAverageLatency)*2);
  244. } else {
  245. tAvgLat=unFp(pSession->FpLocalAverageLatency);
  246. tLatCheck = (tAvgLat*3)/2;
  247. AvgLat133 = max(100,3*unFp(pSession->FpLocalAvgDeviation)+(unFp(pSession->FpLocalAverageLatency)*4)/3); // don't throttle <100ms lat
  248. AvgLat200 = max(100,3*unFp(pSession->FpLocalAvgDeviation)+unFp(pSession->FpLocalAverageLatency)*2);
  249. }
  250. if(tLatCheck < AvgLat133){
  251. tLatCheck = AvgLat133;
  252. }
  253. if(tLatency > tLatCheck){
  254. // check link speed
  255. if(pSession->fFastLink){
  256. if(pSession->Bandwidth <= 10000){
  257. pSession->fFastLink=FALSE;
  258. }
  259. } else {
  260. if(pSession->Bandwidth >= 25000){
  261. pSession->fFastLink=TRUE;
  262. }
  263. }
  264. }
  265. if(pSession->fFastLink && tLatCheck < AvgLat200){
  266. tLatCheck=AvgLat200;
  267. }
  268. DPF(8,"tLat %d, tLatCheck %d, tDelta %d, tLat/3 %d\n",tLatency,tLatCheck,tDelta,tLatency/3);
  269. DPF(8,"pSession->ShortestLatency %d, Shortest+MaxPacketTime %d\n",pSession->ShortestLatency,
  270. pSession->ShortestLatency+(pSession->MaxPacketSize*1000)/pSession->Bandwidth);
  271. if((tLatency > tLatCheck && tDelta > (int)(tLatency/3)) ||
  272. ((!pSession->fFastLink)&&
  273. (tLatency > pSession->ShortestLatency+((pSession->MaxPacketSize*2000)/pSession->Bandwidth))
  274. )
  275. )
  276. {
  277. #ifdef DEBUG
  278. if(pSession->SendRateThrottle){
  279. DPF(8,"BackLog %d, SendRate %d BackLog ms %d, tLatency %d tAvgLat %d Used Bandwidth %d tBacklog %d \n",
  280. BackLog,
  281. pSession->SendRateThrottle,
  282. (BackLog*1000 / pSession->SendRateThrottle),
  283. tLatency,
  284. tAvgLat,
  285. pSession->Bandwidth,
  286. ((BackLog*1000) / pSession->Bandwidth)
  287. );
  288. }
  289. #endif
  290. tBackLog = (BackLog * 1000)/pSession->Bandwidth;
  291. if(tBackLog > 4*tLatency){
  292. DPF(8,"1: tBackLog %d was >> tLatency %d, using 4*tLatency instead\n",tBackLog,tLatency);
  293. tBackLog=4*tLatency; //never wait more than 4 latency periods
  294. }
  295. if(tBackLog > 8000){
  296. DPF(8,"Disalowing backlog > 8 seconds, using 8 instead\n");
  297. tBackLog=8000;
  298. }
  299. // if the backlog is greater than the bandwidth*latency, then we need to slow down our sending.
  300. // don't slow down due to backlog until we are over 100ms on way latency (200 round trip)
  301. if((tBackLog > 200) && (tBackLog > tAvgLat)){
  302. BOOL fWait=TRUE;
  303. // at max we cut send rate in 1/2.
  304. if(pSession->SendRateThrottle/2 > pSession->Bandwidth){
  305. DPF(8,"Asked for too aggresive throttle adjust %d, going from %d to %d\n",pSession->Bandwidth,pSession->SendRateThrottle,pSession->SendRateThrottle/2);
  306. pSession->SendRateThrottle /= 2;
  307. // Recheck if we are really backlogged at the new rate
  308. tBackLog = (BackLog * 1000)/pSession->SendRateThrottle;
  309. if(tBackLog > tLatency){
  310. DPF(8,"2: tBackLog %d was > tLatency %d, using tLatency instead\n",tBackLog,tLatency);
  311. tBackLog=tLatency;// never wait more than last latency period
  312. }
  313. } else {
  314. // set new throttle rate and current observed bandwidth (+5% to avoid overthrottle)
  315. pSession->SendRateThrottle=pSession->Bandwidth+pSession->Bandwidth/16;
  316. }
  317. // don't adjust for a while.
  318. pSession->bhitThrottle=FALSE;
  319. pSession->tLastThrottleAdjust = pCmdInfo->tReceived;
  320. if(fWait && (tBackLog > tAvgLat)){
  321. ExcessBackLog = ((tBackLog-tAvgLat)*pSession->Bandwidth)/1000;
  322. DPF(8,"Throttling back due to BACKLOG, excess = %d\n",ExcessBackLog);
  323. #ifdef DEBUG
  324. if(tBackLog-tAvgLat > 30000){
  325. DPF(5,"WARNING: BACKLOG THROTTLE %d ms seems kinda large\n",tBackLog-tAvgLat);
  326. }
  327. #endif
  328. // wait until backlog is down to avg latency before sending again
  329. Lock(&pSession->SessionStatLock);
  330. pSession->bResetBias = 2; // could be in the middle of a send, so count down from 2.
  331. Unlock(&pSession->SessionStatLock);
  332. UpdateSendTime(pSession,ExcessBackLog,timeGetTime(),TRUE);
  333. } else {
  334. DPF(8,"Not throttling due to BACKLOG because of smaller adjustment\n");
  335. }
  336. } else {
  337. DPF(8,"NOT Throttling back due to BACKLOG\n");
  338. }
  339. }
  340. } else if(tDelta > (int)tLatency) {
  341. // tDelta is bogus due to clock drift, force throttle so we can correct.
  342. Lock(&pSession->SessionStatLock);
  343. pSession->bResetBias=2;
  344. Unlock(&pSession->SessionStatLock);
  345. pSession->tNextSend=timeGetTime()+2*tLatency;
  346. DPF(8,"tDelta %d > tLatency %d, need to correct for clock drift, time %d set next send time to %d\n", tDelta, tLatency,timeGetTime(),pSession->tNextSend);
  347. }
  348. //
  349. // Adjust Throttle if not already adjusted.
  350. //
  351. if((pSession->ThrottleState==Begin) ||
  352. (pCmdInfo->tReceived-pSession->tLastThrottleAdjust) > (1+1*pSession->fFastLink)*unFp(pSession->FpLocalAverageLatency) )
  353. {
  354. if(!fThrottleAdjusted){
  355. DPF(8,"Current Send Rate %d\n", pSession->SendRateThrottle);
  356. if(!BytesLost && pSession->bhitThrottle){
  357. pSession->bhitThrottle=FALSE;
  358. pSession->tLastThrottleAdjust = pCmdInfo->tReceived;
  359. // Good Send, push up send rate if we hit throttle.
  360. switch(pSession->ThrottleState){
  361. case Begin:
  362. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100+START_GROWTH_RATE))/100;
  363. pSession->GrowCount++;
  364. pSession->ShrinkCount=0;
  365. break;
  366. case MetaStable:
  367. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100+METASTABLE_GROWTH_RATE))/100;
  368. pSession->GrowCount++;
  369. pSession->ShrinkCount=0;
  370. break;
  371. case Stable:
  372. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100+STABLE_GROWTH_RATE))/100;
  373. pSession->GrowCount++;
  374. pSession->ShrinkCount=0;
  375. if(pSession->GrowCount > (UINT)(20+60*pSession->fFastLink)){
  376. pSession->ThrottleState = MetaStable;
  377. pSession->GrowCount=0;
  378. }
  379. break;
  380. default:
  381. DPF(0,"Session in wierd ThrottleState %d\n",pSession->ThrottleState);
  382. break;
  383. }
  384. DPF(8,"Successful Send Adjusted Throttle, SendRate %d\n",pSession->SendRateThrottle);
  385. } else if(BytesLost){
  386. // Figure out how much we dropped
  387. if(fBadDrop || (BytesLost > pSession->pProtocol->m_dwSPMaxFrame)){
  388. // Very bad send, back off
  389. pSession->tLastThrottleAdjust = pCmdInfo->tReceived;
  390. switch(pSession->ThrottleState){
  391. case Begin:
  392. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-START_ADJUST_LARGE_ERR))/100;
  393. pSession->GrowCount=0;
  394. pSession->ShrinkCount++;
  395. break;
  396. case MetaStable:
  397. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-METASTABLE_ADJUST_LARGE_ERR))/100;
  398. pSession->GrowCount=0;
  399. pSession->ShrinkCount++;
  400. break;
  401. case Stable:
  402. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-STABLE_ADJUST_LARGE_ERR))/100;
  403. pSession->ShrinkCount++;
  404. if(pSession->ShrinkCount > 1){
  405. pSession->ShrinkCount=0;
  406. pSession->GrowCount=0;
  407. pSession->ThrottleState=MetaStable;
  408. }
  409. break;
  410. default:
  411. DPF(0,"Session in wierd ThrottleState %d\n",pSession->ThrottleState);
  412. break;
  413. }
  414. DPF(8,"VERY BAD SEND Adjusted Throttle, SendRate %d\n",pSession->SendRateThrottle);
  415. } else {
  416. // Bad send, back off a bit
  417. pSession->tLastThrottleAdjust = pCmdInfo->tReceived;
  418. switch(pSession->ThrottleState){
  419. case Begin:
  420. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-START_ADJUST_SMALL_ERR))/100;
  421. pSession->GrowCount=0;
  422. pSession->ShrinkCount=0;
  423. pSession->ThrottleState = MetaStable;
  424. break;
  425. case MetaStable:
  426. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-METASTABLE_ADJUST_SMALL_ERR))/100;
  427. pSession->ShrinkCount++;
  428. pSession->GrowCount=0;
  429. break;
  430. case Stable:
  431. pSession->SendRateThrottle = (pSession->SendRateThrottle*(100-STABLE_ADJUST_SMALL_ERR))/100;
  432. pSession->ShrinkCount++;
  433. pSession->GrowCount=0;
  434. if(pSession->ShrinkCount > 2){
  435. pSession->ShrinkCount=0;
  436. pSession->ThrottleState = MetaStable;
  437. }
  438. break;
  439. default:
  440. DPF(0,"Session in wierd ThrottleState %d\n",pSession->ThrottleState);
  441. break;
  442. }
  443. DPF(8,"BAD SEND Adjusted Throttle, SendRate %d\n",pSession->SendRateThrottle);
  444. } /* if (BadDrop... ) */
  445. } /* if (BytesLost ...) */
  446. }/*if (ThrottleAdjusted) */
  447. }
  448. if(!BytesLost && pSession->Bandwidth && pSession->SendRateThrottle < pSession->Bandwidth){
  449. DPF(8,"Avoid goofyness, throttle was %d, setting to observed bandwidth %d\n",pSession->SendRateThrottle,pSession->Bandwidth);
  450. pSession->SendRateThrottle=pSession->Bandwidth;
  451. }
  452. if(pSession->SendRateThrottle < 100){
  453. DPF(8,"WARNING: SendRateThrottle %d below 100, keeping at 100 to avoid starvation\n",pSession->SendRateThrottle);
  454. pSession->SendRateThrottle=100;
  455. }
  456. #ifdef DEBUG
  457. {
  458. IN_WRITESTATS InWS;
  459. memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS));
  460. InWS.stat_ThrottleRate = pSession->SendRateThrottle;
  461. InWS.stat_BytesSent = pSession->BytesSent;
  462. InWS.stat_BackLog = BackLog;
  463. InWS.stat_BytesLost = pSession->BytesLost;
  464. //InWS.stat_RemBytesReceived;
  465. InWS.stat_Latency = tLatency;
  466. InWS.stat_MinLatency=pSession->ShortestLatency;
  467. InWS.stat_AvgLatency=unFp(pSession->FpLocalAverageLatency);
  468. InWS.stat_AvgDevLatency=unFp(pSession->FpLocalAvgDeviation);
  469. //InWS.stat_USER1=
  470. //InWS.stat_USER2=
  471. //InWS.stat_USER3=
  472. InWS.stat_USER5 = tDelta;
  473. InWS.stat_USER6 = cBiasReset;
  474. DbgWriteStats(&InWS);
  475. }
  476. #endif
  477. DPF(8,"Bandwidth %d, Highest %d\n",pSession->Bandwidth, pSession->HighestBandwidth);
  478. }
  479. // Called with SessionLock and SendLock
  480. // Statistics are stored on the send in send order on a BILINK.
  481. // most recent sends are at the end of the list. We scan from
  482. // the end of the list to the beginning until we find the SENDSTAT
  483. // that records the sequence and serial we got ACKED. We then
  484. // update our statistics and throw out all SENDSTATs
  485. // before this entry.
  486. VOID UpdateSessionSendStats(PSESSION pSession, PSEND pSend, PCMDINFO pCmdInfo, BOOL fBadDrop)
  487. {
  488. PSENDSTAT pStatWalker,pStat=NULL;
  489. BILINK *pStatBilink;
  490. pSend->tLastACK=pCmdInfo->tReceived;
  491. pSend->RetryCount=0;
  492. // Find the last STAT for this ACK.
  493. pStatBilink=pSend->StatList.prev;
  494. while(pStatBilink != &pSend->StatList){
  495. pStatWalker=CONTAINING_RECORD(pStatBilink, SENDSTAT, StatList);
  496. if(pStatWalker->serial==pCmdInfo->serial &&
  497. pStatWalker->sequence==pCmdInfo->sequence)
  498. {
  499. ASSERT(pStatWalker->messageid==pSend->messageid);
  500. ASSERT(pSend->messageid==pCmdInfo->messageid);
  501. pStat=pStatWalker;
  502. break;
  503. }
  504. pStatBilink=pStatBilink->prev;
  505. }
  506. if(pStat){
  507. UpdateSessionStats(pSession,pStat,pCmdInfo,fBadDrop);
  508. // Unlink All Previous SENDSTATS;
  509. pStat->StatList.next->prev=&pSend->StatList;
  510. pSend->StatList.next=pStat->StatList.next;
  511. // Put the SENDSTATS back in the pool.
  512. while(pStatBilink != &pSend->StatList){
  513. pStatWalker=CONTAINING_RECORD(pStatBilink, SENDSTAT, StatList);
  514. pStatBilink=pStatBilink->prev;
  515. ReleaseSendStat(pStatWalker);
  516. }
  517. }
  518. return;
  519. }