10#include "Minstrel_ht.h"
12#define HT_GROUP_RATES 8
13#define VHT_GROUP_RATES 10
14#define HT_BANDWIDTHS 2
15#define VHT_BANDWIDTHS 4
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)
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)
33static Ptr_MinstrelHtPerRemoteStation getMinstrelInfo(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv)
35 Ptr_MinstrelHtWifiStation station = IEEE802_11_PHY(dev,ifid)->rateAdaptationData;
36 return station->minstrelHtInfo[recv];
40void Ht_InitMinstrel(NETSIM_ID nDevId,NETSIM_ID nifid){
42 Ptr_MinstrelHtWifiStation htWifiStation;
44 ht_updateStatsTime = 100*1000;
45 ht_lookAroundRate= 10;
49 htWifiStation = (Ptr_MinstrelHtWifiStation)calloc(1,
sizeof(MinstrelHtWifiStation));
50 htWifiStation->minstrelHtInfo = (Ptr_MinstrelHtPerRemoteStation*)calloc(NETWORK->nDeviceCount+1,
sizeof(Ptr_MinstrelHtPerRemoteStation));
51 htWifiStation->devId = nDevId;
52 htWifiStation->interfaceId = nifid;
53 for(i=0;i<=NETWORK->nDeviceCount;i++){
54 htWifiStation->minstrelHtInfo[i] = (Ptr_MinstrelHtPerRemoteStation)calloc(1,
sizeof(MinstrelHtPerRemoteStation));
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);
60 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = htWifiStation;
63static void CheckInit(Ptr_MinstrelHtPerRemoteStation station,NETSIM_ID devid,NETSIM_ID ifid){
64 if(!station->isInitialized){
65 station->nextStatsUpdate = ldEventTime + ht_updateStatsTime;
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;
77 station->maxTpRate = 0;
78 station->maxTpRate2= 0;
79 station->maxProbRate= 0;
81 station->nGroup= VHT_GROUPS;
82 station->nGroupRate= VHT_GROUP_RATES;
85 station->nGroup = HT_GROUPS;
86 station->nGroupRate = HT_GROUP_RATES;
89 station->phy = IEEE802_11_PHY(devid,ifid);
96 station->samplePacketCount= 0;
97 station->totalPacketCount= 0;
100 station->sampleRate = 0;
102 InitGroupTable(station);
103 InitSampleTable(station);
107static void InitSampleTable(Ptr_MinstrelHtPerRemoteStation station){
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;
119 for(j=0;j<ht_sampleCol;j++){
120 for(i=0;i<station->nGroupRate;i++){
122 int random_var = (int)(station->nGroupRate*rand01());
123 random_var = (i+random_var)%station->nGroupRate;
125 while(station->sampleTable[random_var][j] != 10000){
126 random_var = (random_var + 1)%station->nGroupRate;
128 station->sampleTable[random_var][j] = i;
133static void InitGroupTable(Ptr_MinstrelHtPerRemoteStation station){
135 UINT i,j,ch,sgi,nss,maxCh,maxNss,startid;
137 station->
groupTable = calloc(station->nGroup,
sizeof(GroupInfo));
146 for(ch=20;ch<=maxCh;ch*=2){
147 for(sgi=400;sgi<=800;sgi*=2){
154 for(nss=1;nss<=maxNss;nss++){
155 PhyArray= get_phy_parameter_HT((
double)ch,nss);
158 if(IsEqual(ch,sgi,nss,station->phy->dChannelBandwidth,station->phy->nGuardInterval,station->phy->NSS))
173 station->
groupTable[i].rateTable = calloc(station->nGroupRate,
sizeof(HtRateInfo));
175 for(j=0;j<station->nGroupRate;j++){
176 station->
groupTable[i].rateTable[j].currNumAttempt = 0;
177 station->
groupTable[i].rateTable[j].currNumSuccess = 0;
180 station->
groupTable[i].rateTable[j].numSampleSkipped= 0;
182 station->
groupTable[i].rateTable[j].prevNumAttempt= 0;
183 station->
groupTable[i].rateTable[j].prevNumSuccess= 0;
185 station->
groupTable[i].rateTable[j].rate= PhyArray[j+startid].dDataRate;
189 station->
groupTable[i].rateTable[j].totalNumAttempt= 0;
190 station->
groupTable[i].rateTable[j].totalNumSuccess= 0;
192 if(station->
groupTable[i].rateTable[j].rate <= 0)
203 station->maxTpRate= GetHighestIndex(station);
204 station->maxTpRate2 = GetLowestIndex(station);
205 station->maxProbRate = GetLowestIndex(station);
206 station->trRate = station->maxTpRate;
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)
218 station->
ampduLen += success + failed;
221 UpdatePacketCounter(station,success,failed);
222 groupId = GetGroupId(station->trRate,station->isVht);
223 rateId = GetRateId(station->trRate,station->isVht);
226 station->
groupTable[groupId].rateTable[rateId].currNumAttempt += success + failed;
227 station->
groupTable[groupId].rateTable[rateId].currNumSuccess += success;
229 if(success== 0 && station->longRetry < CountRetries(station)){
234 station->isSampling =
false;
235 UpdateRetry(station);
237 if(ldEventTime >= station->nextStatsUpdate)
238 UpdateStats(station);
240 station->trRate = FindRate(station);
244static void UpdatePacketCounter(Ptr_MinstrelHtPerRemoteStation station,UINT success,UINT failed){
245 station->totalPacketCount += success + failed;
247 if(station->isSampling){
248 station->samplePacketCount += success + failed;
252 if(station->totalPacketCount < 0){
253 station->samplePacketCount = 0;
254 station->totalPacketCount = 0;
264static void UpdateRetry(Ptr_MinstrelHtPerRemoteStation station){
265 station->totalRetry += station->longRetry + station->shortRetry;
266 station->shortRetry = 0;
267 station->longRetry = 0;
270static void UpdateStats(Ptr_MinstrelHtPerRemoteStation station){
274 station->nextStatsUpdate = ldEventTime + ht_updateStatsTime;
287 for(i=0;i<station->nGroup;i++){
290 for(j=0;j<station->nGroupRate;j++){
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;
306 if(station->
groupTable[i].rateTable[j].totalNumAttempt == 0){
315 tempProb = (tempProb * ht_ewmaWeight + (100 - ht_ewmaWeight)*station->
groupTable[i].rateTable[j].
ewmaProb)/100;
324 station->
groupTable[i].rateTable[j].numSampleSkipped++;
327 station->
groupTable[i].rateTable[j].totalNumAttempt += station->
groupTable[i].rateTable[j].currNumAttempt;
328 station->
groupTable[i].rateTable[j].totalNumSuccess += station->
groupTable[i].rateTable[j].currNumSuccess;
329 station->
groupTable[i].rateTable[j].prevNumAttempt = station->
groupTable[i].rateTable[j].currNumAttempt;
330 station->
groupTable[i].rateTable[j].prevNumSuccess = station->
groupTable[i].rateTable[j].currNumSuccess;
331 station->
groupTable[i].rateTable[j].currNumAttempt = 0;
332 station->
groupTable[i].rateTable[j].currNumSuccess = 0;
337 SetStationThRate(station);
338 SetStationProbRate(station);
341 CalculateRetransmits(station,station->maxTpRate);
342 CalculateRetransmits(station,station->maxTpRate2);
343 CalculateRetransmits(station,station->maxProbRate);
346static void UpdateRate(Ptr_MinstrelHtPerRemoteStation station){
361 UINT maxTpRateId, maxTpGrpId, maxTp2RateId, maxTp2GrpId, maxProbRateId, maxProbGrpId;
362 if(!station->isInitialized)
365 station->longRetry++;
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 = GetGroupId(station->maxProbRate, station->isVht);
376 if (!station->isSampling) {
379 station->trRate = station->maxTpRate;
382 else if (station->longRetry < (station->
groupTable[maxTpGrpId].rateTable[maxTpRateId].
retryCount +
384 station->trRate = station->maxTpRate2;
387 else if (station->longRetry <= (station->
groupTable[maxTpGrpId].rateTable[maxTpRateId].
retryCount +
390 station->trRate = station->maxProbRate;
393 fnNetSimError(
"Invalid Retry Condition..!");
401 if(station->longRetry < 1 + station->
groupTable[maxTp2GrpId].rateTable[maxTp2RateId].
retryCount){
402 station->trRate = station->maxTpRate2;
405 else if(station->longRetry >= 1 + station->
groupTable[maxTp2GrpId].rateTable[maxTp2RateId].
retryCount){
406 station->trRate = station->maxProbRate;
409 fnNetSimError(
"Invalid Retry Condition..!");
414static UINT FindRate(Ptr_MinstrelHtPerRemoteStation station){
415 if(station->totalPacketCount == 0){
416 return station->maxTpRate;
421 UINT sampleIdx = GetNextSample(station);
423 UINT sampleGroupId = GetGroupId (sampleIdx,station->isVht);
424 UINT sampleRateId = GetRateId (sampleIdx,station->isVht);
431 if(sampleIdx != station->maxTpRate && sampleIdx != station->maxTpRate2
432 && sampleIdx != station->maxProbRate && station->
groupTable[sampleGroupId].rateTable[sampleRateId].
ewmaProb <= 95){
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);
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;
443 UINT sampleStream = station->
groupTable[sampleGroupId].streams;
444 UINT maxTpStream = station->
groupTable[maxTp2GrpId].streams;
448 if(sampleRate > maxTp2Rate || (sampleStream <= maxTpStream -1 && sampleRate > maxProbRate)){
450 station->isSampling =
true;
452 station->sampleRate = sampleIdx;
457 if(station->
groupTable[sampleGroupId].rateTable[sampleRateId].numSampleSkipped >= 20 && station->
sampleSlow++ <=2){
459 station->isSampling =
true;
461 station->sampleRate = sampleIdx;
473 return station->maxTpRate;
476static void SetStationThRate(Ptr_MinstrelHtPerRemoteStation station){
479 BOOL isVht = station->isVht;
480 UINT grpmaxThId,grpmaxTh2Id;
481 double grpmaxTh,grpmaxThProb,grpmaxTh2,grpmaxTh2Prob,th,prob;
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;
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++){
502 for(j=0;j<station->nGroupRate;j++){
509 if(th > grpmaxTh || (th == grpmaxTh && prob > grpmaxThProb)){
510 grpmaxTh2 = grpmaxTh;
511 grpmaxTh2Prob = grpmaxThProb;
512 grpmaxTh2Id = grpmaxThId;
519 else if(th > grpmaxTh2 || (th == grpmaxTh2 && prob > grpmaxTh2Prob)){
521 grpmaxTh2Prob = prob;
530 if(grpmaxTh > maxTh || (grpmaxTh == maxTh && grpmaxThProb > maxThProb)){
533 maxTh2Prob = maxThProb;
536 maxThId = GetIndex(i,grpmaxThId,station->isVht);
537 maxThProb = grpmaxThProb;
539 else if(grpmaxTh > maxTh2 || (grpmaxTh == maxTh2 && grpmaxThProb > maxTh2Prob)){
541 maxTh2Prob = grpmaxThProb;
542 maxTh2Id = GetIndex(i, grpmaxThId, station->isVht);
545 if(grpmaxTh2 > maxTh2 || (grpmaxTh2 == maxTh2 && grpmaxTh2Prob > maxTh2Prob)){
547 maxTh2Prob = grpmaxTh2Prob;
548 maxTh2Id = GetIndex(i, grpmaxTh2Id, station->isVht);
554 station->maxTpRate = maxThId;
555 station->maxTpRate2 = maxTh2Id;
558static void SetStationProbRate(Ptr_MinstrelHtPerRemoteStation station){
559 UINT i,j,grpmaxProbId;
560 BOOL isVht = station->isVht;
561 double th,prob,grpmaxProb,grpmaxProbTh;
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++){
573 for(j=0;j<station->nGroupRate;j++){
580 if(th > grpmaxProbTh){
587 if(prob > grpmaxProb){
596 if(grpmaxProb > 0.75){
597 if(grpmaxProbTh > maxProbTh){
598 maxProbTh = grpmaxProbTh;
599 maxProb = grpmaxProb;
600 maxProbId = GetIndex(i,grpmaxProbId,station->isVht);
604 if(grpmaxProb > maxProb){
605 maxProbTh = grpmaxProbTh;
606 maxProb = grpmaxProb;
607 maxProbId = GetIndex(i,grpmaxProbId,station->isVht);
611 station->maxProbRate = maxProbId;
614static UINT GetNextSample(Ptr_MinstrelHtPerRemoteStation station){
616 UINT row = station->
groupTable[sampleGroup].row;
617 UINT col = station->
groupTable[sampleGroup].col;
618 UINT sampleIndex = station->sampleTable[row][col];
619 UINT rateIndex = GetIndex(sampleGroup, sampleIndex,station->isVht);
620 SetNextSample(station);
625static void SetNextSample(Ptr_MinstrelHtPerRemoteStation station){
639static double CalculateEwmsd(
double oldEwmsd,
double currentProb,
double ewmaProb,
double ewmaWeight){
640 double diff, incr, tmp;
643 diff = currentProb - ewmaProb;
644 incr = (ewmaWeight) * diff / 100;
645 tmp = oldEwmsd * oldEwmsd;
646 tmp = (100- ewmaWeight)* (tmp + diff * incr) / 100;
652static double CalculateThroughput(Ptr_MinstrelHtPerRemoteStation station,UINT grpId, UINT rateId){
657 double rate = station->
groupTable[grpId].rateTable[rateId].rate;
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;
664static void CalculateRetransmits(Ptr_MinstrelHtPerRemoteStation station,UINT index){
665 UINT grpId = GetGroupId(index,station->isVht);
666 UINT rateId = GetRateId(index,station->isVht);
669 double cwTime,txTime,dataTxTime,rate;
681 rate = station->
groupTable[grpId].rateTable[rateId].rate;
683 dataTxTime = firstTransmissionTime(station->phy,1500,rate) + transmissionTime(station->phy,1500,rate) * (station->
avgAmpduLen - 1);
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);
691 txTime = cwTime + 2*(dataTxTime + ackTime(station->phy));
694 cwTime = (tSlot(station->phy)*cw)>>1;
695 cw = min((cw<<1)| 1,cwMax);
696 txTime += dataTxTime + ackTime(station->phy) + cwTime;
702BOOL Ht_DoNeedDataRetransmission(NETSIM_ID devid,NETSIM_ID ifid,NETSIM_ID recvid){
703 Ptr_MinstrelHtPerRemoteStation station = getMinstrelInfo(devid,ifid,recvid);
704 return (station->longRetry < CountRetries(station));
707static UINT CountRetries(Ptr_MinstrelHtPerRemoteStation station){
709 BOOL isVht = station->isVht;
710 UINT th = station->maxTpRate;
711 UINT th2 = station->maxTpRate2;
712 UINT prob = station->maxProbRate;
713 if(!station->isSampling){
719 return 1 + station->
groupTable[GetGroupId(th2,isVht)].rateTable[GetRateId(th2,isVht)].
retryCount +
724static UINT GetLowestIndex(Ptr_MinstrelHtPerRemoteStation station){
728 while(!(
int)grpId < (
int)station->nGroup &&
732 if(grpId == station->nGroup)
733 fnNetSimError(
"No groups supported..!");
735 while(rateId < station->nGroupRate && !station->
groupTable[grpId].rateTable[rateId].
supported)
738 if(rateId == station->nGroupRate)
739 fnNetSimError(
"No rates supported...!");
741 return GetIndex(grpId,rateId,station->isVht);
744static UINT GetHighestIndex(Ptr_MinstrelHtPerRemoteStation station){
745 int grpId = station->nGroup -1;
746 int rateId = station->nGroupRate -1;
747 while(grpId >= 0 && !station->
groupTable[grpId].supported)
751 fnNetSimError(
"No groups supported..!");
757 fnNetSimError(
"No rates supported..!");
759 return GetIndex(grpId,rateId,station->isVht);
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;
770 if(station->groupTable[grpId].sgi == 800){
776 return get_phy_parameter_HT(W,S)[r];
780void HT_Minstrel_Free(NETSIM_ID nDevId, NETSIM_ID nifid)
782#pragma message(__LOC__"Implement the HT_Minstrel_Free")
783 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = NULL;
Data structure for physical layer parameters.
double avgAmpduLen
Average number of MPDUs in an A-MPDU.
UINT sampleCount
Max number of samples per update interval.
UINT sampleWait
How many transmission attempts to wait until a new sample.
UINT ampduPacketCount
Number of A-MPDUs transmitted since last update.
double ampduLen
Number of MPDUs tried since last update.
UINT sampleTries
Number of sample tries after waiting sampleWait.
UINT sampleSlow
Number of times a slow rate was sampled.
UINT sampleGroup
The group that the sample rate belongs to.
Ptr_GroupInfo groupTable
Table of groups with stats.
BOOL supported
If the rate is supported.
double throughput
Throughput of this rate (in pkts per second).
UINT retryCount
Retry limit.
double prob
Current probability within last time interval. (# frame success )/(# total frames)
double ewmsdProb
Exponential weighted moving standard deviation of probability.
BOOL retryUpdated
If number of retries was updated already.