NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
CSMACA.c
1/************************************************************************************
2* Copyright (C) 2023 *
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#include "IEEE802_11.h"
26#include "IEEE802_11_Phy.h"
27#include "IEEE802_11_MAC_Frame.h"
28#include "NetSim_utility.h"
29
30//Function prototype
31static void fn_NetSim_IEEE802_11_CSMACA_RandomBackOffTimeCalculation();
32static void fn_NetSim_IEEE802_11_CSMACA_StartBackOff();
33
34static double get_CSMACA_Time(PIEEE802_11_PHY_VAR phy)
35{
36 if (!phy->dControlFrameDataRate)
37 fnNetSimError("Control frame data rate is 0 for device %d, interface %d in %s\n",
38 pstruEventDetails->nDeviceId,
39 pstruEventDetails->nInterfaceId,
40 __FUNCTION__);
41 return phy->DIFS +
42 phy->plmeCharacteristics.aSIFSTime +
43 get_preamble_time(phy) +
44 ((getAckSize(phy) * 8) / phy->dControlFrameDataRate);
45
46}
47
48int fn_NetSim_IEEE802_11_CSMACA_Init()
49{
50 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
51 PIEEE802_11_PHY_VAR phy = IEEE802_11_CURR_PHY;
52 phy;
53 NetSim_PACKET* packet;
54
55 if(!isCurrSTAIdle)
56 return -1; //Either mac is busy or radio is busy
57
58 if (mac->dNAV > pstruEventDetails->dEventTime)
59 return -1; // NAV blocked
60
61 //Check buffer has packets to send
62 if(mac->currentProcessingPacket)
63 packet = mac->currentProcessingPacket;
64 else
65 {
66 // Get packet from buffer
67 UINT n;
68 packet = get_from_queue(pstruEventDetails->nDeviceId,
69 pstruEventDetails->nInterfaceId,
70 mac->nNumberOfAggregatedPackets,
71 &n);
72 if(!packet)
73 return -2;
74 mac->currentProcessingPacket=packet;
75 mac->nCWcurrent = mac->currEdcaTable->CWmin;
76 }
77
78 mac->dPacketProcessingEndTime = pstruEventDetails->dEventTime; //Set current time
79
80 //Call RTS-CTS
81 fn_NetSim_IEEE802_11_RTS_CTS_Init();
82
83 //Update packet processing time
84 mac->dPacketProcessingEndTime += get_CSMACA_Time(IEEE802_11_CURR_PHY);
85
86 if (!validate_processing_time(mac->dPacketProcessingEndTime,pstruEventDetails->nDeviceId,pstruEventDetails->nInterfaceId))
87 return -1;
88
89 packet = mac->currentProcessingPacket; //Processing packet may change due to RTS
90
91 // Add MAC_OUT_EVENT
92 NetSim_EVENTDETAILS pevent;
93 memcpy(&pevent, pstruEventDetails, sizeof pevent);
94 pevent.nPacketId = packet->nPacketId;
95 if(packet->pstruAppData)
96 {
97 pevent.nSegmentId = packet->pstruAppData->nSegmentId;
98 pevent.nApplicationId = packet->pstruAppData->nApplicationId;
99 }
100 else
101 {
102 pevent.nSegmentId = 0;
103 pevent.nApplicationId = 0;
104 }
105
106 if(packet->pstruNetworkData)
107 pevent.dPacketSize = packet->pstruNetworkData->dPacketSize;
108 else
109 pevent.dPacketSize = packet->pstruMacData->dPacketSize;
110 pevent.pPacket = packet;
111 pevent.nProtocolId = MAC_PROTOCOL_IEEE802_11;
112 pevent.nSubEventType = CS;
113 pevent.nEventType = MAC_OUT_EVENT;
114 fnpAddEvent(&pevent);
115 return 0;
116}
117
118bool fn_NetSim_IEEE802_11_CSMACA_CS()
119{
120 return (isCurrSTAIdle && isCurrSTAMediumIdle());
121}
122
123/**
124~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125This function called when CHECK_NAV subevent triggered. It is called if the Medium
126is IDLE and a packet in the Access buffer to transmit.
127If NAV <=0 then change the state to Wait_DIFS and add DIFS_END subevent.
128If NAV > 0 then change the state to WF_NAV and add NAV_END subevent.
129~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130*/
131int fn_NetSim_IEEE802_11_CSMACA_CheckNAV()
132{
133 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
134 PIEEE802_11_PHY_VAR phy = IEEE802_11_CURR_PHY;
135
136 if(pstruEventDetails->dEventTime >= mac->dNAV-4)
137 {
138 if (isDCF(mac))
139 {
140 // Change the State
141 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_Wait_DIFS);
142 // Add DIFS_END subevent
143 pstruEventDetails->dEventTime += phy->DIFS;
144 pstruEventDetails->nSubEventType = IEEE802_11_EVENT_DIFS_END;
145 mac->EVENTID.difsEnd = fnpAddEvent(pstruEventDetails);
146 }
147 else if(isEDCAF(mac))
148 {
149 // Change the State
150 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_Wait_AIFS);
151 // Add DIFS_END subevent
152 pstruEventDetails->dEventTime += mac->currEdcaTable->AIFSN * getSlotTime(phy) * 1.0;
153 pstruEventDetails->nSubEventType = IEEE802_11_EVENT_AIFS_END;
154 mac->EVENTID.aifsEnd = fnpAddEvent(pstruEventDetails);
155 }
156 else
157 {
158 fnNetSimError("Unknown Medium access protocol\n");
159 }
160 }
161 return 0;
162}
163
164void ieee802_11_csmaca_difs_failed(PIEEE802_11_MAC_VAR mac)
165{
166 fnDeleteEvent(mac->EVENTID.difsEnd);
167 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_MAC_IDLE);
168}
169
170void ieee802_11_csmaca_aifs_failed(PIEEE802_11_MAC_VAR mac)
171{
172 fnDeleteEvent(mac->EVENTID.aifsEnd);
173 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_MAC_IDLE);
174}
175
176/**
177~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178When the buffer has packet to transmit, the MAC LAYER sense the Medium. If it is IDLE,
179then it will wait for DCF Inter Frame Space (DIFS) time before start transmission.
180At the end of DIFS time check the Medium. If Medium is IDLE, then change the State
181to BACKING_OFF, call the function to start back off. If Medium is BUSY, then change
182the state to IDLE.
183~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184*/
185void fn_NetSim_IEEE802_11_CSMACA_DIFSEnd()
186{
187 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
188 // check the medium
189 if(isCurrSTAMediumIdle())
190 {
191 // Change the state
192 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_BACKING_OFF);
193
194 // Start Back off
195 fn_NetSim_IEEE802_11_CSMACA_StartBackOff();
196 }
197 else if(mac->currMacState==IEEE802_11_MACSTATE_Wait_DIFS)
198 {
199 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_MAC_IDLE);
200 }
201}
202
203void fn_NetSim_IEEE802_11_CSMACA_AIFSEnd()
204{
205 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
206 // check the medium
207 if (isCurrSTAMediumIdle())
208 {
209 // Change the state
210 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_BACKING_OFF);
211
212 // Start Back off
213 fn_NetSim_IEEE802_11_CSMACA_StartBackOff();
214 }
215 else if (mac->currMacState == IEEE802_11_MACSTATE_Wait_AIFS)
216 {
217 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_MAC_IDLE);
218 }
219}
220
221/**
222This function start the Backoff process. If backoff counter != 0,it adds the backoff event at (event
223time + backoff time) else it generate the random backoff time and add the backoff event.
224*/
225static void fn_NetSim_IEEE802_11_CSMACA_StartBackOff()
226{
227 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
228 PIEEE802_11_PHY_VAR phy = IEEE802_11_CURR_PHY;
229 mac->dBackOffStartTime = pstruEventDetails->dEventTime;
230 if(mac->nBackOffCounter == 0)
231 fn_NetSim_IEEE802_11_CSMACA_RandomBackOffTimeCalculation();
232
233 print_ieee802_11_log("Time %lf, Device %d, Interface %d, Starting backoff. Counter is %d.",
234 pstruEventDetails->dEventTime,
235 mac->deviceId,
236 mac->interfaceId,
237 mac->nBackOffCounter);
238
239
240 print_ieee802_11_Backoff_log("%s,%lf,%lld,%d,%d,%d,",
241 DEVICE_NAME(mac->deviceId),
242 pstruEventDetails->dEventTime,
243 mac->currentProcessingPacket->nPacketId,
244 mac->nBackOffCounter,
245 mac->nCWcurrent, mac->nRetryCount);
246
247
248
249 mac->dBackOffStartTime = pstruEventDetails->dEventTime;
250 mac->dBackoffLeftTime = mac->nBackOffCounter*
251 phy->plmeCharacteristics.aSlotTime +
252 mac->dBackOffStartTime;
253
254 mac->dPacketProcessingEndTime += mac->dBackoffLeftTime -
255 mac->dBackOffStartTime; //Add backoff time
256 if (!validate_processing_time(mac->dPacketProcessingEndTime,
257 pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId))
258 return;
259
260 pstruEventDetails->dEventTime += phy->plmeCharacteristics.aSlotTime;
261 pstruEventDetails->nSubEventType = IEEE802_11_EVENT_BACKOFF;
262 mac->EVENTID.backoff = fnpAddEvent(pstruEventDetails);
263}
264
265
266/**
267This function invokes the Back off time calculation.
268BackoffTime = RandomNumber(Between CW) * SlotTime.
269*/
270static void fn_NetSim_IEEE802_11_CSMACA_RandomBackOffTimeCalculation()
271{
272 double dRandomNumber = 0.0;
273 PIEEE802_11_MAC_VAR mac=IEEE802_11_CURR_MAC;
274 NETSIM_ID nDeviceId = pstruEventDetails->nDeviceId;
275
276 dRandomNumber = fn_NetSim_Utilities_GenerateRandomNo(&NETWORK->ppstruDeviceList[nDeviceId-1]->ulSeed[0],&NETWORK->ppstruDeviceList[nDeviceId-1]->ulSeed[1]);
277 dRandomNumber /= NETSIM_RAND_MAX;
278 dRandomNumber *= mac->nCWcurrent;
279 mac->nBackOffCounter = (int)dRandomNumber;
280}
281
282bool fn_NetSim_IEEE802_11_CSMACA_Backoff()
283{
284 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
285 PIEEE802_11_PHY_VAR phy = IEEE802_11_CURR_PHY;
286
287 assert(mac->nBackOffCounter>=0);
288
289 //Take care of back-off freeze
290 mac->dPacketProcessingEndTime = max(mac->dPacketProcessingEndTime, pstruEventDetails->dEventTime);
291
292 if(phy->radio.radioState != RX_ON_IDLE) // Back-off failed
293 {
294 if(mac->currMacState==IEEE802_11_MACSTATE_BACKING_OFF)
295 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_MAC_IDLE);
296 mac->metrics.nBackoffFailedCount++;
297 //mac->dBackoffLeftTime=0;
298 //mac->nBackOffCounter=0;
299 print_ieee802_11_log("Time %lf micro sec, Backoff failed for %d-%d due to radio is not idle\n",
300 ldEventTime, pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId);
301 return false;
302 }
303
304 if(isCurrSTAMediumIdle())
305 {
306 mac->nBackOffCounter--;
307 if(mac->nBackOffCounter>0) // Back-off in progress
308 {
309 pstruEventDetails->dEventTime += phy->plmeCharacteristics.aSlotTime;
310
311 if (!validate_processing_time(pstruEventDetails->dEventTime,
312 pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId))
313 return false; //Stop back-off process
314
315 pstruEventDetails->nSubEventType = IEEE802_11_EVENT_BACKOFF;
316 mac->EVENTID.backoff = fnpAddEvent(pstruEventDetails);
317 return false;
318 }
319 else // Back-off successful
320 {
321 mac->nBackOffCounter=0;
322 mac->dBackoffLeftTime=0;
323 mac->metrics.nBackoffSuccessCount++;
324 print_ieee802_11_log("Time %lf micro sec, Backoff Suceesful for %d-%d\n",
325 ldEventTime, pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId);
326 return true;
327 }
328 }
329 else
330 {
331 if(mac->nBackOffCounter<=1) // Back-off failed
332 {
333 if(mac->currMacState==IEEE802_11_MACSTATE_BACKING_OFF)
334 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_MAC_IDLE);
335 mac->metrics.nBackoffFailedCount++;
336 mac->dBackoffLeftTime=0;
337 mac->nBackOffCounter=0;
338 print_ieee802_11_log("Time %lf micro sec, Backoff failed for %d-%d due to medium is not idle\n",
339 ldEventTime, pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId);
340 return false;
341 }
342 else // Back-off Freeze
343 {
344 pstruEventDetails->dEventTime += phy->plmeCharacteristics.aSlotTime;
345
346 if (!validate_processing_time(pstruEventDetails->dEventTime,
347 pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId))
348 return false; //Stop back-off process
349
350 pstruEventDetails->nSubEventType = IEEE802_11_EVENT_BACKOFF;
351 mac->EVENTID.backoff = fnpAddEvent(pstruEventDetails);
352 print_ieee802_11_log("Time %lf micro sec, Backoff paused for %d-%d due to medium is not idle.\n",
353 ldEventTime, pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId);
354 return false;
355 }
356 }
357}
358
359void ieee802_11_csmaca_pause_backoff(PIEEE802_11_MAC_VAR mac)
360{
361 fnDeleteEvent(mac->EVENTID.backoff);
362 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_MAC_IDLE);
363}
364
365/**
366This function is called to create and send an Ack after receiving the DATA
367from the destination or from the AP
368*/
369int fn_NetSim_IEEE802_11_CSMACA_SendACK()
370{
371 NetSim_PACKET* packet=fn_NetSim_IEEE802_11_CreateAckPacket(pstruEventDetails->nDeviceId,
372 pstruEventDetails->nInterfaceId,
373 pstruEventDetails->pPacket,
374 pstruEventDetails->dEventTime);
375
376 //Free the data packet
377 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
378
379 // Add SEND ACK sub-event
380 pstruEventDetails->dEventTime += IEEE802_11_CURR_PHY->SIFS;
381 pstruEventDetails->dPacketSize = packet->pstruMacData->dPacketSize;
382 pstruEventDetails->nSubEventType = 0;
383 pstruEventDetails->nEventType = PHYSICAL_OUT_EVENT;
384 pstruEventDetails->pPacket = packet;
385 fnpAddEvent(pstruEventDetails);
386 // Change the state
387 IEEE802_11_Change_Mac_State(IEEE802_11_CURR_MAC,IEEE802_11_MACSTATE_TXing_ACK);
388 return 0;
389}
390
391void fn_NetSim_IEEE802_11_CSMACA_ProcessAck()
392{
393 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
394
395 NetSim_PACKET* p=mac->currentProcessingPacket;
396
397 //Call rate adaptation
398 if(mac->rate_adaptationAlgo== RATEADAPTATION_GENERIC)
399 packet_recv_notify(pstruEventDetails->nDeviceId,
400 pstruEventDetails->nInterfaceId,
401 pstruEventDetails->pPacket->nTransmitterId);
402 else if(mac->rate_adaptationAlgo== RATEADAPTATION_MINSTREL)
403 DoReportDataOk(pstruEventDetails->nDeviceId,
404 pstruEventDetails->nInterfaceId,
405 pstruEventDetails->pPacket->nTransmitterId);
406
407 while (p)
408 {
409 NetSim_PACKET* t=p;
410 p=p->pstruNextPacket;
411 if(t->ReceiveAckNotification)
412 t->ReceiveAckNotification(pstruEventDetails->pPacket);
413 fn_NetSim_Packet_FreePacket(t);
414 }
415 mac->currentProcessingPacket=NULL;
416 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
417 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_MAC_IDLE);
418
419 if (ieee802_11_edcaf_is_txop_timer_set(mac, ldEventTime))
420 {
421 // Get packet from buffer
422 UINT n;
423 NetSim_PACKET* packet = get_from_queue(pstruEventDetails->nDeviceId,
424 pstruEventDetails->nInterfaceId,
425 mac->nNumberOfAggregatedPackets,
426 &n);
427
428 if (!packet) ieee802_11_edcaf_unset_txop_time(mac);
429 else
430 {
431 mac->currentProcessingPacket = packet;
432 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(mac->deviceId, mac->parentInterfaceId);
433
434 //Wait for SIFS and then transmit packet
435 pstruEventDetails->dEventTime += getSIFSTime(phy);
436 fn_NetSim_IEEE802_11_SendToPhy();
437 }
438 }
439 else
440 {
441 ieee802_11_edcaf_unset_txop_time(mac);
442 fn_NetSim_IEE802_11_MacReInit(pstruEventDetails->nDeviceId,
443 pstruEventDetails->nInterfaceId);
444 }
445 fnDeleteEvent(mac->EVENTID.ackTimeOut);
446}
447
448void fn_NetSim_IEEE802_11_CSMACA_ProcessBlockAck()
449{
450 UINT success=0,fail=0;
451 int i=0;
452 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
453 NetSim_PACKET* p=mac->currentProcessingPacket;
454 PIEEE802_11_BLOCKACK back = ((ptrIEEE802_11_HDR)PACKET_MACPROTOCOLDATA(pstruEventDetails->pPacket))->hdr;
455 NetSim_PACKET* prev=NULL;
456 int flag = 1;
457 while (p)
458 {
459 if (flag == 0 && i == 1)
460 {
461 i = 0;
462 }
463 if(BIT_IS_SET_64(back->BitMap,i++))
464 {
465 NetSim_PACKET* t=p;
466 if (t->ReceiveAckNotification)
467 t->ReceiveAckNotification(pstruEventDetails->pPacket);
468 success++;
469 if(prev)
470 {
471 prev->pstruNextPacket=t->pstruNextPacket;
472 p=p->pstruNextPacket;
473 fn_NetSim_Packet_FreePacket(t);
474 continue;
475 }
476 else
477 {
478 p=p->pstruNextPacket;
479 mac->currentProcessingPacket=p;
480 fn_NetSim_Packet_FreePacket(t);
481 continue;
482 }
483 }
484 else
485 {
486 fail++;
487 flag = 0;
488 prev=p;
489 p=p->pstruNextPacket;
490 continue;
491 }
492 }
493 if(mac->rate_adaptationAlgo== RATEADAPTATION_GENERIC)
494 {
495 //Call rate adaptation
496 if(flag) //All packet received.
497 packet_recv_notify(pstruEventDetails->nDeviceId,
498 pstruEventDetails->nInterfaceId,
499 pstruEventDetails->pPacket->nTransmitterId);
500 else //Some packet dropped
501 packet_drop_notify(pstruEventDetails->nDeviceId,
502 pstruEventDetails->nInterfaceId,
503 pstruEventDetails->pPacket->nTransmitterId);
504 }
505 else if(mac->rate_adaptationAlgo== RATEADAPTATION_MINSTREL)
506 {
507 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(pstruEventDetails->nDeviceId, pstruEventDetails->nInterfaceId);
508 if (phy->PhyProtocol == IEEE_802_11ax)
509 {
510 He_DoReportAmpduStatus(pstruEventDetails->nDeviceId,
511 pstruEventDetails->nInterfaceId,
512 pstruEventDetails->pPacket->nTransmitterId,
513 success, fail);
514 }
515 else {
516 DoReportAmpduStatus(pstruEventDetails->nDeviceId,
517 pstruEventDetails->nInterfaceId,
518 pstruEventDetails->pPacket->nTransmitterId,
519 success,fail);
520 }
521 }
522
523 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
524 IEEE802_11_Change_Mac_State(mac, IEEE802_11_MACSTATE_MAC_IDLE);
525
526 if (ieee802_11_edcaf_is_txop_timer_set(mac, ldEventTime))
527 {
528 // Get packet from buffer
529 UINT n;
530 NetSim_PACKET* packet = get_from_queue(pstruEventDetails->nDeviceId,
531 pstruEventDetails->nInterfaceId,
532 mac->nNumberOfAggregatedPackets,
533 &n);
534 if (!packet)
535 ieee802_11_edcaf_unset_txop_time(mac);
536 else
537 {
538 mac->currentProcessingPacket = packet;
539 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(mac->deviceId, mac->parentInterfaceId);
540
541 //Wait for SIFS and then transmit packet
542 pstruEventDetails->dEventTime += getSIFSTime(phy);
543 fn_NetSim_IEEE802_11_SendToPhy();
544 }
545 }
546 else
547 {
548 ieee802_11_edcaf_unset_txop_time(mac);
549 fn_NetSim_IEE802_11_MacReInit(pstruEventDetails->nDeviceId,
550 pstruEventDetails->nInterfaceId);
551 }
552
553 fnDeleteEvent(mac->EVENTID.ackTimeOut);
554}
555
556void fn_NetSim_IEEE802_11_CSMACA_AddAckTimeOut(NetSim_PACKET* packet,NETSIM_ID devId,NETSIM_ID devIf)
557{
558 ptrIEEE802_11_HDR hdr = packet->pstruMacData->Packet_MACProtocol;
559
560 NetSim_EVENTDETAILS pevent;
561 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(devId,devIf);
562 PIEEE802_11_MAC_VAR mac = IEEE802_11_MAC(devId, hdr->sendInterfaceId);
563 double acktime;
564
565 acktime = ceil(packet->pstruPhyData->dStartTime
566 + phy->plmeCharacteristics.aSIFSTime
567 + get_preamble_time(phy)
568 + ((getAckSize(phy) * 8)/phy->dControlFrameDataRate));
569
570 pevent.dEventTime=acktime+2;
571 pevent.dPacketSize=0;
572 pevent.nDeviceId=devId;
573 pevent.nDeviceType=DEVICE_TYPE(devId);
574 pevent.nEventType=TIMER_EVENT;
575 pevent.nInterfaceId=hdr->sendInterfaceId;
576 pevent.nPacketId=packet->nPacketId;
577 pevent.nProtocolId=MAC_PROTOCOL_IEEE802_11;
578 if(packet->pstruAppData)
579 {
580 pevent.nSegmentId=packet->pstruAppData->nSegmentId;
581 pevent.nApplicationId=packet->pstruAppData->nApplicationId;
582 }
583 else
584 {
585 pevent.nSegmentId=0;
586 pevent.nApplicationId=0;
587 }
588 pevent.nSubEventType=ACK_TIMEOUT;
589 pevent.pPacket=NULL;
590 pevent.szOtherDetails=NULL;
591 mac->EVENTID.ackTimeOut = fnpAddEvent(&pevent);
592}
593
594void fn_NetSim_IEEE802_11_CSMA_AckTimeOut()
595{
596 PIEEE802_11_MAC_VAR mac = IEEE802_11_CURR_MAC;
597 bool isRetry=false;
598
599 if(mac->currMacState == IEEE802_11_MACSTATE_Wait_ACK ||
600 mac->currMacState == IEEE802_11_MACSTATE_TXing_MPDU)
601 {
602 UINT frameLength = (UINT)mac->currentProcessingPacket->pstruMacData->dPayload;
603 //Call rate adaptation
604 if(mac->rate_adaptationAlgo== RATEADAPTATION_GENERIC)
605 packet_drop_notify(pstruEventDetails->nDeviceId,
606 pstruEventDetails->nInterfaceId,
607 mac->currentProcessingPacket->nReceiverId);
608
609 IEEE802_11_Change_Mac_State(mac,IEEE802_11_MACSTATE_MAC_IDLE);
610 ieee802_11_edcaf_unset_txop_time(mac);
611
612 if (mac->rate_adaptationAlgo == RATEADAPTATION_MINSTREL)
613 isRetry = Minstrel_DoNeedDataSend(pstruEventDetails->nDeviceId,
614 pstruEventDetails->nInterfaceId,
615 mac->currentProcessingPacket->nReceiverId);
616 else
617 isRetry = fn_NetSim_IEEE802_11_CSMACA_CheckRetryLimit(mac, frameLength);
618
619 if(isRetry)
620 {
621 mac->nRetryCount++;
622 if(mac->rate_adaptationAlgo== RATEADAPTATION_MINSTREL)
623 Minstrel_ReportDataFailed(pstruEventDetails->nDeviceId,
624 pstruEventDetails->nInterfaceId,
625 mac->currentProcessingPacket->nReceiverId);
626 fn_NetSim_IEEE802_11_CSMACA_IncreaseCW(mac);
627 fn_NetSim_IEEE802_11_CSMACA_Init();
628 }
629 else
630 {
631 if(mac->rate_adaptationAlgo == RATEADAPTATION_MINSTREL)
632 Minstrel_ReportFinalDataFailed(pstruEventDetails->nDeviceId,
633 pstruEventDetails->nInterfaceId,
634 mac->currentProcessingPacket->nReceiverId);
635
636 if(mac->currentProcessingPacket)
637 {
638 NetSim_PACKET* pstruPacket = mac->currentProcessingPacket;
639
640 if(pstruPacket->DropNotification)
641 pstruPacket->DropNotification(pstruPacket);
642 fn_NetSim_Packet_FreePacket(mac->currentProcessingPacket);
643 mac->currentProcessingPacket=NULL;
644 }
645 mac->nRetryCount = 0;
646 fn_NetSim_IEEE802_11_CSMACA_Init();
647 }
648 }
649}
650
651/**
652 This function invoke the retry limit checking. If active frame retry count is less than
653 active frame retry limit, then set move flag as one to allow the frame retransmission.
654 Otherwise, set move flag as zero to drop the active frame
655 */
656bool fn_NetSim_IEEE802_11_CSMACA_CheckRetryLimit(PIEEE802_11_MAC_VAR mac, UINT frameLength)
657{
658 if (frameLength <= mac->dot11RTSThreshold)
659 {
660 if (mac->nRetryCount < mac->dot11ShortRetryLimit - 1)
661 return true;
662 else
663 return false;
664 }
665 else
666 {
667 if (mac->nRetryCount < mac->dot11LongRetryLimit - 1)
668 return true;
669 else
670 return false;
671 }
672}
673
674/**
675~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
676This function is used to expand the CW.
677else if CWcurrent >= CWmax, then CWcurrent is set to CWmax the Maximum CW.
678else CWcurrent = (nCWcurrent * 2) + 1.
679~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
680*/
681void fn_NetSim_IEEE802_11_CSMACA_IncreaseCW(PIEEE802_11_MAC_VAR mac)
682{
683 mac->nCWcurrent = min((mac->nCWcurrent * 2) + 1, mac->currEdcaTable->CWmax);
684}
685
686/**
687This function is called to create and send an Ack after receiving the DATA
688from the destination or from the AP
689*/
690int fn_NetSim_IEEE802_11_CSMACA_SendBlockACK()
691{
692 NetSim_PACKET* packet;
693 NetSim_PACKET* p=pstruEventDetails->pPacket;
694
695 if(IEEE802_11_CURR_MAC->blockAckPacket)
696 packet = IEEE802_11_CURR_MAC->blockAckPacket;
697 else
698 {
699 packet=fn_NetSim_IEEE802_11_CreateBlockAckPacket(pstruEventDetails->nDeviceId,
700 pstruEventDetails->nInterfaceId,
701 pstruEventDetails->pPacket,
702 pstruEventDetails->dEventTime);
703 IEEE802_11_CURR_MAC->blockAckPacket=packet;
704 }
705
706 set_blockack_bitmap(packet,pstruEventDetails->pPacket);
707
708 if(!is_more_fragment_coming(pstruEventDetails->pPacket))
709 {
710 PIEEE802_11_BLOCKACK back = ((ptrIEEE802_11_HDR)PACKET_MACPROTOCOLDATA(packet))->hdr;
711 if (BIT_IS_SET_64(back->BitMap, 0))
712 {
713 // Add SEND ACK sub-event
714 pstruEventDetails->dEventTime += IEEE802_11_CURR_PHY->SIFS;
715 pstruEventDetails->dPacketSize = packet->pstruMacData->dPacketSize;
716 pstruEventDetails->nSubEventType = 0;
717 pstruEventDetails->nEventType = PHYSICAL_OUT_EVENT;
718 pstruEventDetails->pPacket = packet;
719 fnpAddEvent(pstruEventDetails);
720 }
721 // Change the state
722 IEEE802_11_Change_Mac_State(IEEE802_11_CURR_MAC,IEEE802_11_MACSTATE_TXing_ACK);
723 IEEE802_11_CURR_MAC->blockAckPacket=NULL;
724 }
725
726 //Free the data packet
727 fn_NetSim_Packet_FreePacket(p);
728 return 0;
729}
730
731void fn_NetSim_IEEE802_11_CSMA_UpdateNAV(NETSIM_ID d, NETSIM_ID in, NetSim_PACKET* packet)
732{
733 ptrIEEE802_11_HDR mhdr = packet->pstruMacData->Packet_MACProtocol;
734 if (d == packet->nReceiverId && mhdr->recvInterfaceId == in) { return; }
735
736 bool isUpdated = false;
737 PIEEE802_11_MAC_VAR mac = IEEE802_11_MAC(d, in);
738 UINT type;
739 void* hdr = ieee802_11_get_hdr(packet, &type);
740 switch (type)
741 {
742 case WLAN_RTS:
743 if (d == packet->nTransmitterId && mhdr->sendInterfaceId == in) { return; }
744 mac->dNAV = max(mac->dNAV, (ldEventTime + ((PIEEE802_11_RTS)hdr)->Duration));
745 isUpdated = true;
746 break;
747 case WLAN_CTS:
748 mac->dNAV = max(mac->dNAV, (ldEventTime + ((PIEEE802_11_CTS)hdr)->Duration));
749 isUpdated = true;
750 break;
751 }
752
753 if (isUpdated)
754 {
755 NetSim_EVENTDETAILS pevent;
756 memset(&pevent, 0, sizeof pevent);
757 pevent.dEventTime = mac->dNAV+1.05;
758 pevent.dPacketSize = 0;
759 pevent.nDeviceId = d;
760 pevent.nDeviceType = DEVICE_TYPE(d);
761 pevent.nEventType = MAC_OUT_EVENT;
762 pevent.nInterfaceId = in;
763 pevent.nProtocolId = MAC_PROTOCOL_IEEE802_11;
764 pevent.nSubEventType = 0;
765 fnpAddEvent(&pevent);
766 }
767}