NetSim Source Code Help
Loading...
Searching...
No Matches
Minstrel_ht.c
Go to the documentation of this file.
1/************************************************************************************
2* Copyright (C) 2020 *
3* TETCOS, Bangalore. India *
4* *
5* The code Minstrel Rate Control algorithm is provided per GNU GPLv2 licensing *
6* *
7* Author: Dhruvang *
8* *
9* ---------------------------------------------------------------------------------*/
10#include "Minstrel_ht.h"
11
12#define HT_GROUP_RATES 8 //number of rates per group in 802.11n
13#define VHT_GROUP_RATES 10 //number of rates per group in 802.11ac
14#define HT_BANDWIDTHS 2 //number of bandwidths 20Mhz & 40Mhz
15#define VHT_BANDWIDTHS 4 //number of vht bandwidths 20,40,80,160 MHz
16#define HT_NSS 4 //number of special streams
17#define VHT_NSS 8 //number of special streams in VHT
18#define HT_GROUPS 16 //number of groups (bandwidth,sgi,nss)
19#define VHT_GROUPS 64 //number of groups (bandwidth,sgi,nss)
20
21#define GetRateId(index,isVht) (isVht ? (index%VHT_GROUP_RATES):(index%HT_GROUP_RATES))
22#define GetGroupId(index,isVht) (isVht ? (index/VHT_GROUP_RATES):(index/HT_GROUP_RATES))
23#define GetIndex(grpId,rateId,isVht) (isVht ? (grpId*VHT_GROUP_RATES + rateId):(grpId*HT_GROUP_RATES + rateId))
24#define IsEqual(b1,g1,s1,b2,g2,s2) ((b1 == b2 && g1 == g2 && s1 ==s2) ? true:false)
25
26#define SEED_r &NETWORK->ppstruDeviceList[0]->ulSeed[0],&NETWORK->ppstruDeviceList[0]->ulSeed[1]
27#define rand01() (fn_NetSim_Utilities_GenerateRandomNo(SEED_r)/NETSIM_RAND_MAX)
28#define tSlot(phy) (phy->plmeCharacteristics.aSlotTime)
29#define ackTime(phy) (phy->plmeCharacteristics.aSIFSTime + get_preamble_time(phy) + (getAckSize(phy) * 8)/phy->dControlFrameDataRate)
30#define firstTransmissionTime(phy,byte,rate) (phy->plmeCharacteristics.aSIFSTime + get_preamble_time(phy)+ byte*8/rate)
31#define transmissionTime(phy,byte,rate) (byte*8/rate)
32
34{
36 return station->minstrelHtInfo[recv];
37}
38
39
41 NETSIM_ID i;
42 Ptr_MinstrelHtWifiStation htWifiStation;
43 //initialize the Minstrel global variables
44 ht_updateStatsTime = 100*1000; //100 ms
46 ht_sampleCol = 10;
47 ht_ewmaWeight = 25;
48
49 htWifiStation = (Ptr_MinstrelHtWifiStation)calloc(1,sizeof(MinstrelHtWifiStation));
51 htWifiStation->devId = nDevId;
52 htWifiStation->interfaceId = nifid;
53 for(i=0;i<=NETWORK->nDeviceCount;i++){
55 htWifiStation->minstrelHtInfo[i]->remoteStationId = i;
56 htWifiStation->minstrelHtInfo[i]->stationId = nDevId;
57 htWifiStation->minstrelHtInfo[i]->stationInterface = nifid;
58 CheckInit(htWifiStation->minstrelHtInfo[i],nDevId,nifid);
59 }
60 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = htWifiStation;
61}
62
63static void CheckInit(Ptr_MinstrelHtPerRemoteStation station,NETSIM_ID devid,NETSIM_ID ifid){ //fill
64 if(!station->isInitialized){
66 station->ampduLen = 0;
67 station->ampduPacketCount = 0;
68 station->avgAmpduLen = 1;
69
70 station->isInitialized= true;
71 station->isSampling= false;
72 station->isVht= (IEEE802_11_PHY(devid,ifid)->PhyType==VHT);
73 station->longRetry= 0;
74 station->shortRetry= 0;
75 station->totalRetry= 0;
76
77 station->maxTpRate = 0;
78 station->maxTpRate2= 0;
79 station->maxProbRate= 0;
80 if(station->isVht){
81 station->nGroup= VHT_GROUPS;
83 }
84 else{
85 station->nGroup = HT_GROUPS;
86 station->nGroupRate = HT_GROUP_RATES;
87 }
88
89 station->phy = IEEE802_11_PHY(devid,ifid);
90 station->sampleCount = 16;
91 station->sampleGroup= 0;
92 station->sampleSlow= 0;
93 station->sampleTries= 4;
94 station->sampleWait= 0;
95
96 station->samplePacketCount= 0;
97 station->totalPacketCount= 0;
98
99 station->trRate= 0;
100 station->sampleRate = 0;
101
102 InitGroupTable(station);
103 InitSampleTable(station);
104 }
105}
106
108 UINT i,j;
109 //Memory allocation for Sample Table
110 station->sampleTable = calloc(station->nGroupRate, sizeof(UINT*));
111 for(i=0;i<station->nGroupRate;i++){
112 station->sampleTable[i] = calloc(ht_sampleCol,sizeof(UINT));
113 for(j=0;j<ht_sampleCol;j++)
114 station->sampleTable[i][j] = 10000;
115 //memset(station->sampleTable[i],10000,sampleCol*sizeof(UINT));
116 }
117
118 //Randomly filling table with values [0,nRate-1]
119 for(j=0;j<ht_sampleCol;j++){
120 for(i=0;i<station->nGroupRate;i++){
121 //generate the random number
122 int random_var = (int)station->nGroupRate*(int)rand01();
123 random_var = (i+random_var)%station->nGroupRate;
124
125 while(station->sampleTable[random_var][j] != 10000){
126 random_var = (random_var + 1)%station->nGroupRate;
127 }
128 station->sampleTable[random_var][j] = i;
129 }
130 }
131}
132
134 //sort order of groups is: BW -> SGI -> #streams
135 UINT i,j,ch,sgi,nss,maxCh,maxNss,startid;
136 struct stru_802_11_Phy_Parameters_HT* PhyArray;
137 station->groupTable = calloc(station->nGroup,sizeof(GroupInfo));
138 maxCh=40;
139 maxNss=4;
140 if(station->isVht){
141 maxCh= 160;
142 maxNss= 8;
143 }
144
145 i=0;
146 for(ch=20;ch<=maxCh;ch*=2){ //bandwidth
147 for(sgi=400;sgi<=800;sgi*=2){ //sgi
148
149 if(sgi == 400) //NetSim requirement see IEEE802_11_HTPhy.c
150 startid = 10;
151 else
152 startid = 0;
153
154 for(nss=1;nss<=maxNss;nss++){ //#streams
155 PhyArray= get_phy_parameter_HT((double)ch,nss);
156 //check if group is supported //fill
157
158 if(IsEqual(ch,sgi,nss,station->phy->dChannelBandwidth,station->phy->nGuardInterval,station->phy->NSS))
159 station->groupTable[i].supported = true;
160 else
161 station->groupTable[i].supported = false;
162
163 if(station->groupTable[i].supported){
164 station->groupTable[i].chWidth= ch;
165 station->groupTable[i].col= 0;
166 station->groupTable[i].maxProbRate=0;
167 station->groupTable[i].maxTpRate= 0;
168 station->groupTable[i].maxTpRate2= 0;
169 station->groupTable[i].row= 0;
170 station->groupTable[i].sgi = sgi;
171 station->groupTable[i].streams = nss;
172
173 station->groupTable[i].rateTable = calloc(station->nGroupRate,sizeof(HtRateInfo));
174
175 for(j=0;j<station->nGroupRate;j++){
176 station->groupTable[i].rateTable[j].currNumAttempt = 0;
177 station->groupTable[i].rateTable[j].currNumSuccess = 0;
178 station->groupTable[i].rateTable[j].ewmaProb= 0;
179 station->groupTable[i].rateTable[j].ewmsdProb = 0;
180 station->groupTable[i].rateTable[j].numSampleSkipped= 0;
181 //station->groupTable[i].rateTable[j].perfectTrTime = ; //fill
182 station->groupTable[i].rateTable[j].prevNumAttempt= 0;
183 station->groupTable[i].rateTable[j].prevNumSuccess= 0;
184 station->groupTable[i].rateTable[j].prob= 0;
185 station->groupTable[i].rateTable[j].rate= PhyArray[j+startid].dDataRate;
186 station->groupTable[i].rateTable[j].retryCount= 0;
187 station->groupTable[i].rateTable[j].retryUpdated= false;
188 station->groupTable[i].rateTable[j].throughput= 0;
189 station->groupTable[i].rateTable[j].totalNumAttempt= 0;
190 station->groupTable[i].rateTable[j].totalNumSuccess= 0;
191
192 if(station->groupTable[i].rateTable[j].rate <= 0)
193 station->groupTable[i].rateTable[j].supported= false;//fill
194 else
195 station->groupTable[i].rateTable[j].supported= true;
196 }
197
198 }
199 i++;
200 }
201 }
202 }
203 station->maxTpRate= GetHighestIndex(station);
204 station->maxTpRate2 = GetLowestIndex(station);
205 station->maxProbRate = GetLowestIndex(station);
206 station->trRate = station->maxTpRate;
207
208}
209
210void DoReportAmpduStatus(NETSIM_ID devid,NETSIM_ID ifid,NETSIM_ID recvid,UINT success,UINT failed){
211 UINT groupId, rateId;
212 Ptr_MinstrelHtPerRemoteStation station = getMinstrelInfo(devid,ifid,recvid);
213 if(!station->isInitialized)
214 return;
215
216 //update ampdu variables
217 station->ampduPacketCount++;
218 station->ampduLen += success + failed;
219
220 //update station packet counters
221 UpdatePacketCounter(station,success,failed); //fill
222 groupId = GetGroupId(station->trRate,station->isVht); //fill
223 rateId = GetRateId(station->trRate,station->isVht); //fill
224
225 //update rate counters
226 station->groupTable[groupId].rateTable[rateId].currNumAttempt += success + failed;
227 station->groupTable[groupId].rateTable[rateId].currNumSuccess += success;
228
229 if(success== 0 && station->longRetry < CountRetries(station)){
230 //Not a single success..Entire A-MPDU failed
231 UpdateRate(station); //fill
232 }
233 else{
234 station->isSampling = false;
235 UpdateRetry(station); //fill
236
237 if(ldEventTime >= station->nextStatsUpdate)
238 UpdateStats(station); //fill
239
240 FindRate(station); //fill
241 }
242}
243
245 station->totalPacketCount += success + failed;
246 //if sampling update samplecount
247 if(station->isSampling){
248 station->samplePacketCount += success + failed;
249 }
250
251 //wraparound
252 if(station->totalPacketCount < 0){
253 station->samplePacketCount = 0;
254 station->totalPacketCount = 0;
255 }
256
257 if(station->sampleWait == 0 && station->sampleTries == 0 && station->sampleCount > 0){
258 station->sampleWait = (UINT)(16 + 2*station->avgAmpduLen);
259 station->sampleTries = 1;
260 station->sampleCount--;
261 }
262}
263
265 station->totalRetry += station->longRetry + station->shortRetry;
266 station->shortRetry = 0;
267 station->longRetry = 0;
268}
269
271 //Call this function after the scheduled update
272 double tempProb;
273 UINT i,j;
275 station->sampleCount = 0;
276 station->sampleSlow = 0;
277
278 if(station->ampduPacketCount > 0){
279 double newLen = station->ampduLen / station->ampduPacketCount ;
280 //exponentially weighted average MPDUs per A-MPDU
281 station->avgAmpduLen = (newLen* ht_ewmaWeight + station->avgAmpduLen*(100- ht_ewmaWeight))/100;
282 station->ampduLen = 0;
283 station->ampduPacketCount = 0;
284 }
285
286 //update stats for each group and each rate
287 for(i=0;i<station->nGroup;i++){
288 if (!station->groupTable[i].supported)
289 continue;
290 for(j=0;j<station->nGroupRate;j++){
291 //check if rate is supported
292 if(station->groupTable[i].rateTable[j].supported){
293 //try to sample all available rates during each interval
294 station->sampleCount++;
295 station->groupTable[i].rateTable[j].retryUpdated = false;
296
297 //if we have attempted something
298 if(station->groupTable[i].rateTable[j].currNumAttempt > 0){
299 station->groupTable[i].rateTable[j].numSampleSkipped = 0;
300 tempProb = (18000* station->groupTable[i].rateTable[j].currNumSuccess)/station->groupTable[i].rateTable[j].currNumAttempt;
301 tempProb = tempProb/18000;
302
303 station->groupTable[i].rateTable[j].prob= tempProb;
304
305 //if updating the rate for the first time
306 if(station->groupTable[i].rateTable[j].totalNumAttempt == 0){
307 station->groupTable[i].rateTable[j].ewmaProb = tempProb;
308 }
309 //take weighted average
310 else{
312 tempProb,station->groupTable[i].rateTable[j].ewmaProb,ht_ewmaWeight); //fill
313
314 //EWMA probability
315 tempProb = (tempProb * ht_ewmaWeight + (100 - ht_ewmaWeight)*station->groupTable[i].rateTable[j].ewmaProb)/100;
316 station->groupTable[i].rateTable[j].ewmaProb = tempProb;
317 }
318
319 station->groupTable[i].rateTable[j].throughput = CalculateThroughput(station,i,j); //fill
320
321 }
322 //nothing is attempted at this rate
323 else{
324 station->groupTable[i].rateTable[j].numSampleSkipped++;
325 }
326
331 station->groupTable[i].rateTable[j].currNumAttempt = 0;
332 station->groupTable[i].rateTable[j].currNumAttempt = 0;
333 }
334 }
335 }
336 //update the group and station max rates
337 SetStationThRate(station); //fill
338 SetStationProbRate(station); //fill
339
340 //Calculate Retransmits..changed based on AMpdu values
341 CalculateRetransmits(station,station->maxTpRate); //fill
342 CalculateRetransmits(station,station->maxTpRate2);
343 CalculateRetransmits(station,station->maxProbRate);
344}
345
347 /**
348 * Retry Chain table is implemented here.
349 * Note this Retry Chain is different from Legacy Minstrel.
350 *
351 * Try | LOOKAROUND RATE | NORMAL RATE
352 * -------------------------------------------------------
353 * 1 | Random rate | Best throughput
354 * 2 | Next best throughput | Next best throughput
355 * 3 | Best probability | Best probability
356 *
357 * Note: For clarity, multiple blocks of if's and else's are used
358 * Following implementation in Linux, in MinstrelHT Lowest baserate is not used.
359 * Explanation can be found here: http://marc.info/?l=linux-wireless&m=144602778611966&w=2
360 */
361 UINT maxTpRateId, maxTpGrpId, maxTp2RateId, maxTp2GrpId, maxProbRateId, maxProbGrpId;
362 if(!station->isInitialized)
363 return;
364
365 station->longRetry++;
366
367 maxTpRateId = GetRateId(station->maxTpRate ,station->isVht);
368 maxTpGrpId = GetGroupId(station->maxTpRate, station->isVht);
369 maxTp2RateId = GetRateId(station->maxTpRate2, station->isVht);
370 maxTp2GrpId = GetGroupId(station->maxTpRate2, station->isVht);
371 maxProbRateId = GetRateId(station->maxProbRate, station->isVht);
372 maxProbGrpId = GetRateId(station->maxProbRate, station->isVht);
373
374
375 //for normal rates
376 if (!station->isSampling) {
377 //use best rate
378 if (station->longRetry < station->groupTable[maxTpGrpId].rateTable[maxTpRateId].retryCount)
379 station->trRate = station->maxTpRate;
380
381 // Use second best throughput rate.
382 else if (station->longRetry < (station->groupTable[maxTpGrpId].rateTable[maxTpRateId].retryCount +
383 station->groupTable[maxTp2GrpId].rateTable[maxTp2RateId].retryCount)) {
384 station->trRate = station->maxTpRate2;
385 }
386 //Use best probability rate
387 else if (station->longRetry <= (station->groupTable[maxTpGrpId].rateTable[maxTpRateId].retryCount +
388 station->groupTable[maxTp2GrpId].rateTable[maxTp2RateId].retryCount +
389 station->groupTable[maxProbGrpId].rateTable[maxProbRateId].retryCount)) {
390 station->trRate = station->maxProbRate;
391 }
392 else {
393 fnNetSimError("Invalid Retry Condition..!");
394 }
395
396 }
397 //for lookaround rates
398 else{
399 //sample rate is used only once
400 //use 2nd best rate **FIXME..!**
401 if(station->longRetry < 1 + station->groupTable[maxTp2GrpId].rateTable[maxTp2RateId].retryCount){
402 station->trRate = station->maxTpRate2;
403 }
404 //use the best proability rate
405 else if(station->longRetry >= 1 + station->groupTable[maxTp2GrpId].rateTable[maxTp2RateId].retryCount){
406 station->trRate = station->maxProbRate;
407 }
408 else{
409 fnNetSimError("Invalid Retry Condition..!");
410 }
411 }
412}
413
415 if(station->totalPacketCount == 0){
416 return station->maxTpRate;
417 }
418 //if we have waited enough then sample
419 if(station->sampleWait == 0 && station->sampleTries != 0){
420 //sampling
421 UINT sampleIdx = GetNextSample(station); //fill
422 //evaluate if the sample rate should be used
423 UINT sampleGroupId = GetGroupId (sampleIdx,station->isVht);
424 UINT sampleRateId = GetRateId (sampleIdx,station->isVht);
425
426 //use sample rate only if it is supported
427 if(station->groupTable[sampleGroupId].supported && station->groupTable[sampleGroupId].rateTable[sampleRateId].supported){
428 /*dont use sampling for the currently used rates
429 * also dont use sampling if probability is already higher than 95%
430 * to avoid wasting airtime */
431 if(sampleIdx != station->maxTpRate && sampleIdx != station->maxTpRate2
432 && sampleIdx != station->maxProbRate && station->groupTable[sampleGroupId].rateTable[sampleRateId].ewmaProb <= 95){
433
434 UINT maxTp2GrpId = GetGroupId(station->maxTpRate2,station->isVht);
435 UINT maxTp2RateId = GetRateId(station->maxTpRate2,station->isVht);
436 UINT maxProbRateId = GetRateId(station->maxProbRate,station->isVht);
437 UINT maxProbGrpId = GetGroupId(station->maxProbRate, station->isVht);
438
439 UINT sampleRate = (UINT)station->groupTable[sampleGroupId].rateTable[sampleRateId].rate;
440 UINT maxTp2Rate = (UINT)station->groupTable[maxTp2GrpId].rateTable[maxTp2RateId].rate;
441 UINT maxProbRate = (UINT)station->groupTable[maxProbGrpId].rateTable[maxProbRateId].rate;
442
443 UINT sampleStream = station->groupTable[sampleGroupId].streams;
444 UINT maxTpStream = station->groupTable[maxTp2GrpId].streams;
445
446 /* Make sure that lower rates get sampled only occasionally,
447 * if the link is working perfectly */
448 if(sampleRate > maxTp2Rate || (sampleStream <= maxTpStream -1 && sampleRate > maxProbRate)){
449 //set flag for currently sampling
450 station->isSampling = true;
451 //set the sample rate
452 station->sampleRate = sampleIdx;
453 station->sampleTries--;
454 return sampleIdx;
455 }
456 else{
457 if(station->groupTable[sampleGroupId].rateTable[sampleRateId].numSampleSkipped >= 20 && station->sampleSlow++ <=2){
458 //set flag for sampling
459 station->isSampling = true;
460 //set the sample rate
461 station->sampleRate = sampleIdx;
462 station->sampleTries--;
463 return sampleIdx;
464 }
465 }
466 }
467 }
468 }
469 if(station->sampleWait > 0)
470 station->sampleWait--;
471
472 //Continue using best rate
473 return station->maxTpRate;
474}
475
477 //set the max and 2nd max throughput rates of the groups and the station
478 UINT i,j;
479 BOOL isVht = station->isVht;
480 UINT grpmaxThId,grpmaxTh2Id;
481 double grpmaxTh,grpmaxThProb,grpmaxTh2,grpmaxTh2Prob,th,prob;
482
483 UINT maxThId = GetLowestIndex(station);
484 double maxTh = station->groupTable[GetGroupId(maxThId,isVht)].rateTable[GetRateId(maxThId,isVht)].throughput;
485 double maxThProb = station->groupTable[GetGroupId(maxThId,isVht)].rateTable[GetRateId(maxThId,isVht)].ewmaProb;
486
487
488 UINT maxTh2Id = GetLowestIndex(station);
489 double maxTh2 = station->groupTable[GetGroupId(maxTh2Id,isVht)].rateTable[GetRateId(maxTh2Id,isVht)].throughput;
490 double maxTh2Prob = station->groupTable[GetGroupId(maxTh2Id,isVht)].rateTable[GetRateId(maxTh2Id,isVht)].ewmaProb;
491 for(i=0;i<station->nGroup;i++){ //for each group
492 if(!station->groupTable[i].supported)
493 continue;
494
495 grpmaxTh = 0;
496 grpmaxThId = 0; //will be rate id
497 grpmaxThProb = 0;
498
499 grpmaxTh2 = 0;
500 grpmaxTh2Id = 0;
501 grpmaxTh2Prob = 0;
502 for(j=0;j<station->nGroupRate;j++){
503 if(!station->groupTable[i].rateTable[j].supported)
504 continue;
505
506 th = station->groupTable[i].rateTable[j].throughput;
507 prob = station->groupTable[i].rateTable[j].ewmaProb;
508 //rate is better than current grp best
509 if(th > grpmaxTh || (th == grpmaxTh && prob > grpmaxThProb)){
510 grpmaxTh2 = grpmaxTh;
511 grpmaxTh2Prob = grpmaxThProb;
512 grpmaxTh2Id = grpmaxThId;
513
514 grpmaxTh = th;
515 grpmaxThProb = prob;
516 grpmaxThId = j;
517 }
518 //rate is better than current grp 2nd best
519 else if(th > grpmaxTh2 || (th == grpmaxTh2 && prob > grpmaxTh2Prob)){
520 grpmaxTh2 = th;
521 grpmaxTh2Prob = prob;
522 grpmaxTh2Id = j;
523 }
524 //do nothing
525 else{
526 }
527 }
528
529 //compare grp values with station values
530 if(grpmaxTh > maxTh || (grpmaxTh == maxTh && grpmaxThProb > maxThProb)){
531 maxTh2 = maxTh;
532 maxTh2Id = maxThId;
533 maxTh2Prob = maxThProb;
534
535 maxTh = grpmaxTh;
536 maxThId = GetIndex(i,grpmaxThId,station->isVht);
537 maxThProb = grpmaxThProb;
538 }
539 else if(grpmaxTh > maxTh2 || (grpmaxTh == maxTh2 && grpmaxThProb > maxTh2Prob)){
540 maxTh2 = grpmaxTh;
541 maxTh2Prob = grpmaxThProb;
542 maxTh2Id = grpmaxThId;
543 }
544
545 if(grpmaxTh2 > maxTh2 || (grpmaxTh2 == maxTh2 && grpmaxTh2Prob > maxTh2Prob)){
546 maxTh2 = grpmaxTh2;
547 maxTh2Prob = grpmaxTh2Prob;
548 maxTh2Id = grpmaxTh2Id;
549 }
550 else{
551 }
552 }
553
554 station->maxTpRate = maxThId;
555 station->maxTpRate2 = maxTh2Id;
556}
557
559 UINT i,j,grpmaxProbId;
560 BOOL isVht = station->isVht;
561 double th,prob,grpmaxProb,grpmaxProbTh;
562
563 UINT maxProbId= GetLowestIndex(station);
564 double maxProb= station->groupTable[GetGroupId(maxProbId,isVht)].rateTable[GetRateId(maxProbId,isVht)].ewmaProb;
565 double maxProbTh= station->groupTable[GetGroupId(maxProbId,isVht)].rateTable[GetRateId(maxProbId,isVht)].throughput;
566 for(i=0;i<station->nGroup;i++){
567 if(!station->groupTable[i].supported)
568 continue;
569
570 grpmaxProb=0;
571 grpmaxProbId=0; //will be rate id
572 grpmaxProbTh=0;
573 for(j=0;j<station->nGroupRate;j++){
574 if(!station->groupTable[i].rateTable[j].supported)
575 continue;
576
577 th = station->groupTable[i].rateTable[j].throughput;
578 prob = station->groupTable[i].rateTable[j].ewmaProb;
579 if(prob > 0.75){
580 if(th > grpmaxProbTh){
581 grpmaxProbTh = th;
582 grpmaxProb = prob;
583 grpmaxProbId = j;
584 }
585 }
586 else{
587 if(prob > grpmaxProb){
588 grpmaxProbTh =th;
589 grpmaxProb = prob;
590 grpmaxProbId = j;
591 }
592 }
593 }
594
595 //update station values based on group values if necessary
596 if(grpmaxProb > 0.75){
597 if(grpmaxProbTh > maxProbTh){
598 maxProbTh = grpmaxProbTh;
599 maxProb = grpmaxProb;
600 maxProbId = GetIndex(i,grpmaxProbId,station->isVht);
601 }
602 }
603 else{
604 if(grpmaxProb > maxProb){
605 maxProbTh = grpmaxProbTh;
606 maxProb = grpmaxProb;
607 maxProbId = GetIndex(i,grpmaxProbId,station->isVht);
608 }
609 }
610 }
611
612}
613
615 UINT sampleGroup = station->sampleGroup;
616 UINT row = station->groupTable[sampleGroup].row;
617 UINT col = station->groupTable[sampleGroup].col;
618 UINT sampleIndex = station->sampleTable[row][col]; //rateId
619 UINT rateIndex = GetIndex(sampleGroup, sampleIndex,station->isVht); //fill
620 SetNextSample(station); //set the next sample rate
621
622 return rateIndex;
623}
624
626 //search for the next supported group
627 do{
628 station->sampleGroup = (++station->sampleGroup)%station->nGroup;
629 }while(!station->groupTable[station->sampleGroup].supported);
630
631 station->groupTable[station->sampleGroup].row++;
632 if(station->groupTable[station->sampleGroup].row >= station->nGroupRate){
633 station->groupTable[station->sampleGroup].row = 0;
634 if(++station->groupTable[station->sampleGroup].col >= ht_sampleCol)
635 station->groupTable[station->sampleGroup].col = 0;
636 }
637}
638
639static double CalculateEwmsd(double oldEwmsd, double currentProb, double ewmaProb, double ewmaWeight){
640 double diff, incr, tmp;
641
642 /* calculate exponential weighted moving variance */
643 diff = currentProb - ewmaProb;
644 incr = (ewmaWeight) * diff / 100;
645 tmp = oldEwmsd * oldEwmsd;
646 tmp = (100- ewmaWeight)* (tmp + diff * incr) / 100;
647
648 /* return standard deviation */
649 return sqrt (tmp);
650}
651
652static double CalculateThroughput(Ptr_MinstrelHtPerRemoteStation station,UINT grpId, UINT rateId){
653 if(station->groupTable[grpId].rateTable[rateId].ewmaProb < 0.1)
654 return 0;
655 else{
656 double ewmaProb = station->groupTable[grpId].rateTable[rateId].ewmaProb;
657 double rate = station->groupTable[grpId].rateTable[rateId].rate;
658 double nPackets = station->avgAmpduLen;
659 double TrTime = firstTransmissionTime(station->phy,1500,rate) + transmissionTime(station->phy,1500,rate)*(nPackets - 1);
660 return (max(ewmaProb,0.9)*8*1500*nPackets)/TrTime; //check and fill
661 }
662}
663
665 UINT grpId = GetGroupId(index,station->isVht);
666 UINT rateId = GetRateId(index,station->isVht);
667 UINT cw = 15;
668 UINT cwMax = 1023;
669 double cwTime,txTime,dataTxTime,rate;
670
671
672 if(station->groupTable[grpId].rateTable[rateId].retryUpdated)
673 return;
674
675 if(station->groupTable[grpId].rateTable[rateId].ewmaProb < 0.01)
676 station->groupTable[grpId].rateTable[rateId].retryCount =1;
677 else{
678 station->groupTable[grpId].rateTable[rateId].retryCount =2;
679 station->groupTable[grpId].rateTable[rateId].retryUpdated = true;
680
681 rate = station->groupTable[grpId].rateTable[rateId].rate;
682 //data transmission time
683 dataTxTime = firstTransmissionTime(station->phy,1500,rate) + transmissionTime(station->phy,1500,rate) * (station->avgAmpduLen - 1);
684
685 //contention time for first two transmission
686 cwTime = (tSlot(station->phy)*cw)>>1;
687 cw = min((cw<<1)| 1,cwMax);
688 cwTime += (tSlot(station->phy)*cw)>>1;
689 cw = min((cw<<1)| 1,cwMax);
690
691 txTime = cwTime + 2*(dataTxTime + ackTime(station->phy));
692
693 do{
694 cwTime = (tSlot(station->phy)*cw)>>1;
695 cw = min((cw<<1)| 1,cwMax);
696 txTime += dataTxTime + ackTime(station->phy) + cwTime;
697 }while(txTime < 6000 && (++station->groupTable[grpId].rateTable[rateId].retryCount < 7));
698
699 }
700}
701
703 Ptr_MinstrelHtPerRemoteStation station = getMinstrelInfo(devid,ifid,recvid);
704 return (station->longRetry < CountRetries(station));
705}
706
708 //is station is sampling
709 BOOL isVht = station->isVht;
710 UINT th = station->maxTpRate;
711 UINT th2 = station->maxTpRate2;
712 UINT prob = station->maxProbRate;
713 if(!station->isSampling){
714 return station->groupTable[GetGroupId(th,isVht)].rateTable[GetRateId(th,isVht)].retryCount +
715 station->groupTable[GetGroupId(th2,isVht)].rateTable[GetRateId(th2,isVht)].retryCount +
716 station->groupTable[GetGroupId(prob,isVht)].rateTable[GetRateId(prob,isVht)].retryCount;
717 }
718 else{
719 return 1 + station->groupTable[GetGroupId(th2,isVht)].rateTable[GetRateId(th2,isVht)].retryCount +
720 station->groupTable[GetGroupId(prob,isVht)].rateTable[GetRateId(prob,isVht)].retryCount;
721 }
722}
723
725 UINT grpId = 0;
726 UINT rateId = 0;
727
728 while(!(int)grpId < (int)station->nGroup &&
729 !station->groupTable[grpId].supported)
730 grpId++;
731
732 if(grpId == station->nGroup)
733 fnNetSimError("No groups supported..!");
734
735 while(rateId < station->nGroupRate && !station->groupTable[grpId].rateTable[rateId].supported)
736 rateId++;
737
738 if(rateId == station->nGroupRate)
739 fnNetSimError("No rates supported...!");
740
741 return GetIndex(grpId,rateId,station->isVht);
742}
743
745 int grpId = station->nGroup -1;
746 int rateId = station->nGroupRate -1;
747 while(grpId >= 0 && !station->groupTable[grpId].supported)
748 grpId--;
749
750 if(grpId == -1)
751 fnNetSimError("No groups supported..!");
752
753 while(rateId >= 0 && !station->groupTable[grpId].rateTable[rateId].supported)
754 rateId--;
755
756 if(rateId == -1)
757 fnNetSimError("No rates supported..!");
758
759 return GetIndex(grpId,rateId,station->isVht);
760}
761
763{
764 Ptr_MinstrelHtPerRemoteStation station = getMinstrelInfo(devid,ifid,recvid);
765 UINT grpId = GetGroupId(station->trRate,station->isVht);
766 UINT rateId = GetRateId(station->trRate,station->isVht);
767 UINT W = station->groupTable[grpId].chWidth;
768 UINT S = station->groupTable[grpId].streams;
769 UINT r;
770 if(station->groupTable[grpId].sgi == 800){
771 r = rateId;
772 }
773 else{
774 r = 10 + rateId;
775 }
776 return get_phy_parameter_HT(W,S)[r];
777
778}
779
781{
782#pragma message(__LOC__"Implement the HT_Minstrel_Free")
783 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = NULL;
784}
unsigned int NETSIM_ID
Definition: Animation.h:45
PIEEE802_11_PHY_VAR IEEE802_11_PHY(NETSIM_ID ndeviceId, NETSIM_ID nInterfaceId)
struct stru_802_11_Phy_Parameters_HT * get_phy_parameter_HT(double dChannelBandwidth, UINT NSS)
@ VHT
BOOL
Definition: Linux.h:62
#define UINT
Definition: Linux.h:38
#define fnNetSimError(x,...)
Definition: Linux.h:56
#define min(a, b)
Definition: Linux.h:106
#define max(a, b)
Definition: Linux.h:107
#define calloc(c, s)
Definition: Memory.h:29
static Ptr_MinstrelPerRemoteStation getMinstrelInfo(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:37
double ewmaWeight
Definition: Minstrel.h:73
#define GetIndex(grpId, rateId, isVht)
Definition: Minstrel_ht.c:23
static double CalculateEwmsd(double oldEwmsd, double currentProb, double ewmaProb, double ewmaWeight)
Definition: Minstrel_ht.c:639
static void UpdateRate(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:346
static void CheckInit(Ptr_MinstrelHtPerRemoteStation station, NETSIM_ID devid, NETSIM_ID ifid)
Definition: Minstrel_ht.c:63
#define HT_GROUP_RATES
Definition: Minstrel_ht.c:12
static UINT CountRetries(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:707
void Ht_InitMinstrel(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel_ht.c:40
static UINT GetLowestIndex(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:724
static void SetStationThRate(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:476
static UINT GetNextSample(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:614
void DoReportAmpduStatus(NETSIM_ID devid, NETSIM_ID ifid, NETSIM_ID recvid, UINT success, UINT failed)
Definition: Minstrel_ht.c:210
#define VHT_GROUPS
Definition: Minstrel_ht.c:19
#define ackTime(phy)
Definition: Minstrel_ht.c:29
#define VHT_GROUP_RATES
Definition: Minstrel_ht.c:13
#define GetRateId(index, isVht)
Definition: Minstrel_ht.c:21
#define transmissionTime(phy, byte, rate)
Definition: Minstrel_ht.c:31
#define GetGroupId(index, isVht)
Definition: Minstrel_ht.c:22
BOOL Ht_DoNeedDataRetransmission(NETSIM_ID devid, NETSIM_ID ifid, NETSIM_ID recvid)
Definition: Minstrel_ht.c:702
struct stru_802_11_Phy_Parameters_HT getTxRate(NETSIM_ID devid, NETSIM_ID ifid, NETSIM_ID recvid)
Definition: Minstrel_ht.c:762
void HT_Minstrel_Free(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel_ht.c:780
#define firstTransmissionTime(phy, byte, rate)
Definition: Minstrel_ht.c:30
static void SetNextSample(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:625
static Ptr_MinstrelHtPerRemoteStation getMinstrelInfo(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel_ht.c:33
static double CalculateThroughput(Ptr_MinstrelHtPerRemoteStation station, UINT grpId, UINT rateId)
Definition: Minstrel_ht.c:652
#define HT_GROUPS
Definition: Minstrel_ht.c:18
#define IsEqual(b1, g1, s1, b2, g2, s2)
Definition: Minstrel_ht.c:24
#define rand01()
Definition: Minstrel_ht.c:27
static void UpdateStats(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:270
static void InitGroupTable(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:133
static UINT FindRate(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:414
static void CalculateRetransmits(Ptr_MinstrelHtPerRemoteStation station, UINT index)
Definition: Minstrel_ht.c:664
static void InitSampleTable(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:107
static UINT GetHighestIndex(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:744
#define tSlot(phy)
Definition: Minstrel_ht.c:28
static void UpdateRetry(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:264
static void SetStationProbRate(Ptr_MinstrelHtPerRemoteStation station)
Definition: Minstrel_ht.c:558
static void UpdatePacketCounter(Ptr_MinstrelHtPerRemoteStation station, UINT success, UINT failed)
Definition: Minstrel_ht.c:244
double ht_ewmaWeight
Definition: Minstrel_ht.h:144
double ht_lookAroundRate
Definition: Minstrel_ht.h:143
struct stru_HtPerRemoteStation * Ptr_MinstrelHtPerRemoteStation
UINT ht_sampleCol
Definition: Minstrel_ht.h:145
struct stru_MinstrelHtWifiStation * Ptr_MinstrelHtWifiStation
double ht_updateStatsTime
Definition: Minstrel_ht.h:142
EXPORTED double ldEventTime
Definition: Stack.h:838
EXPORTED struct stru_NetSim_Network * NETWORK
Definition: Stack.h:742
Data structure for physical layer parameters.
IEEE802_11_PHY_TYPE PhyType
Ptr_HtRateInfo rateTable
Definition: Minstrel_ht.h:94
PIEEE802_11_PHY_VAR phy
Definition: Minstrel_ht.h:132
double avgAmpduLen
Average number of MPDUs in an A-MPDU.
Definition: Minstrel_ht.h:108
UINT sampleCount
Max number of samples per update interval.
Definition: Minstrel_ht.h:105
UINT sampleWait
How many transmission attempts to wait until a new sample.
Definition: Minstrel_ht.h:103
UINT ampduPacketCount
Number of A-MPDUs transmitted since last update.
Definition: Minstrel_ht.h:110
double ampduLen
Number of MPDUs tried since last update.
Definition: Minstrel_ht.h:109
UINT sampleTries
Number of sample tries after waiting sampleWait.
Definition: Minstrel_ht.h:104
UINT sampleSlow
Number of times a slow rate was sampled.
Definition: Minstrel_ht.h:106
UINT sampleGroup
The group that the sample rate belongs to.
Definition: Minstrel_ht.h:102
Ptr_GroupInfo groupTable
Table of groups with stats.
Definition: Minstrel_ht.h:111
UINT numSampleSkipped
Definition: Minstrel_ht.h:71
BOOL supported
If the rate is supported.
Definition: Minstrel_ht.h:54
double throughput
Throughput of this rate (in pkts per second).
Definition: Minstrel_ht.h:68
UINT retryCount
Retry limit.
Definition: Minstrel_ht.h:56
double prob
Current probability within last time interval. (# frame success )/(# total frames)
Definition: Minstrel_ht.h:58
double ewmsdProb
Exponential weighted moving standard deviation of probability.
Definition: Minstrel_ht.h:69
UINT64 totalNumSuccess
Definition: Minstrel_ht.h:77
UINT64 totalNumAttempt
Definition: Minstrel_ht.h:76
BOOL retryUpdated
If number of retries was updated already.
Definition: Minstrel_ht.h:60
Ptr_MinstrelHtPerRemoteStation * minstrelHtInfo
Definition: Minstrel_ht.h:139