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