19 */ |
19 */ |
20 |
20 |
21 #include "ns3/assert.h" |
21 #include "ns3/assert.h" |
22 #include "ns3/packet.h" |
22 #include "ns3/packet.h" |
23 #include "ns3/log.h" |
23 #include "ns3/log.h" |
|
24 #include "ns3/simulator.h" |
|
25 #include "ns3/net-device.h" |
|
26 #include "ns3/node.h" |
24 |
27 |
25 #include "dca-txop.h" |
28 #include "dca-txop.h" |
26 #include "dcf.h" |
29 #include "dcf-manager.h" |
27 #include "mac-parameters.h" |
30 #include "mac-parameters.h" |
28 #include "mac-low.h" |
31 #include "mac-low.h" |
29 #include "wifi-mac-queue.h" |
32 #include "wifi-mac-queue.h" |
30 #include "mac-tx-middle.h" |
33 #include "mac-tx-middle.h" |
31 #include "wifi-phy.h" |
34 #include "wifi-phy.h" |
|
35 #include "random-stream.h" |
32 |
36 |
33 NS_LOG_COMPONENT_DEFINE ("DcaTxop"); |
37 NS_LOG_COMPONENT_DEFINE ("DcaTxop"); |
34 |
38 |
|
39 #define MY_DEBUG(x) \ |
|
40 NS_LOG_DEBUG (Simulator::Now () << " " << m_low->GetDevice ()->GetNode ()->GetId () << ":" << \ |
|
41 m_low->GetDevice ()->GetIfIndex () << " " << x) |
|
42 |
35 |
43 |
36 namespace ns3 { |
44 namespace ns3 { |
37 |
45 |
38 class DcaTxop::NavListener : public ns3::MacLowNavListener { |
46 class DcaTxop::Dcf : public DcfState |
|
47 { |
39 public: |
48 public: |
40 NavListener (ns3::Dcf *dcf) |
49 Dcf (DcaTxop *txop) |
41 : m_dcf (dcf) {} |
50 : m_txop (txop) |
42 virtual ~NavListener () {} |
51 {} |
43 virtual void NavStart (Time now, Time duration) { |
|
44 m_dcf->NotifyNavStart (now, duration); |
|
45 } |
|
46 virtual void NavContinue (Time now, Time duration) { |
|
47 m_dcf->NotifyNavContinue (now, duration); |
|
48 } |
|
49 virtual void NavReset (Time now, Time duration) { |
|
50 m_dcf->NotifyNavReset (now, duration); |
|
51 } |
|
52 private: |
52 private: |
53 ns3::Dcf *m_dcf; |
53 virtual void DoNotifyAccessGranted (void) { |
54 }; |
54 m_txop->NotifyAccessGranted (); |
55 class DcaTxop::PhyListener : public ns3::WifiPhyListener { |
55 } |
56 public: |
56 virtual void DoNotifyInternalCollision (void) { |
57 PhyListener (ns3::Dcf *dcf) |
57 m_txop->NotifyInternalCollision (); |
58 : m_dcf (dcf) {} |
58 } |
59 virtual ~PhyListener () {} |
59 virtual void DoNotifyCollision (void) { |
60 virtual void NotifyRxStart (Time duration) { |
60 m_txop->NotifyCollision (); |
61 m_dcf->NotifyRxStartNow (duration); |
61 } |
62 } |
62 |
63 virtual void NotifyRxEndOk (void) { |
|
64 m_dcf->NotifyRxEndOkNow (); |
|
65 } |
|
66 virtual void NotifyRxEndError (void) { |
|
67 m_dcf->NotifyRxEndErrorNow (); |
|
68 } |
|
69 virtual void NotifyTxStart (Time duration) { |
|
70 m_dcf->NotifyTxStartNow (duration); |
|
71 } |
|
72 virtual void NotifyCcaBusyStart (Time duration) { |
|
73 m_dcf->NotifyCcaBusyStartNow (duration); |
|
74 } |
|
75 private: |
|
76 ns3::Dcf *m_dcf; |
|
77 }; |
|
78 |
|
79 |
|
80 class DcaTxop::AccessListener : public DcfAccessListener { |
|
81 public: |
|
82 AccessListener (DcaTxop *txop) |
|
83 : DcfAccessListener (), |
|
84 m_txop (txop) {} |
|
85 |
|
86 virtual ~AccessListener () {} |
|
87 |
|
88 virtual void AccessGrantedNow (void) |
|
89 { |
|
90 m_txop->AccessGrantedNow (); |
|
91 } |
|
92 virtual bool AccessNeeded (void) |
|
93 { |
|
94 return m_txop->AccessNeeded (); |
|
95 } |
|
96 virtual bool AccessingAndWillNotify (void) |
|
97 { |
|
98 return m_txop->AccessingAndWillNotify (); |
|
99 } |
|
100 |
|
101 private: |
|
102 DcaTxop *m_txop; |
63 DcaTxop *m_txop; |
103 }; |
64 }; |
104 |
65 |
105 class DcaTxop::TransmissionListener : public MacLowTransmissionListener { |
66 class DcaTxop::TransmissionListener : public MacLowTransmissionListener { |
106 public: |
67 public: |
131 |
92 |
132 private: |
93 private: |
133 DcaTxop *m_txop; |
94 DcaTxop *m_txop; |
134 }; |
95 }; |
135 |
96 |
136 DcaTxop::DcaTxop (uint32_t minCw, uint32_t maxCw) |
97 DcaTxop::DcaTxop (uint32_t minCw, uint32_t maxCw, uint32_t aifsn, DcfManager *manager) |
137 : m_accessListener (0), |
98 : m_manager (manager), |
138 m_hasCurrent (false), |
99 m_hasCurrent (false), |
139 m_ssrc (0), |
100 m_ssrc (0), |
140 m_slrc (0) |
101 m_slrc (0) |
|
102 |
141 { |
103 { |
142 m_transmissionListener = new DcaTxop::TransmissionListener (this); |
104 m_transmissionListener = new DcaTxop::TransmissionListener (this); |
143 m_dcf = new Dcf (minCw, maxCw); |
105 m_dcf = new DcaTxop::Dcf (this); |
144 m_accessListener = new DcaTxop::AccessListener (this); |
106 m_dcf->SetCwBounds (minCw, maxCw); |
145 m_dcf->RegisterAccessListener (m_accessListener); |
107 m_dcf->SetAifsn (aifsn); |
|
108 m_manager->Add (m_dcf); |
146 m_queue = new WifiMacQueue (); |
109 m_queue = new WifiMacQueue (); |
|
110 m_rng = new RealRandomStream (); |
147 } |
111 } |
148 |
112 |
149 DcaTxop::~DcaTxop () |
113 DcaTxop::~DcaTxop () |
150 { |
114 { |
151 delete m_accessListener; |
|
152 delete m_transmissionListener; |
115 delete m_transmissionListener; |
153 delete m_navListener; |
|
154 delete m_phyListener; |
|
155 delete m_queue; |
116 delete m_queue; |
156 delete m_dcf; |
117 delete m_dcf; |
157 m_accessListener = 0; |
|
158 m_transmissionListener = 0; |
118 m_transmissionListener = 0; |
159 m_navListener = 0; |
|
160 m_phyListener = 0; |
|
161 m_queue = 0; |
119 m_queue = 0; |
162 m_dcf = 0; |
120 m_dcf = 0; |
163 } |
121 } |
164 |
122 |
165 void |
123 void |
166 DcaTxop::SetLow (MacLow *low) |
124 DcaTxop::SetLow (MacLow *low) |
167 { |
125 { |
168 m_low = low; |
126 m_low = low; |
169 m_navListener = new DcaTxop::NavListener (m_dcf); |
127 } |
170 m_low->RegisterNavListener (m_navListener); |
128 void |
171 } |
129 DcaTxop::SetParameters (MacParameters *parameters) |
|
130 { |
|
131 m_parameters = parameters; |
|
132 } |
|
133 void |
|
134 DcaTxop::SetTxMiddle (MacTxMiddle *txMiddle) |
|
135 { |
|
136 m_txMiddle = txMiddle; |
|
137 } |
|
138 void |
|
139 DcaTxop::SetTxOkCallback (TxOk callback) |
|
140 { |
|
141 m_txOkCallback = callback; |
|
142 } |
|
143 void |
|
144 DcaTxop::SetTxFailedCallback (TxFailed callback) |
|
145 { |
|
146 m_txFailedCallback = callback; |
|
147 } |
|
148 |
|
149 void |
|
150 DcaTxop::SetMaxQueueSize (uint32_t size) |
|
151 { |
|
152 m_queue->SetMaxSize (size); |
|
153 } |
|
154 void |
|
155 DcaTxop::SetMaxQueueDelay (Time delay) |
|
156 { |
|
157 m_queue->SetMaxDelay (delay); |
|
158 } |
|
159 |
|
160 void |
|
161 DcaTxop::Queue (Packet packet, WifiMacHeader const &hdr) |
|
162 { |
|
163 m_queue->Enqueue (packet, hdr); |
|
164 StartAccessIfNeeded (); |
|
165 } |
|
166 |
172 void |
167 void |
173 DcaTxop::SetPhy (Ptr<WifiPhy> phy) |
168 DcaTxop::RestartAccessIfNeeded (void) |
174 { |
169 { |
175 m_phyListener = new DcaTxop::PhyListener (m_dcf); |
170 if ((m_hasCurrent || |
176 phy->RegisterListener (m_phyListener); |
171 !m_queue->IsEmpty ()) && |
177 } |
172 !m_dcf->IsAccessRequested ()) |
178 void |
173 { |
179 DcaTxop::SetParameters (MacParameters *parameters) |
174 m_manager->RequestAccess (m_dcf); |
180 { |
175 } |
181 m_parameters = parameters; |
176 } |
182 m_dcf->SetParameters (parameters); |
177 |
183 } |
178 void |
184 void |
179 DcaTxop::StartAccessIfNeeded (void) |
185 DcaTxop::SetTxMiddle (MacTxMiddle *txMiddle) |
180 { |
186 { |
181 if (!m_hasCurrent && |
187 m_txMiddle = txMiddle; |
182 !m_queue->IsEmpty () && |
188 } |
183 !m_dcf->IsAccessRequested ()) |
189 void |
184 { |
190 DcaTxop::SetTxOkCallback (TxOk callback) |
185 m_manager->RequestAccess (m_dcf); |
191 { |
186 } |
192 m_txOkCallback = callback; |
|
193 } |
|
194 void |
|
195 DcaTxop::SetTxFailedCallback (TxFailed callback) |
|
196 { |
|
197 m_txFailedCallback = callback; |
|
198 } |
|
199 |
|
200 void |
|
201 DcaTxop::SetDifs (Time difs) |
|
202 { |
|
203 m_dcf->SetDifs (difs); |
|
204 } |
|
205 void |
|
206 DcaTxop::SetEifs (Time eifs) |
|
207 { |
|
208 m_dcf->SetEifs (eifs); |
|
209 } |
|
210 void |
|
211 DcaTxop::SetCwBounds (uint32_t min, uint32_t max) |
|
212 { |
|
213 m_dcf->SetCwBounds (min, max); |
|
214 } |
|
215 void |
|
216 DcaTxop::SetMaxQueueSize (uint32_t size) |
|
217 { |
|
218 m_queue->SetMaxSize (size); |
|
219 } |
|
220 void |
|
221 DcaTxop::SetMaxQueueDelay (Time delay) |
|
222 { |
|
223 m_queue->SetMaxDelay (delay); |
|
224 } |
|
225 |
|
226 void |
|
227 DcaTxop::Queue (Packet packet, WifiMacHeader const &hdr) |
|
228 { |
|
229 m_queue->Enqueue (packet, hdr); |
|
230 m_dcf->RequestAccess (); |
|
231 } |
187 } |
232 |
188 |
233 |
189 |
234 MacLow * |
190 MacLow * |
235 DcaTxop::Low (void) |
191 DcaTxop::Low (void) |
398 m_currentHdr.SetFragmentNumber (0); |
330 m_currentHdr.SetFragmentNumber (0); |
399 m_currentHdr.SetNoMoreFragments (); |
331 m_currentHdr.SetNoMoreFragments (); |
400 m_ssrc = 0; |
332 m_ssrc = 0; |
401 m_slrc = 0; |
333 m_slrc = 0; |
402 m_fragmentNumber = 0; |
334 m_fragmentNumber = 0; |
403 NS_LOG_DEBUG ("dequeued size="<<m_currentPacket.GetSize ()<< |
335 MY_DEBUG ("dequeued size="<<m_currentPacket.GetSize ()<< |
404 ", to="<<m_currentHdr.GetAddr1 ()<< |
336 ", to="<<m_currentHdr.GetAddr1 ()<< |
405 ", seq="<<m_currentHdr.GetSequenceControl ()); |
337 ", seq="<<m_currentHdr.GetSequenceControl ()); |
406 } |
338 } |
407 MacLowTransmissionParameters params; |
339 MacLowTransmissionParameters params; |
408 params.DisableOverrideDurationId (); |
340 params.DisableOverrideDurationId (); |
429 params.DisableRts (); |
361 params.DisableRts (); |
430 WifiMacHeader hdr; |
362 WifiMacHeader hdr; |
431 Packet fragment = GetFragmentPacket (&hdr); |
363 Packet fragment = GetFragmentPacket (&hdr); |
432 if (IsLastFragment ()) |
364 if (IsLastFragment ()) |
433 { |
365 { |
434 NS_LOG_DEBUG ("fragmenting last fragment size="<<fragment.GetSize ()); |
366 MY_DEBUG ("fragmenting last fragment size="<<fragment.GetSize ()); |
435 params.DisableNextData (); |
367 params.DisableNextData (); |
436 } |
368 } |
437 else |
369 else |
438 { |
370 { |
439 NS_LOG_DEBUG ("fragmenting size="<<fragment.GetSize ()); |
371 MY_DEBUG ("fragmenting size="<<fragment.GetSize ()); |
440 params.EnableNextData (GetNextFragmentSize ()); |
372 params.EnableNextData (GetNextFragmentSize ()); |
441 } |
373 } |
442 Low ()->StartTransmission (fragment, &hdr, params, |
374 Low ()->StartTransmission (fragment, &hdr, params, |
443 m_transmissionListener); |
375 m_transmissionListener); |
444 } |
376 } |
445 else |
377 else |
446 { |
378 { |
447 if (NeedRts ()) |
379 if (NeedRts ()) |
448 { |
380 { |
449 params.EnableRts (); |
381 params.EnableRts (); |
450 NS_LOG_DEBUG ("tx unicast rts"); |
382 MY_DEBUG ("tx unicast rts"); |
451 } |
383 } |
452 else |
384 else |
453 { |
385 { |
454 params.DisableRts (); |
386 params.DisableRts (); |
455 NS_LOG_DEBUG ("tx unicast"); |
387 MY_DEBUG ("tx unicast"); |
456 } |
388 } |
457 params.DisableNextData (); |
389 params.DisableNextData (); |
458 // We need to make a copy in case we need to |
390 // We need to make a copy in case we need to |
459 // retransmit the packet: the MacLow modifies the input |
391 // retransmit the packet: the MacLow modifies the input |
460 // Packet so, we would retransmit a modified packet |
392 // Packet so, we would retransmit a modified packet |
466 params, m_transmissionListener); |
398 params, m_transmissionListener); |
467 } |
399 } |
468 } |
400 } |
469 } |
401 } |
470 |
402 |
|
403 void |
|
404 DcaTxop::NotifyInternalCollision (void) |
|
405 { |
|
406 NotifyCollision (); |
|
407 } |
|
408 void |
|
409 DcaTxop::NotifyCollision (void) |
|
410 { |
|
411 MY_DEBUG ("collision"); |
|
412 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
|
413 RestartAccessIfNeeded (); |
|
414 } |
471 |
415 |
472 void |
416 void |
473 DcaTxop::GotCts (double snr, WifiMode txMode) |
417 DcaTxop::GotCts (double snr, WifiMode txMode) |
474 { |
418 { |
475 NS_LOG_DEBUG ("got cts"); |
419 MY_DEBUG ("got cts"); |
476 m_ssrc = 0; |
420 m_ssrc = 0; |
477 } |
421 } |
478 void |
422 void |
479 DcaTxop::MissedCts (void) |
423 DcaTxop::MissedCts (void) |
480 { |
424 { |
481 NS_LOG_DEBUG ("missed cts"); |
425 MY_DEBUG ("missed cts"); |
482 m_ssrc++; |
426 m_ssrc++; |
483 m_ctstimeoutTrace (m_ssrc); |
427 m_ctstimeoutTrace (m_ssrc); |
484 if (m_ssrc > Parameters ()->GetMaxSsrc ()) |
428 if (m_ssrc > Parameters ()->GetMaxSsrc ()) |
485 { |
429 { |
486 // to reset the dcf. |
430 // to reset the dcf. |
|
431 m_hasCurrent = false; |
487 m_dcf->ResetCw (); |
432 m_dcf->ResetCw (); |
488 m_dcf->StartBackoff (); |
|
489 m_hasCurrent = false; |
|
490 } |
433 } |
491 else |
434 else |
492 { |
435 { |
493 m_dcf->UpdateFailedCw (); |
436 m_dcf->UpdateFailedCw (); |
494 m_dcf->StartBackoff (); |
437 } |
495 } |
438 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
|
439 RestartAccessIfNeeded (); |
496 } |
440 } |
497 void |
441 void |
498 DcaTxop::GotAck (double snr, WifiMode txMode) |
442 DcaTxop::GotAck (double snr, WifiMode txMode) |
499 { |
443 { |
500 m_slrc = 0; |
444 m_slrc = 0; |
501 if (!NeedFragmentation () || |
445 if (!NeedFragmentation () || |
502 IsLastFragment ()) |
446 IsLastFragment ()) |
503 { |
447 { |
504 NS_LOG_DEBUG ("got ack. tx done."); |
448 MY_DEBUG ("got ack. tx done."); |
505 if (!m_txOkCallback.IsNull ()) |
449 if (!m_txOkCallback.IsNull ()) |
506 { |
450 { |
507 m_txOkCallback (m_currentHdr); |
451 m_txOkCallback (m_currentHdr); |
508 } |
452 } |
509 |
453 |
510 /* we are not fragmenting or we are done fragmenting |
454 /* we are not fragmenting or we are done fragmenting |
511 * so we can get rid of that packet now. |
455 * so we can get rid of that packet now. |
512 */ |
456 */ |
513 m_hasCurrent = false; |
457 m_hasCurrent = false; |
514 m_dcf->ResetCw (); |
458 m_dcf->ResetCw (); |
515 m_dcf->StartBackoff (); |
459 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
516 } |
460 RestartAccessIfNeeded (); |
517 else |
461 } |
518 { |
462 else |
519 NS_LOG_DEBUG ("got ack. tx not done, size="<<m_currentPacket.GetSize ()); |
463 { |
|
464 MY_DEBUG ("got ack. tx not done, size="<<m_currentPacket.GetSize ()); |
520 } |
465 } |
521 } |
466 } |
522 void |
467 void |
523 DcaTxop::MissedAck (void) |
468 DcaTxop::MissedAck (void) |
524 { |
469 { |
525 NS_LOG_DEBUG ("missed ack"); |
470 MY_DEBUG ("missed ack"); |
526 m_slrc++; |
471 m_slrc++; |
527 m_acktimeoutTrace (m_slrc); |
472 m_acktimeoutTrace (m_slrc); |
528 if (m_slrc > Parameters ()->GetMaxSlrc ()) |
473 if (m_slrc > Parameters ()->GetMaxSlrc ()) |
529 { |
474 { |
530 // to reset the dcf. |
475 // to reset the dcf. |
|
476 m_hasCurrent = false; |
531 m_dcf->ResetCw (); |
477 m_dcf->ResetCw (); |
532 m_dcf->StartBackoff (); |
|
533 m_hasCurrent = false; |
|
534 } |
478 } |
535 else |
479 else |
536 { |
480 { |
537 m_currentHdr.SetRetry (); |
481 m_currentHdr.SetRetry (); |
538 if (!m_txFailedCallback.IsNull ()) |
482 if (!m_txFailedCallback.IsNull ()) |
539 { |
483 { |
540 m_txFailedCallback (m_currentHdr); |
484 m_txFailedCallback (m_currentHdr); |
541 } |
485 } |
542 m_dcf->UpdateFailedCw (); |
486 m_dcf->UpdateFailedCw (); |
543 m_dcf->StartBackoff (); |
487 } |
544 } |
488 m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); |
545 |
489 RestartAccessIfNeeded (); |
546 } |
490 } |
547 void |
491 void |
548 DcaTxop::StartNext (void) |
492 DcaTxop::StartNext (void) |
549 { |
493 { |
550 NS_LOG_DEBUG ("start next packet fragment"); |
494 MY_DEBUG ("start next packet fragment"); |
551 /* this callback is used only for fragments. */ |
495 /* this callback is used only for fragments. */ |
552 NextFragment (); |
496 NextFragment (); |
553 WifiMacHeader hdr; |
497 WifiMacHeader hdr; |
554 Packet fragment = GetFragmentPacket (&hdr); |
498 Packet fragment = GetFragmentPacket (&hdr); |
555 MacLowTransmissionParameters params; |
499 MacLowTransmissionParameters params; |
580 * If the normal queue tries to send a unicast data frame, but |
524 * If the normal queue tries to send a unicast data frame, but |
581 * if the tx fails (ack timeout), it starts a backoff. If the beacon |
525 * if the tx fails (ack timeout), it starts a backoff. If the beacon |
582 * queue gets a tx oportunity during this backoff, it will trigger |
526 * queue gets a tx oportunity during this backoff, it will trigger |
583 * a call to this Cancel function. |
527 * a call to this Cancel function. |
584 * |
528 * |
585 * Since we are already doing a backoff, so we will get access to |
529 * Since we are already doing a backoff, we will get access to |
586 * the medium when we can, we have nothing to do here. We just |
530 * the medium when we can, we have nothing to do here. We just |
587 * ignore the cancel event and wait until we are given again a |
531 * ignore the cancel event and wait until we are given again a |
588 * tx oportunity. |
532 * tx oportunity. |
589 * |
533 * |
590 * Note that this is really non-trivial because each of these |
534 * Note that this is really non-trivial because each of these |