NetSim Source Code Help
Loading...
Searching...
No Matches
Minstrel.c
Go to the documentation of this file.
1/************************************************************************************
2* Copyright (C) 2021 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#include "main.h"
25
26#include "Minstrel.h"
27
28static int show=0; //variable for showing Minstrel Table
29
30
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)
36
38{
39 switch (IEEE802_11_PHY(dev, ifid)->PhyProtocol)
40 {
41 case IEEE_802_11a:
42 case IEEE_802_11b:
43 case IEEE_802_11g:
44 case IEEE_802_11p:
45 {
47 return station->minstrelInfo[recv];
48 }
49 break;
50 case IEEE_802_11ac:
51 case IEEE_802_11n:
52 break;
53 default:
54 fnNetSimError("Unknown phy protocol in %s\n", __FUNCTION__);
55 }
56 return NULL;
57}
58
59void get_data_rate(NETSIM_ID devid,NETSIM_ID ifid,double* rate,unsigned int* len)
60{
61 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(devid,ifid);
62 switch(phy->PhyProtocol)
63 {
64 case IEEE_802_11a:
65 case IEEE_802_11g:
66 case IEEE_802_11p:
67 get_ofdm_phy_all_rate((int)phy->dChannelBandwidth, rate, len);
68 break;
69 case IEEE_802_11b:
70 get_dsss_phy_all_rate(rate, len);
71 break;
72 case IEEE_802_11n:
73 case IEEE_802_11ac:
74 default:
75 fnNetSimError("Unknown phy protocol %d in %s.\n",phy->PhyProtocol,__FUNCTION__);
76 return;
77 }
78}
79
81{
82 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
83 {
84 case IEEE_802_11a:
85 case IEEE_802_11b:
86 case IEEE_802_11g:
87 case IEEE_802_11p:
88 InitMinstrel(nDevId,nifid);
89 break;
90 case IEEE_802_11ac:
91 case IEEE_802_11n:
92 Ht_InitMinstrel(nDevId,nifid);
93 break;
94 default:
95 fnNetSimError("Unknown phy protocol in %s\n",__FUNCTION__);
96 }
97}
98
100{
101 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
102 {
103 case IEEE_802_11a:
104 case IEEE_802_11b:
105 case IEEE_802_11g:
106 case IEEE_802_11p:
107 return DoNeedDataRetransmission(nDevId,nifid,recvid);
108 break;
109 case IEEE_802_11ac:
110 case IEEE_802_11n:
111 return Ht_DoNeedDataRetransmission(nDevId,nifid,recvid);
112 break;
113 default:
114 fnNetSimError("Unknown phy protocol in %s\n",__FUNCTION__);
115 }
116 return false;
117}
118
120{
121 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
122 {
123 case IEEE_802_11a:
124 case IEEE_802_11b:
125 case IEEE_802_11g:
126 case IEEE_802_11p:
127 DoReportDataFailed(nDevId,nifid,recvid);
128 break;
129 case IEEE_802_11ac:
130 case IEEE_802_11n:
131 {
132 UINT c = 0;
134 while(p)
135 {
136 c++;
137 p=p->pstruNextPacket;
138 }
139 DoReportAmpduStatus(nDevId,nifid,recvid,0,c);
140 }
141 break;
142 default:
143 fnNetSimError("Unknown phy protocol in %s\n",__FUNCTION__);
144 }
145}
146
148{
149 switch(IEEE802_11_PHY(nDevId,nifid)->PhyProtocol)
150 {
151 case IEEE_802_11a:
152 case IEEE_802_11b:
153 case IEEE_802_11g:
154 case IEEE_802_11p:
155 DoReportFinalDataFailed(nDevId,nifid,recvid);
156 break;
157 case IEEE_802_11ac:
158 case IEEE_802_11n:
159 {
160 UINT c = 0;
162 while(p)
163 {
164 c++;
165 p=p->pstruNextPacket;
166 }
167 DoReportAmpduStatus(nDevId,nifid,recvid,0,c);
168 }
169 break;
170 default:
171 fnNetSimError("Unknown phy protocol in %s\n",__FUNCTION__);
172 }
173}
174
176 NETSIM_ID i;
177 Ptr_MinstrelWifiStation wifiStation;
178 //initialize the Minstrel global variables
179 show=1;
180 updateStatsTime = 100*1000; //100 ms
181 lookAroundRate= 10;
182 sampleCol = 10;
183 ewmaWeight = 25;
184
185 wifiStation = (Ptr_MinstrelWifiStation)calloc(1,sizeof(MinstrelWifiStation));
187
188 for(i=1;i<=NETWORK->nDeviceCount;i++)
189 {
191 {
193 CheckInit(wifiStation->minstrelInfo[i],nDevId,nifid);
194 }
195 }
196 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = wifiStation;
197}
198
200 if(!station->isInitialized){
201 UINT i,get_nrate;
202 double get_rate[10];
203 //function to get the available rates for the device
204 get_data_rate(nDevId,nifid,get_rate,&get_nrate);
205
206 station->nextStatsUpdate = ldEventTime + updateStatsTime; //fill
207 station->maxTpRate= 0;
208 station->maxTp2Rate= 0;
209 station->maxProbRate= 0;
210 station->phy = IEEE802_11_PHY(nDevId,nifid);
211
212 station->nRate = get_nrate; //fill
213 station->baseRate = 0;
214 for(i=0;i<station->nRate;i++)
215 if(get_rate[i] < get_rate[station->baseRate]) //fill
216 station->baseRate = i;
217
218 station->sampleRate= 0;
219 station->trRate= 0;
220
221 station->isSampling= false;
222 station->samplePacketCount= 0;
223 station->totalPacketCount= 0;
224 station->shortRetry= 0;
225 station->longRetry= 0;
226 station->totalRetry= 0;
227
228 station->col= 0;
229 station->row= 0;
230 InitSampleTable(station);
231 InitMinstrelTable(station,get_rate);
232 station->isInitialized = true;
233 }
234}
235
237 UINT i,j;
238 //Memory allocation for Sample Table
239 station->sampleTable = calloc(station->nRate, sizeof(UINT*));
240 for(i=0;i<station->nRate;i++){
241 station->sampleTable[i] = calloc(sampleCol,sizeof(UINT));
242 for(j=0;j<sampleCol;j++)
243 station->sampleTable[i][j] = 10000;
244 //memset(station->sampleTable[i],10000,sampleCol*sizeof(UINT));
245 }
246
247 //set indices for traversing in Sample Table
248 station->col = 0;
249 station->row = 0;
250 //Randomly filling table with values [0,nRate-1]
251 for(j=0;j<sampleCol;j++){
252 for(i=0;i<station->nRate;i++){
253 //generate the random number
254 int random_var = station->nRate*(int)rand01();
255 random_var = (i+random_var)%station->nRate;
256
257 while(station->sampleTable[random_var][j] != 10000){
258 random_var = (random_var + 1)%station->nRate;
259 }
260 station->sampleTable[random_var][j] = i;
261 }
262 }
263}
264
265static void InitMinstrelTable(Ptr_MinstrelPerRemoteStation station,double *rate_arr){
266 UINT i,cw;
267 double trTime;
268 station->minstrelTable = (RateInfo*)calloc(station->nRate,sizeof(RateInfo));
269 for(i=0;i<station->nRate;i++){
270 station->minstrelTable[i].currNumAttempt= 0;
271 station->minstrelTable[i].currNumSuccess= 0;
272 station->minstrelTable[i].prevNumAttempt = 0;
273 station->minstrelTable[i].prevNumSuccess = 0;
274 station->minstrelTable[i].totalNumAttempt= 0;
275 station->minstrelTable[i].totalNumSuccess= 0;
276 station->minstrelTable[i].prob= 0;
277 station->minstrelTable[i].ewmaProb= 0;
278 station->minstrelTable[i].throughput= 0;
279 station->minstrelTable[i].numSampleSkipped= 0;
280 station->minstrelTable[i].rate= rate_arr[i]; //fill
281 station->minstrelTable[i].sampleLimit= -1; //no limit
282 station->minstrelTable[i].retryCount= 1; //atleast 1 retry count for each rate
283 station->minstrelTable[i].adjustedRetryCount= 1;
284 station->minstrelTable[i].perfectTrTime= transmissionTime(station->phy,1500,rate_arr[i]); //fill
285
286 cw = 15; //minimum contention window
287 trTime= station->minstrelTable[i].perfectTrTime + ackTime(station->phy); //fill
288
289 while(1){
290 //add retransmission time
291 trTime += station->minstrelTable[i].perfectTrTime + ackTime(station->phy); //fill
292
293 //contention window and average backoff
294 trTime+= (tSlot(station->phy)*cw)>>1; //fill
295 cw = min((cw<<1)|1,1023); //max contention window = 1023
296
297 //retry count is limited by 6 millisecond
298 if(trTime < 6000){
299 station->minstrelTable[i].retryCount++;
300 station->minstrelTable[i].adjustedRetryCount++;
301 }
302 else{
303 break;
304 }
305 }
306 }
307 UpdateStats(station);
308}
309
311 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
312 if(!station->isInitialized)
313 return;
314
315 station->minstrelTable[station->trRate].currNumAttempt++;
316 station->minstrelTable[station->trRate].currNumSuccess++;
317
318 UpdatePacketCounter(station);
319 UpdateRetry(station);
320 UpdateStats(station);
321
322 if(station->nRate >=1)
323 station->trRate = FindRate(station);
324}
325
327 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
328 if(!station->isInitialized)
329 return;
330 UpdateRate(station);
331}
332
334 //Retry Chain Table is Implemented here.
335 //Only called when data fails
336
337 station->longRetry++;
338 station->totalPacketCount++;
339 station->minstrelTable[station->trRate].currNumAttempt++;
340 //if sample rate is used
341 if(station->isSampling && station->trRate == station->sampleRate)
342 station->samplePacketCount++;
343
344 //for normal rate, we aren't sampling rates
345 if(!station->isSampling){
346
347 //first try with best throughput
348 if(station->longRetry < station->minstrelTable[station->maxTpRate].adjustedRetryCount){
349 station->trRate = station->maxTpRate;
350 }
351 //use 2nd best throughput rate
352 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
353 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount){
354 station->trRate = station->maxTp2Rate;
355 }
356 //use best probability rate
357 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
358 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
359 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
360 station->trRate = station->maxProbRate;
361 }
362 //use lowest base rate
363 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
364 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
365 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
366 station->trRate = station->baseRate;
367 }
368 else{
369 fnNetSimError("Failed to Update Rate");
370 }
371 }
372 //for lookaround rate, currently sampling
373 else{
374 //current sampling is slower than current best rate
375 if(station->isDeferredSample){
376 //use best throughput rate
377 if(station->longRetry < station->minstrelTable[station->maxTpRate].adjustedRetryCount){
378 station->trRate = station->maxTpRate;
379 }
380 //use random rate
381 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
382 station->minstrelTable[station->sampleRate].adjustedRetryCount){
383 station->trRate = station->sampleRate;
384 }
385 //use best probability rate
386 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
387 station->minstrelTable[station->sampleRate].adjustedRetryCount +
388 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
389 station->trRate = station->maxProbRate;
390 }
391 //use lowest base rate
392 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
393 station->minstrelTable[station->sampleRate].adjustedRetryCount +
394 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
395 station->trRate = station->baseRate;
396 }
397 else{
398 fnNetSimError("Failed to Update Rate");
399 }
400 }
401 //current sampling rate is better than current best rate
402 else{
403 //use random rate
404 if(station->longRetry < station->minstrelTable[station->sampleRate].adjustedRetryCount){
405 station->trRate = station->sampleRate;
406 }
407 //use best throughput rate
408 else if(station->longRetry < station->minstrelTable[station->sampleRate].adjustedRetryCount +
409 station->minstrelTable[station->maxTpRate].adjustedRetryCount){
410 station->trRate = station->maxTpRate;
411 }
412 //use best probability rate
413 else if(station->longRetry <= station->minstrelTable[station->maxTpRate].adjustedRetryCount +
414 station->minstrelTable[station->sampleRate].adjustedRetryCount +
415 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
416 station->trRate = station->maxProbRate;
417 }
418 //use lowest base rate
419 else if(station->longRetry > station->minstrelTable[station->maxTpRate].adjustedRetryCount +
420 station->minstrelTable[station->sampleRate].adjustedRetryCount +
421 station->minstrelTable[station->maxProbRate].adjustedRetryCount){
422 station->trRate = station->baseRate;
423 }
424 else{
425 fnNetSimError("Failed to Update Rate");
426 }
427 }
428 }
429}
430
432 //Updates the packet counter of station
433 station->totalPacketCount++;
434
435 //If it is sampling and sampling rate is used
436 if(station->isSampling && station->trRate == station->sampleRate){
437 station->samplePacketCount++;
438 }
439
440 if(station->numSampleDeferred >0){
441 station->numSampleDeferred--;
442 }
443
444 //wrap around
445 if(station->totalPacketCount < 0){
446 station->numSampleDeferred = 0;
447 station->samplePacketCount = 0;
448 station->totalPacketCount = 0;
449 }
450
451 //whether sampling/deferred sample or not will be decided by "FindRate"
452 station->isSampling = false;
453 station->isDeferredSample = false;
454}
455
457 station->totalRetry += station->longRetry + station->shortRetry;
458 station->longRetry = 0;
459 station->shortRetry = 0;
460}
461
463 UINT i,index_max_tp, index_max_tp2, index_max_prob;
464 double tempProb, max_prob, max_tp;
465 //Update time has not come
466 if(ldEventTime < station->nextStatsUpdate){
467 return;
468 }
469 if(!station->isInitialized){
470 return;
471 }
473 //update for each rate in minstrel table
474 for(i=0;i<station->nRate;i++){
475 double trTime;
476 trTime = station->minstrelTable[i].perfectTrTime;
477
478 //just for initialization
479 if(trTime == 0){
480 trTime = 1000*1000; //1 second
481 }
482
483 //if attempted something
484 if(station->minstrelTable[i].currNumAttempt){
485 station->minstrelTable[i].numSampleSkipped = 0;
486 //calculate probability of success
487 tempProb = (station->minstrelTable[i].currNumSuccess*18000) / station->minstrelTable[i].currNumAttempt;
488 tempProb = tempProb/18000.0;
489 station->minstrelTable[i].prob = tempProb;
490
491 //Updating this rate for the first time
492 if(station->minstrelTable[i].totalNumAttempt == 0){
493 station->minstrelTable[i].ewmaProb = tempProb;
494 }
495 else{
496 //ewma probability
497 tempProb = (tempProb*ewmaWeight + station->minstrelTable[i].ewmaProb*(100-ewmaWeight))/100;
498 station->minstrelTable[i].ewmaProb = tempProb;
499 }
500
501 //calculate Throughput(using ewmaProb)
502 //linux implementation
503 if(tempProb < 0.1)
504 station->minstrelTable[i].throughput = 0;
505 else
506 station->minstrelTable[i].throughput = (tempProb*8*1500)/(trTime); //fill
507
508 }
509 //if not attempted at this rate
510 else{
511 station->minstrelTable[i].numSampleSkipped++;
512 }
513
514 //bookkeeping
519 station->minstrelTable[i].currNumAttempt = 0;
520 station->minstrelTable[i].currNumSuccess = 0;
521
522 //sample less often below 10% and above 95% success
523 if(station->minstrelTable[i].ewmaProb < 0.1 || station->minstrelTable[i].ewmaProb > 0.95){
524 /**
525 * See: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/minstrel/
526 *
527 * Analysis of information showed that the system was sampling too hard at some rates.
528 * For those rates that never work (54mb, 500m range) there is no point in retrying 10 sample packets (< 6 ms time).
529 * Consequently, for the very low probability rates, we try at most twice when fails and not sample more than 4 times.
530 */
531 if(station->minstrelTable[i].retryCount > 2){
532 station->minstrelTable[i].adjustedRetryCount = 2;
533 }
534 station->minstrelTable[i].sampleLimit = 4;
535 }
536 else{
537 //no sampling limit
538 station->minstrelTable[i].sampleLimit = -1;
540 }
541
542 //if its 0,allow two retries (generally wont happen)
543 if(station->minstrelTable[i].adjustedRetryCount == 0)
544 station->minstrelTable[i].adjustedRetryCount = 2;
545 }
546
547 max_tp=0;
548 index_max_tp= 0;
549 index_max_tp2= 0;
550 index_max_prob=0;
551 max_prob=0;
552 //find the max throughput
553 for(i=0;i<station->nRate;i++){
554 if(max_tp < station->minstrelTable[i].throughput){
555 index_max_tp = i;
556 max_tp = station->minstrelTable[i].throughput;
557 }
558 }
559 //find the 2nd max throughput and high probability succ
560 max_tp=0;
561 for(i=0;i<station->nRate;i++){
562 if(i != index_max_tp && max_tp < station->minstrelTable[i].throughput){
563 index_max_tp2 = i;
564 max_tp = station->minstrelTable[i].throughput;
565 }
566 }
567 //find high probability success rate
568 for(i=0;i<station->nRate;i++){
569 //above 95% choose with highest throughput
570 if(station->minstrelTable[i].ewmaProb >= 0.95 && station->minstrelTable[i].throughput >= station->minstrelTable[index_max_prob].throughput){
571 index_max_prob = i;
572 max_prob = station->minstrelTable[i].ewmaProb;
573 }
574 else if(station->minstrelTable[i].ewmaProb >= max_prob){
575 index_max_prob = i;
576 max_prob = station->minstrelTable[i].ewmaProb;
577 }
578 }
579 station->maxTpRate = index_max_tp;
580 station->maxTp2Rate = index_max_tp2;
581 station->maxProbRate = index_max_prob;
582}
583
585 UINT idx;
586 int delta;
587 if(station->totalPacketCount == 0)
588 return 0;
589
590 delta = (int)(((station->totalPacketCount*lookAroundRate)/100) - (station->samplePacketCount + station->numSampleDeferred/2 ));
591 //if delta < 0: no sampling required
592 //if delta > 0: insufficient sampling
593 if(delta >=0)
594 {
595 UINT n_rates = station->nRate;
596 if(delta > (int)(2* n_rates)){
597 /* From Linux implementation:
598 * With multi-rate retry, not every planned sample
599 * attempt actually gets used, due to the way the retry
600 * chain is set up - [max_tp,sample,prob,lowest] for
601 * sample_rate < max_tp.
602 *
603 * If there's too much sampling backlog and the link
604 * starts getting worse, minstrel would start bursting
605 * out lots of sampling frames, which would result
606 * in a large throughput loss. */
607 station->samplePacketCount += delta - 2*n_rates;
608 }
609
610 idx = GetNextSample(station); //fill
611 if(idx >= n_rates)
612 fnNetSimError("Unknown rate...!");
613
614 station->sampleRate = idx;
615
616 /* From Linux implementation:
617 * Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
618 * rate sampling method should be used.
619 * Respect such rates that are not sampled for 20 iterations.
620 */
621
622 if((station->minstrelTable[idx].perfectTrTime > station->minstrelTable[station->maxTpRate].perfectTrTime)
623 && station->minstrelTable[idx].numSampleSkipped < 20){
624 //if rate is slower defer to 2nd stage
625 station->isDeferredSample = true;
626 station->numSampleDeferred++;
627
628 //set flag for currently sampling
629 station->isSampling = true;
630 }
631 else{
632 //if sample limit is zero then dont sample this rate
633 if(station->minstrelTable[idx].sampleLimit == 0){
634 idx = station->maxTpRate;
635 station->isSampling = false;
636 }
637 else{
638 //set flag for currently sampling
639 station->isSampling = true;
640 if(station->minstrelTable[idx].sampleLimit > 0)
641 station->minstrelTable[idx].sampleLimit--;
642 }
643 }
644
645 //sample rate is slower
646 if(station->isDeferredSample){
647 idx = station->maxTpRate;
648 }
649 }
650 //delta < 0: no sampling required, continue using best rate
651 else
652 {
653 idx = station->maxTpRate;
654 }
655
656 return idx;
657}
658
660 UINT sample_rate = station->sampleTable[station->row][station->col];
661
662 //bookkeeping for next sample index
663 station->row++;
664 if(station->row >= station->nRate){
665 station->row = 0;
666 station->col++;
667 if(station->col >= sampleCol)
668 station->col = 0;
669 }
670 return sample_rate;
671}
672
673//void DoReportFinalDataFailed(Ptr_MinstrelPerRemoteStation station){
675 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
676 if(!station->isInitialized)
677 return;
678
679 UpdatePacketCounter(station);
680 UpdateRetry(station);
681 UpdateStats(station);
682
683 if(station->nRate >= 1)
684 station->trRate=FindRate(station);
685}
686
687//BOOL DoNeedDataRetransmission(Ptr_MinstrelPerRemoteStation station){
689 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
690 //check if we can do retransmission
691 if(!station->isInitialized)
692 return false;
693 if(station->longRetry > CountRetry(station))
694 return false;
695 else
696 return true;
697}
698
700 //if not sampling
701 if(!station->isSampling){
702 return station->minstrelTable[station->maxTpRate].adjustedRetryCount +
703 station->minstrelTable[station->maxTp2Rate].adjustedRetryCount +
704 station->minstrelTable[station->maxProbRate].adjustedRetryCount +
705 station->minstrelTable[station->baseRate].adjustedRetryCount;
706 }
707 else{
708 return station->minstrelTable[station->maxTpRate].adjustedRetryCount +
709 station->minstrelTable[station->sampleRate].adjustedRetryCount +
710 station->minstrelTable[station->maxProbRate].adjustedRetryCount +
711 station->minstrelTable[station->baseRate].adjustedRetryCount;
712 }
713}
714
716 station->shortRetry++;
717}
718
720 UpdateRetry(station);
721}
723{
724 NETSIM_ID i;
726 for(i=0;i<=NETWORK->nDeviceCount;i++){
727 if(wifistation->minstrelInfo[i])
728 {
729 FreeTables(wifistation->minstrelInfo[i]);
730 free(wifistation->minstrelInfo[i]);
731 }
732 }
733 free(wifistation->minstrelInfo);
734 free(wifistation);
735 IEEE802_11_PHY(nDevId,nifid)->rateAdaptationData = NULL;
736}
737
739{
740 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(nDevId, nifid);
741 switch(phy->PhyProtocol)
742 {
743 case IEEE_802_11a:
744 case IEEE_802_11b:
745 case IEEE_802_11g:
746 case IEEE_802_11p:
747 Minstrel_Free(nDevId,nifid);
748 break;
749 case IEEE_802_11ac:
750 case IEEE_802_11n:
751 HT_Minstrel_Free(nDevId,nifid);
752 break;
753 default:
754 fnNetSimError("Unknown phy protocol %d for device %d interface %d in %s\n", phy->PhyProtocol,
755 nDevId, nifid, __FUNCTION__);
756 }
757}
758
760 UINT i;
761 for(i=0;i<station->nRate;i++){
762 free(station->sampleTable[i]);
763 }
764 free(station->sampleTable);
765 free(station->minstrelTable);
766}
767
769 Ptr_MinstrelPerRemoteStation station = getMinstrelInfo(dev,ifid,recv);
770 if(!station || !station->isInitialized)
771 return 0;
772 return station->trRate;
773}
774
776{
777 NETSIM_ID i, j;
778 UINT k;
780 if(!show)
781 return;
782
783 PMETRICSNODE menu = init_metrics_node(MetricsNode_Menu, "Minstrel Data", NULL);
784 PMETRICSNODE table = init_metrics_node(MetricsNode_Table, "Minstrel table", NULL);
785 add_node_to_menu(menu, table);
786
787 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,");
788 for(i=1;i<=NETWORK->nDeviceCount;i++)
789 {
791 {
792 if(IEEE802_11_MAC(i,1)->rate_adaptationAlgo!= RATEADAPTATION_MINSTREL)
793 continue;
794 for(j=1;j<=NETWORK->nDeviceCount;j++)
795 {
796 station= getMinstrelInfo(i,1,j); //ifid is believed to be 1..Change if necessary
797 if(!station)
798 continue;
799 if(station && station->totalPacketCount > 0){ //print only if there is transmission
800
801 for(k=0;k<station->nRate;k++){
802 add_table_row_formatted(false,table, "%d,%d,%lf,", DEVICE_CONFIGID(i), DEVICE_CONFIGID(j),station->minstrelTable[k].rate);
803 add_table_row_formatted(true, table, "%u,%lf,%lf,",station->minstrelTable[k].retryCount,station->minstrelTable[k].throughput,station->minstrelTable[k].ewmaProb);
804 add_table_row_formatted(true, table, "%u,%u,%llu,",station->minstrelTable[k].currNumSuccess,station->minstrelTable[k].currNumAttempt,station->minstrelTable[k].totalNumSuccess);
805 add_table_row_formatted(true, table, "%llu,",station->minstrelTable[k].totalNumAttempt);
806 if(k==0)
807 add_table_row_formatted(true, table, "%llu,%llu,%llu,",station->samplePacketCount, station->totalPacketCount,station->totalRetry);
808 else
809 add_table_row_formatted(true, table, ",,,");
810
811 }
812 }
813 }
814 }
815 }
816 write_metrics_node(metricsWriter, WriterPosition_Current, NULL, menu);
818}
unsigned int NETSIM_ID
Definition: Animation.h:45
PIEEE802_11_MAC_VAR IEEE802_11_MAC(NETSIM_ID ndeviceId, NETSIM_ID nInterfaceId)
bool isIEEE802_11_Configure(NETSIM_ID ndeviceId, NETSIM_ID nInterfaceId)
PIEEE802_11_PHY_VAR IEEE802_11_PHY(NETSIM_ID ndeviceId, NETSIM_ID nInterfaceId)
void get_ofdm_phy_all_rate(int bandwidth_MHz, double *rate, UINT *len)
@ RATEADAPTATION_MINSTREL
Definition: IEEE802_11.h:194
void Ht_InitMinstrel(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel_ht.c:40
void DoReportAmpduStatus(NETSIM_ID devid, NETSIM_ID ifid, NETSIM_ID recvid, UINT success, UINT failed)
Definition: Minstrel_ht.c:210
@ IEEE_802_11ac
Definition: IEEE802_11.h:72
@ IEEE_802_11b
Definition: IEEE802_11.h:67
@ IEEE_802_11n
Definition: IEEE802_11.h:70
@ IEEE_802_11g
Definition: IEEE802_11.h:68
@ IEEE_802_11p
Definition: IEEE802_11.h:69
@ IEEE_802_11a
Definition: IEEE802_11.h:66
BOOL Ht_DoNeedDataRetransmission(NETSIM_ID devid, NETSIM_ID ifid, NETSIM_ID recvid)
Definition: Minstrel_ht.c:702
void HT_Minstrel_Free(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel_ht.c:780
void get_dsss_phy_all_rate(double *rate, UINT *len)
#define c
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 free(p)
Definition: Memory.h:31
#define calloc(c, s)
Definition: Memory.h:29
@ WriterPosition_Current
Definition: MetricsWriter.h:15
void write_metrics_node(PMETRICSWRITER writer, WRITER_POSITION writerPosition, char *writer_name, PMETRICSNODE node)
void add_table_heading_special(PMETRICSNODE node, char *heading)
PMETRICSNODE init_metrics_node(METRICS_NODE type, char *name, char *secondarg)
void * PMETRICSNODE
Definition: MetricsWriter.h:21
void * PMETRICSWRITER
Definition: MetricsWriter.h:27
void delete_metrics_node(PMETRICSNODE node)
void add_node_to_menu(PMETRICSNODE menu, PMETRICSNODE node)
void add_table_row_formatted(bool issame, PMETRICSNODE node, char *format,...)
@ MetricsNode_Menu
Definition: MetricsWriter.h:5
@ MetricsNode_Table
Definition: MetricsWriter.h:6
BOOL Minstrel_DoNeedDataSend(NETSIM_ID nDevId, NETSIM_ID nifid, NETSIM_ID recvid)
Definition: Minstrel.c:99
BOOL DoNeedDataRetransmission(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:688
static UINT GetNextSample(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:659
void DoReportDataFailed(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:326
static UINT CountRetry(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:699
void Minstrel_Init(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel.c:80
static void UpdateRetry(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:456
void print_minstrel_table(PMETRICSWRITER metricsWriter)
Definition: Minstrel.c:775
static void UpdatePacketCounter(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:431
#define ackTime(phy)
Definition: Minstrel.c:33
void DoReportDataOk(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:310
void Minstrel_Free(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel.c:722
static UINT FindRate(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:584
#define transmissionTime(phy, byte, rate)
Definition: Minstrel.c:35
static void InitMinstrelTable(Ptr_MinstrelPerRemoteStation station, double *rate_arr)
Definition: Minstrel.c:265
static void DoReportFinalRtsFailed(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:719
void FreeMinstrel(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel.c:738
void DoReportFinalDataFailed(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:674
static int show
Definition: Minstrel.c:28
static void DoReportRtsFailed(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:715
static void UpdateRate(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:333
static Ptr_MinstrelPerRemoteStation getMinstrelInfo(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:37
static void UpdateStats(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:462
void FreeTables(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:759
static void InitSampleTable(Ptr_MinstrelPerRemoteStation station)
Definition: Minstrel.c:236
#define rand01()
Definition: Minstrel.c:32
void get_data_rate(NETSIM_ID devid, NETSIM_ID ifid, double *rate, unsigned int *len)
Definition: Minstrel.c:59
UINT get_minstrel_rate_index(NETSIM_ID dev, NETSIM_ID ifid, NETSIM_ID recv)
Definition: Minstrel.c:768
void InitMinstrel(NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel.c:175
void Minstrel_ReportDataFailed(NETSIM_ID nDevId, NETSIM_ID nifid, NETSIM_ID recvid)
Definition: Minstrel.c:119
#define tSlot(phy)
Definition: Minstrel.c:34
static void CheckInit(Ptr_MinstrelPerRemoteStation station, NETSIM_ID nDevId, NETSIM_ID nifid)
Definition: Minstrel.c:199
void Minstrel_ReportFinalDataFailed(NETSIM_ID nDevId, NETSIM_ID nifid, NETSIM_ID recvid)
Definition: Minstrel.c:147
double updateStatsTime
Definition: Minstrel.h:71
double lookAroundRate
Definition: Minstrel.h:72
struct stru_MinstrelWifiRemoteStation * Ptr_MinstrelPerRemoteStation
struct stru_MinstrelWifiStation * Ptr_MinstrelWifiStation
double ewmaWeight
Definition: Minstrel.h:73
UINT sampleCol
Definition: Minstrel.h:74
EXPORTED double ldEventTime
Definition: Stack.h:838
#define DEVICE_CONFIGID(DeviceId)
Definition: Stack.h:779
EXPORTED struct stru_NetSim_Network * NETWORK
Definition: Stack.h:742
PMETRICSNODE menu
Definition: SwitchTable.c:48
NetSim_PACKET * currentProcessingPacket
Definition: IEEE802_11.h:256
IEEE802_11_PROTOCOL PhyProtocol
PIEEE802_11_PHY_VAR phy
Definition: Minstrel.h:68
Ptr_MinstrelPerRemoteStation * minstrelInfo
Definition: Minstrel.h:78
struct stru_NetSim_Packet * pstruNextPacket
Definition: Packet.h:278
int sampleLimit
Definition: Minstrel.h:41
double prob
Definition: Minstrel.h:32
UINT prevNumAttempt
Definition: Minstrel.h:29
UINT prevNumSuccess
Definition: Minstrel.h:30
UINT adjustedRetryCount
Definition: Minstrel.h:26
UINT retryCount
Definition: Minstrel.h:25
UINT currNumSuccess
Definition: Minstrel.h:28
UINT currNumAttempt
Definition: Minstrel.h:27
double ewmaProb
Definition: Minstrel.h:34
double rate
Definition: Minstrel.h:19
double perfectTrTime
Definition: Minstrel.h:23
double throughput
Definition: Minstrel.h:35
UINT numSampleSkipped
Definition: Minstrel.h:40
UINT64 totalNumAttempt
Definition: Minstrel.h:37
UINT64 totalNumSuccess
Definition: Minstrel.h:38