31#define SEED_r &NETWORK->ppstruDeviceList[0]->ulSeed[0],&NETWORK->ppstruDeviceList[0]->ulSeed[1]
32#define rand01() (fn_NetSim_Utilities_GenerateRandomNo(SEED_r)/NETSIM_RAND_MAX)
33#define ackTime(phy) (phy->plmeCharacteristics.aSIFSTime + get_preamble_time(phy) + (getAckSize(phy) * 8)/phy->dControlFrameDataRate)
34#define tSlot(phy) (phy->plmeCharacteristics.aSlotTime)
35#define transmissionTime(phy,byte,rate) (phy->plmeCharacteristics.aSIFSTime + get_preamble_time(phy)+ byte*8/rate)
37static Ptr_MinstrelPerRemoteStation getMinstrelInfo(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv)
39 switch (IEEE802_11_PHY(dev, ifid)->PhyProtocol)
46 Ptr_MinstrelWifiStation station = IEEE802_11_PHY(dev, ifid)->rateAdaptationData;
47 return station->minstrelInfo[recv];
55 fnNetSimError(
"Unknown phy protocol in %s\n", __FUNCTION__);
60void get_data_rate(NETSIM_ID devid,NETSIM_ID ifid,
double* rate,
unsigned int* len)
62 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(devid,ifid);
63 switch(phy->PhyProtocol)
68 get_ofdm_phy_all_rate((
int)phy->dChannelBandwidth, rate, len);
71 get_dsss_phy_all_rate(rate, len);
76 fnNetSimError(
"Unknown phy protocol %d in %s.\n",phy->PhyProtocol,__FUNCTION__);
81void Minstrel_Init(NETSIM_ID nDevId,NETSIM_ID nifid)
83 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
89 InitMinstrel(nDevId,nifid);
93 Ht_InitMinstrel(nDevId,nifid);
96 He_InitMinstrel(nDevId, nifid);
99 fnNetSimError(
"Unknown phy protocol in %s\n",__FUNCTION__);
103BOOL Minstrel_DoNeedDataSend(NETSIM_ID nDevId,NETSIM_ID nifid,NETSIM_ID recvid)
105 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
111 return DoNeedDataRetransmission(nDevId,nifid,recvid);
115 return Ht_DoNeedDataRetransmission(nDevId,nifid,recvid);
118 return He_DoNeedDataRetransmission(nDevId, nifid, recvid);
121 fnNetSimError(
"Unknown phy protocol in %s\n",__FUNCTION__);
126void Minstrel_ReportDataFailed(NETSIM_ID nDevId,NETSIM_ID nifid,NETSIM_ID recvid)
128 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
134 DoReportDataFailed(nDevId,nifid,recvid);
140 NetSim_PACKET* p = IEEE802_11_MAC(nDevId,nifid)->currentProcessingPacket;
144 p=p->pstruNextPacket;
146 DoReportAmpduStatus(nDevId,nifid,recvid,0,c);
152 NetSim_PACKET* p = IEEE802_11_MAC(nDevId, nifid)->currentProcessingPacket;
156 p = p->pstruNextPacket;
158 He_DoReportAmpduStatus(nDevId, nifid, recvid, 0, c);
162 fnNetSimError(
"Unknown phy protocol in %s\n",__FUNCTION__);
166void Minstrel_ReportFinalDataFailed(NETSIM_ID nDevId,NETSIM_ID nifid,NETSIM_ID recvid)
168 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
174 DoReportFinalDataFailed(nDevId,nifid,recvid);
180 NetSim_PACKET* p = IEEE802_11_MAC(nDevId,nifid)->currentProcessingPacket;
184 p=p->pstruNextPacket;
186 DoReportAmpduStatus(nDevId,nifid,recvid,0,c);
192 NetSim_PACKET* p = IEEE802_11_MAC(nDevId, nifid)->currentProcessingPacket;
196 p = p->pstruNextPacket;
198 He_DoReportAmpduStatus(nDevId, nifid, recvid, 0, c);
202 fnNetSimError(
"Unknown phy protocol in %s\n",__FUNCTION__);
206void InitMinstrel(NETSIM_ID nDevId,NETSIM_ID nifid){
208 NETSIM_ID nPort, nNumOfPorts;
209 Ptr_MinstrelWifiStation wifiStation;
212 updateStatsTime = 100*1000;
217 wifiStation = (Ptr_MinstrelWifiStation)calloc(1,
sizeof(MinstrelWifiStation));
218 wifiStation->minstrelInfo = (Ptr_MinstrelPerRemoteStation*)calloc(NETWORK->nDeviceCount+1,
sizeof(Ptr_MinstrelPerRemoteStation));
220 for(i=1;i<=NETWORK->nDeviceCount;i++)
222 nNumOfPorts = NETWORK->ppstruDeviceList[i - 1]->nNumOfInterface;
223 for (nPort = 1; nPort <= nNumOfPorts; nPort++)
225 if (isIEEE802_11_Configure(i, nPort))
227 wifiStation->minstrelInfo[i] = (Ptr_MinstrelPerRemoteStation)calloc(1,
sizeof(MinstrelPerRemoteStation));
228 CheckInit(wifiStation->minstrelInfo[i],nDevId,nifid);
232 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = wifiStation;
235static void CheckInit(Ptr_MinstrelPerRemoteStation station,NETSIM_ID nDevId,NETSIM_ID nifid){
236 if(!station->isInitialized){
240 get_data_rate(nDevId,nifid,get_rate,&get_nrate);
242 station->nextStatsUpdate = ldEventTime + updateStatsTime;
243 station->maxTpRate= 0;
244 station->maxTp2Rate= 0;
245 station->maxProbRate= 0;
246 station->phy = IEEE802_11_PHY(nDevId,nifid);
248 station->nRate = get_nrate;
249 station->baseRate = 0;
250 for(i=0;i<station->nRate;i++)
251 if(get_rate[i] < get_rate[station->baseRate])
252 station->baseRate = i;
254 station->sampleRate= 0;
257 station->isSampling=
false;
258 station->samplePacketCount= 0;
259 station->totalPacketCount= 0;
260 station->shortRetry= 0;
261 station->longRetry= 0;
262 station->totalRetry= 0;
266 InitSampleTable(station);
267 InitMinstrelTable(station,get_rate);
268 station->isInitialized =
true;
272static void InitSampleTable(Ptr_MinstrelPerRemoteStation station){
275 station->sampleTable = calloc(station->nRate,
sizeof(UINT*));
276 for(i=0;i<station->nRate;i++){
277 station->sampleTable[i] = calloc(sampleCol,
sizeof(UINT));
278 for(j=0;j<sampleCol;j++)
279 station->sampleTable[i][j] = 10000;
287 for(j=0;j<sampleCol;j++){
288 for(i=0;i<station->nRate;i++){
290 int random_var = station->nRate*(int)rand01();
291 random_var = (i+random_var)%station->nRate;
293 while(station->sampleTable[random_var][j] != 10000){
294 random_var = (random_var + 1)%station->nRate;
296 station->sampleTable[random_var][j] = i;
301static void InitMinstrelTable(Ptr_MinstrelPerRemoteStation station,
double *rate_arr){
304 station->minstrelTable = (RateInfo*)calloc(station->nRate,
sizeof(RateInfo));
305 for(i=0;i<station->nRate;i++){
306 station->minstrelTable[i].currNumAttempt= 0;
307 station->minstrelTable[i].currNumSuccess= 0;
308 station->minstrelTable[i].prevNumAttempt = 0;
309 station->minstrelTable[i].prevNumSuccess = 0;
310 station->minstrelTable[i].totalNumAttempt= 0;
311 station->minstrelTable[i].totalNumSuccess= 0;
312 station->minstrelTable[i].prob= 0;
313 station->minstrelTable[i].ewmaProb= 0;
314 station->minstrelTable[i].throughput= 0;
315 station->minstrelTable[i].numSampleSkipped= 0;
316 station->minstrelTable[i].rate= rate_arr[i];
317 station->minstrelTable[i].sampleLimit= -1;
318 station->minstrelTable[i].retryCount= 1;
319 station->minstrelTable[i].adjustedRetryCount= 1;
320 station->minstrelTable[i].perfectTrTime= transmissionTime(station->phy,1500,rate_arr[i]);
323 trTime= station->minstrelTable[i].perfectTrTime + ackTime(station->phy);
327 trTime += station->minstrelTable[i].perfectTrTime + ackTime(station->phy);
330 trTime+= (tSlot(station->phy)*cw)>>1;
331 cw = min((cw<<1)|1,1023);
335 station->minstrelTable[i].retryCount++;
336 station->minstrelTable[i].adjustedRetryCount++;
343 UpdateStats(station);
346void DoReportDataOk(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv){
347 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
348 if(!station->isInitialized)
351 station->minstrelTable[station->trRate].currNumAttempt++;
352 station->minstrelTable[station->trRate].currNumSuccess++;
354 UpdatePacketCounter(station);
355 UpdateRetry(station);
356 UpdateStats(station);
358 if(station->nRate >=1)
359 station->trRate = FindRate(station);
362void DoReportDataFailed(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv){
363 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
364 if(!station->isInitialized)
369static void UpdateRate(Ptr_MinstrelPerRemoteStation station){
373 station->longRetry++;
374 station->totalPacketCount++;
375 station->minstrelTable[station->trRate].currNumAttempt++;
377 if(station->isSampling && station->trRate == station->sampleRate)
378 station->samplePacketCount++;
381 if(!station->isSampling){
384 if(station->longRetry < station->minstrelTable[station->maxTpRate].adjustedRetryCount){
385 station->trRate = station->maxTpRate;
388 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
389 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount){
390 station->trRate = station->maxTp2Rate;
393 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
394 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
395 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
396 station->trRate = station->maxProbRate;
399 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
400 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
401 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
402 station->trRate = station->baseRate;
405 fnNetSimError(
"Failed to Update Rate");
411 if(station->isDeferredSample){
413 if(station->longRetry < station->minstrelTable[station->maxTpRate].adjustedRetryCount){
414 station->trRate = station->maxTpRate;
417 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
418 station->minstrelTable[station->sampleRate].adjustedRetryCount){
419 station->trRate = station->sampleRate;
422 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
423 station->minstrelTable[station->sampleRate].adjustedRetryCount +
424 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
425 station->trRate = station->maxProbRate;
428 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
429 station->minstrelTable[station->sampleRate].adjustedRetryCount +
430 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
431 station->trRate = station->baseRate;
434 fnNetSimError(
"Failed to Update Rate");
440 if(station->longRetry < station->minstrelTable[station->sampleRate].adjustedRetryCount){
441 station->trRate = station->sampleRate;
444 else if(station->longRetry < station->minstrelTable[station->sampleRate].adjustedRetryCount +
445 station->minstrelTable[station->maxTpRate].adjustedRetryCount){
446 station->trRate = station->maxTpRate;
449 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
450 station->minstrelTable[station->sampleRate].adjustedRetryCount +
451 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
452 station->trRate = station->maxProbRate;
455 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
456 station->minstrelTable[station->sampleRate].adjustedRetryCount +
457 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
458 station->trRate = station->baseRate;
461 fnNetSimError(
"Failed to Update Rate");
467static void UpdatePacketCounter(Ptr_MinstrelPerRemoteStation station){
469 station->totalPacketCount++;
472 if(station->isSampling && station->trRate == station->sampleRate){
473 station->samplePacketCount++;
476 if(station->numSampleDeferred >0){
477 station->numSampleDeferred--;
481 if(station->totalPacketCount < 0){
482 station->numSampleDeferred = 0;
483 station->samplePacketCount = 0;
484 station->totalPacketCount = 0;
488 station->isSampling =
false;
489 station->isDeferredSample =
false;
492static void UpdateRetry(Ptr_MinstrelPerRemoteStation station){
493 station->totalRetry += station->longRetry + station->shortRetry;
494 station->longRetry = 0;
495 station->shortRetry = 0;
498static void UpdateStats(Ptr_MinstrelPerRemoteStation station){
499 UINT i,index_max_tp, index_max_tp2, index_max_prob;
500 double tempProb, max_prob, max_tp;
502 if(ldEventTime < station->nextStatsUpdate){
505 if(!station->isInitialized){
508 station->nextStatsUpdate = ldEventTime + updateStatsTime;
510 for(i=0;i<station->nRate;i++){
512 trTime = station->minstrelTable[i].perfectTrTime;
520 if(station->minstrelTable[i].currNumAttempt){
521 station->minstrelTable[i].numSampleSkipped = 0;
523 tempProb = (station->minstrelTable[i].currNumSuccess*18000) / station->minstrelTable[i].currNumAttempt;
524 tempProb = tempProb/18000.0;
525 station->minstrelTable[i].prob = tempProb;
528 if(station->minstrelTable[i].totalNumAttempt == 0){
529 station->minstrelTable[i].ewmaProb = tempProb;
533 tempProb = (tempProb*ewmaWeight + station->minstrelTable[i].ewmaProb*(100-ewmaWeight))/100;
534 station->minstrelTable[i].ewmaProb = tempProb;
540 station->minstrelTable[i].throughput = 0;
542 station->minstrelTable[i].throughput = (tempProb*8*1500)/(trTime);
547 station->minstrelTable[i].numSampleSkipped++;
551 station->minstrelTable[i].totalNumAttempt += station->minstrelTable[i].currNumAttempt;
552 station->minstrelTable[i].totalNumSuccess += station->minstrelTable[i].currNumSuccess;
553 station->minstrelTable[i].prevNumAttempt = station->minstrelTable[i].currNumAttempt;
554 station->minstrelTable[i].prevNumSuccess = station->minstrelTable[i].currNumSuccess;
555 station->minstrelTable[i].currNumAttempt = 0;
556 station->minstrelTable[i].currNumSuccess = 0;
559 if(station->minstrelTable[i].ewmaProb < 0.1 || station->minstrelTable[i].ewmaProb > 0.95){
567 if(station->minstrelTable[i].retryCount > 2){
568 station->minstrelTable[i].adjustedRetryCount = 2;
570 station->minstrelTable[i].sampleLimit = 4;
574 station->minstrelTable[i].sampleLimit = -1;
575 station->minstrelTable[i].adjustedRetryCount = station->minstrelTable[i].retryCount;
579 if(station->minstrelTable[i].adjustedRetryCount == 0)
580 station->minstrelTable[i].adjustedRetryCount = 2;
589 for(i=0;i<station->nRate;i++){
590 if(max_tp < station->minstrelTable[i].throughput){
592 max_tp = station->minstrelTable[i].throughput;
597 for(i=0;i<station->nRate;i++){
598 if(i != index_max_tp && max_tp < station->minstrelTable[i].throughput){
600 max_tp = station->minstrelTable[i].throughput;
604 for(i=0;i<station->nRate;i++){
606 if(station->minstrelTable[i].ewmaProb >= 0.95 && station->minstrelTable[i].throughput >= station->minstrelTable[index_max_prob].throughput){
608 max_prob = station->minstrelTable[i].ewmaProb;
610 else if(station->minstrelTable[i].ewmaProb >= max_prob){
612 max_prob = station->minstrelTable[i].ewmaProb;
615 station->maxTpRate = index_max_tp;
616 station->maxTp2Rate = index_max_tp2;
617 station->maxProbRate = index_max_prob;
620static UINT FindRate(Ptr_MinstrelPerRemoteStation station){
623 if(station->totalPacketCount == 0)
626 delta = (int)(((station->totalPacketCount*lookAroundRate)/100) - (station->samplePacketCount + station->numSampleDeferred/2 ));
631 UINT n_rates = station->nRate;
632 if(delta > (
int)(2* n_rates)){
643 station->samplePacketCount += delta - 2*n_rates;
646 idx = GetNextSample(station);
648 fnNetSimError(
"Unknown rate...!");
650 station->sampleRate = idx;
658 if((station->minstrelTable[idx].perfectTrTime > station->minstrelTable[station->maxTpRate].perfectTrTime)
659 && station->minstrelTable[idx].numSampleSkipped < 20){
661 station->isDeferredSample =
true;
662 station->numSampleDeferred++;
665 station->isSampling =
true;
669 if(station->minstrelTable[idx].sampleLimit == 0){
670 idx = station->maxTpRate;
671 station->isSampling =
false;
675 station->isSampling =
true;
676 if(station->minstrelTable[idx].sampleLimit > 0)
677 station->minstrelTable[idx].sampleLimit--;
682 if(station->isDeferredSample){
683 idx = station->maxTpRate;
689 idx = station->maxTpRate;
695static UINT GetNextSample(Ptr_MinstrelPerRemoteStation station){
696 UINT sample_rate = station->sampleTable[station->row][station->col];
700 if(station->row >= station->nRate){
703 if(station->col >= sampleCol)
710void DoReportFinalDataFailed(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv){
711 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
712 if(!station->isInitialized)
715 UpdatePacketCounter(station);
716 UpdateRetry(station);
717 UpdateStats(station);
719 if(station->nRate >= 1)
720 station->trRate=FindRate(station);
724BOOL DoNeedDataRetransmission(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv){
725 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
727 if(!station->isInitialized)
729 if(station->longRetry > CountRetry(station))
735static UINT CountRetry(Ptr_MinstrelPerRemoteStation station){
737 if(!station->isSampling){
738 return station->minstrelTable[station->maxTpRate].adjustedRetryCount +
739 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
740 station->minstrelTable[station->maxProbRate].adjustedRetryCount +
741 station->minstrelTable[station->baseRate].adjustedRetryCount;
744 return station->minstrelTable[station->maxTpRate].adjustedRetryCount +
745 station->minstrelTable[station->sampleRate].adjustedRetryCount +
746 station->minstrelTable[station->maxProbRate].adjustedRetryCount +
747 station->minstrelTable[station->baseRate].adjustedRetryCount;
751static void DoReportRtsFailed(Ptr_MinstrelPerRemoteStation station){
752 station->shortRetry++;
755static void DoReportFinalRtsFailed(Ptr_MinstrelPerRemoteStation station){
756 UpdateRetry(station);
758void Minstrel_Free(NETSIM_ID nDevId, NETSIM_ID nifid)
761 Ptr_MinstrelWifiStation wifistation= IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData;
762 for(i=0;i<=NETWORK->nDeviceCount;i++){
763 if(wifistation->minstrelInfo[i])
765 FreeTables(wifistation->minstrelInfo[i]);
766 free(wifistation->minstrelInfo[i]);
769 free(wifistation->minstrelInfo);
771 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = NULL;
774void FreeMinstrel(NETSIM_ID nDevId, NETSIM_ID nifid)
776 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(nDevId, nifid);
777 switch(phy->PhyProtocol)
783 Minstrel_Free(nDevId,nifid);
787 HT_Minstrel_Free(nDevId,nifid);
790 HE_Minstrel_Free(nDevId, nifid);
793 fnNetSimError(
"Unknown phy protocol %d for device %d interface %d in %s\n", phy->PhyProtocol,
794 nDevId, nifid, __FUNCTION__);
798void FreeTables(Ptr_MinstrelPerRemoteStation station){
800 for(i=0;i<station->nRate;i++){
801 free(station->sampleTable[i]);
803 free(station->sampleTable);
804 free(station->minstrelTable);
807UINT get_minstrel_rate_index(NETSIM_ID dev,NETSIM_ID ifid,NETSIM_ID recv){
808 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
809 if(!station || !station->isInitialized)
811 return station->trRate;
814void print_minstrel_table(PMETRICSWRITER metricsWriter)
818 Ptr_MinstrelPerRemoteStation station;
822 PMETRICSNODE menu = init_metrics_node(MetricsNode_Menu,
"Minstrel Data", NULL);
823 PMETRICSNODE table = init_metrics_node(MetricsNode_Table,
"Minstrel table", NULL);
824 add_node_to_menu(menu, table);
826 add_table_heading_special(table,
"SourceId#1,DestinationId#1,Rate#1,RetryCount#0,Throughput#1,EwmaProb#0,CurrentSuccess#0,CurrentAttempt#0,TotalSuccess#0,TotalAttempt#0,StationSample#0,StationTotal#0,StationRetry#0,");
827 for(i=1;i<=NETWORK->nDeviceCount;i++)
829 if(isIEEE802_11_Configure(i,1))
831 if(IEEE802_11_MAC(i,1)->rate_adaptationAlgo!= RATEADAPTATION_MINSTREL)
833 for(j=1;j<=NETWORK->nDeviceCount;j++)
835 station= getMinstrelInfo(i,1,j);
838 if(station && station->totalPacketCount > 0){
840 for(k=0;k<station->nRate;k++){
841 add_table_row_formatted(
false,table,
"%d,%d,%lf,", DEVICE_CONFIGID(i), DEVICE_CONFIGID(j),station->minstrelTable[k].rate);
842 add_table_row_formatted(
true, table,
"%u,%lf,%lf,",station->minstrelTable[k].retryCount,station->minstrelTable[k].throughput,station->minstrelTable[k].ewmaProb);
843 add_table_row_formatted(
true, table,
"%u,%u,%llu,",station->minstrelTable[k].currNumSuccess,station->minstrelTable[k].currNumAttempt,station->minstrelTable[k].totalNumSuccess);
844 add_table_row_formatted(
true, table,
"%llu,",station->minstrelTable[k].totalNumAttempt);
846 add_table_row_formatted(
true, table,
"%llu,%llu,%llu,",station->samplePacketCount, station->totalPacketCount,station->totalRetry);
848 add_table_row_formatted(
true, table,
",,,");
855 write_metrics_node(metricsWriter, WriterPosition_Current, NULL, menu);
856 delete_metrics_node(menu);