A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
dca-txop.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/assert.h"
22 #include "ns3/packet.h"
23 #include "ns3/log.h"
24 #include "ns3/simulator.h"
25 #include "ns3/node.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/pointer.h"
28 
29 #include "dca-txop.h"
30 #include "dcf-manager.h"
31 #include "mac-low.h"
32 #include "wifi-mac-queue.h"
33 #include "mac-tx-middle.h"
34 #include "wifi-mac-trailer.h"
35 #include "wifi-mac.h"
36 #include "random-stream.h"
37 #include "yans-wifi-phy.h"
38 
39 NS_LOG_COMPONENT_DEFINE ("DcaTxop");
40 
41 #undef NS_LOG_APPEND_CONTEXT
42 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
43 
44 namespace ns3 {
45 
46 DcaTxop::ActiveChannels::ActiveChannels(uint16_t channel, Time lastActive)
47  : channel (channel),
48  lastActive (lastActive)
49 {
50 }
51 
52 class DcaTxop::Dcf : public DcfState
53 {
54 public:
55  Dcf (DcaTxop * txop)
56  : m_txop (txop)
57  {
58  }
59 private:
60  virtual void DoNotifyAccessGranted (void)
61  {
62  m_txop->NotifyAccessGranted ();
63  }
64  virtual void DoNotifyInternalCollision (void)
65  {
66  m_txop->NotifyInternalCollision ();
67  }
68  virtual void DoNotifyCollision (void)
69  {
70  m_txop->NotifyCollision ();
71  }
72  virtual void DoNotifyChannelSwitching (Time duration, uint16_t toChannel)
73  {
74  m_txop->NotifyChannelSwitching (duration, toChannel);
75  }
76  virtual void DoNotifyChannelSensing (void)
77  {
78  m_txop->NotifyChannelSensing ();
79  }
80  DcaTxop *m_txop;
81 };
82 
84 {
85 public:
88  m_txop (txop) {
89  }
90 
91  virtual ~TransmissionListener () {}
92 
93  virtual void GotCts (double snr, WifiMode txMode)
94  {
95  m_txop->GotCts (snr, txMode);
96  }
97  virtual void MissedCts (void)
98  {
99  m_txop->MissedCts ();
100  }
101  virtual void GotAck (double snr, WifiMode txMode)
102  {
103  m_txop->GotAck (snr, txMode);
104  }
105  virtual void MissedAck (void)
106  {
107  m_txop->MissedAck ();
108  }
109  virtual void StartNext (void)
110  {
111  m_txop->StartNext ();
112  }
113  virtual void Cancel (void)
114  {
115  m_txop->Cancel ();
116  }
117  virtual void EndTxNoAck (void)
118  {
119  m_txop->EndTxNoAck ();
120  }
121 
122 private:
123  DcaTxop *m_txop;
124 };
125 
126 NS_OBJECT_ENSURE_REGISTERED (DcaTxop);
127 
128 TypeId
129 DcaTxop::GetTypeId (void)
130 {
131  static TypeId tid = TypeId ("ns3::DcaTxop")
132  .SetParent (ns3::Dcf::GetTypeId ())
134  .AddAttribute ("Queue", "The WifiMacQueue object",
135  PointerValue (),
136  MakePointerAccessor (&DcaTxop::GetQueue),
137  MakePointerChecker<WifiMacQueue> ())
138  .AddAttribute ("ChannelActiveTimeout",
139  "After how long should a channel be considered inactive if not used",
140  TimeValue (Seconds (2)),
141  MakeTimeAccessor (&DcaTxop::m_activeChannelTimeout),
142  MakeTimeChecker ())
143  .AddAttribute ("QueueUtilizationInterval",
144  "How long should we transmit on a queue for a specific channel",
145  TimeValue (MilliSeconds (150)),
146  MakeTimeAccessor (&DcaTxop::m_queueUtilizationTime),
147  MakeTimeChecker ())
148  ;
149  return tid;
150 }
151 
152 DcaTxop::DcaTxop ()
153  : m_manager (0),
154  m_currentPacket (0),
155  m_currentChannel (1),
156  m_switchQueueTimer ()
157 {
158  NS_LOG_FUNCTION (this);
159  m_transmissionListener = new DcaTxop::TransmissionListener (this);
160  m_dcf = new DcaTxop::Dcf (this);
161  m_queue = CreateObject<WifiMacQueue> ();
162  m_rng = new RealRandomStream ();
163  m_txMiddle = new MacTxMiddle ();
164 }
165 
166 DcaTxop::~DcaTxop ()
167 {
168  NS_LOG_FUNCTION (this);
169  m_switchQueueTimer.Cancel();
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION (this);
176  m_queue = 0;
177  m_low = 0;
178  m_stationManager = 0;
179  delete m_transmissionListener;
180  delete m_dcf;
181  delete m_rng;
182  delete m_txMiddle;
183  m_transmissionListener = 0;
184  m_dcf = 0;
185  m_rng = 0;
186  m_txMiddle = 0;
187 }
188 
189 void
190 DcaTxop::SetManager (DcfManager *manager)
191 {
192  NS_LOG_FUNCTION (this << manager);
193  m_manager = manager;
194  m_manager->Add (m_dcf);
195 }
196 
197 void
198 DcaTxop::SetLow (Ptr<MacLow> low)
199 {
200  NS_LOG_FUNCTION (this << low);
201  m_low = low;
202 }
203 void
204 DcaTxop::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager)
205 {
206  NS_LOG_FUNCTION (this << remoteManager);
207  m_stationManager = remoteManager;
208 }
209 void
211 {
212  NS_LOG_FUNCTION (this << &callback);
213  m_txOkCallback = callback;
214 }
215 void
217 {
218  NS_LOG_FUNCTION (this << &callback);
219  m_txFailedCallback = callback;
220 }
221 
223 DcaTxop::GetQueue () const
224 {
225  NS_LOG_FUNCTION (this);
226  return m_queue;
227 }
228 
229 void
230 DcaTxop::SetMinCw (uint32_t minCw)
231 {
232  NS_LOG_FUNCTION (this << minCw);
233  m_dcf->SetCwMin (minCw);
234 }
235 void
236 DcaTxop::SetMaxCw (uint32_t maxCw)
237 {
238  NS_LOG_FUNCTION (this << maxCw);
239  m_dcf->SetCwMax (maxCw);
240 }
241 void
242 DcaTxop::SetAifsn (uint32_t aifsn)
243 {
244  NS_LOG_FUNCTION (this << aifsn);
245  m_dcf->SetAifsn (aifsn);
246 }
247 uint32_t
248 DcaTxop::GetMinCw (void) const
249 {
250  NS_LOG_FUNCTION (this);
251  return m_dcf->GetCwMin ();
252 }
253 uint32_t
254 DcaTxop::GetMaxCw (void) const
255 {
256  NS_LOG_FUNCTION (this);
257  return m_dcf->GetCwMax ();
258 }
259 uint32_t
260 DcaTxop::GetAifsn (void) const
261 {
262  NS_LOG_FUNCTION (this);
263  return m_dcf->GetAifsn ();
264 }
265 
266 void
268 {
269  NS_LOG_FUNCTION (this << packet << &hdr);
270  WifiMacTrailer fcs;
271  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
272  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
273  packet, fullPacketSize);
275  bool found = packet->PeekPacketTag(pcpt);
276  NS_LOG_LOGIC ("Enqueue packet to channel : " << pcpt.GetChannel() <<
277  " current channel: " << m_low->GetPhy()->GetChannelNumber());
278  if (m_low && found)
279  {
280  if (m_low->IsTxRadio() && m_low->GetPhy()->GetChannelNumber() == 1) //first packet
281  {
282  NS_LOG_LOGIC ("Switch PHY to channel: " << pcpt.GetChannel());
283  m_low->GetPhy()->SetChannelNumber(pcpt.GetChannel());
284  }
285  }
286  m_queue->Enqueue (packet, hdr);
287  if (pcpt.GetChannel()!=1 && pcpt.GetChannel()!=0 &&
288  m_low->IsTxRadio())
289  UpdateActiveChannels(pcpt.GetChannel());
290  //start the switching queue timer
291  if (!m_switchQueueTimer.IsRunning() && m_low->IsTxRadio ())
292  {
293  m_switchQueueTimer = Simulator::Schedule(m_queueUtilizationTime,
294  &DcaTxop::SwitchQueueHandler, this);
295  }
296  StartAccessIfNeeded ();
297 }
298 
299 void
300 DcaTxop::UpdateActiveChannels(uint16_t channel)
301 {
302  NS_LOG_FUNCTION (this << channel);
303  bool found = false;
304  if (m_activeChannels.empty())
305  {
306  m_activeChannels.push_back(DcaTxop::ActiveChannels(channel, Simulator::Now()));
307  return;
308  }
309  else
310  {
311  ListActiveChannelsI it;
312  for (it = m_activeChannels.begin (); it != m_activeChannels.end (); ++it)
313  {
314  uint16_t chan = it->channel;
315  if (channel == chan)
316  {
317  //update current entry
318  it->lastActive = Simulator::Now();
319  found = true;
320  break;
321  }
322  }
323  }
324  if (!found)
325  {
326  m_activeChannels.push_back(DcaTxop::ActiveChannels(channel, Simulator::Now()));
327  }
328 }
329 
330 uint16_t
331 DcaTxop::GetNextActiveChannel (void)
332 {
333  //Only traverse if we're not empty and not size = 1
334  if (!m_activeChannels.empty() && m_activeChannels.size()!=1)
335  {
336  ListActiveChannelsI it;
337  ListActiveChannelsI startIterator;
338  bool startLooking = false;
339  bool keepRunning = true;
340  while (keepRunning) {
341  keepRunning = false;
342  it = m_activeChannels.begin();
343  long unsigned int count = 0;
344  while (it != startIterator)
345  {
346  count++;
347  if (it->channel == m_currentChannel && !startLooking)
348  {
349  NS_LOG_LOGIC ("rotate STARTS: " << count);
350  startLooking = true;
351  startIterator = it;
352  }
353  if (startLooking)
354  {
355  if (Simulator::Now() - it->lastActive > m_activeChannelTimeout
356  && it->channel != m_currentChannel)
357  {
358  //record is too old. let's not use this channel anymore
359  NS_LOG_LOGIC ("Disabling channel " << it->channel << " usage in TX radio");
360  m_activeChannels.erase(it);
361  if (m_activeChannels.size() == 1) return m_currentChannel;
362  keepRunning = true;
363  break;
364  }
365  else if ( it->channel != m_currentChannel )
366  {
367  //record is good! let's switch
368  NS_LOG_LOGIC ("Found next active channel " << it->channel);
369  return it->channel;
370  }
371  }
372 
373  //rotate
374  if (count == m_activeChannels.size()) {
375  it = m_activeChannels.begin();
376  }
377  else ++it;
378 
379  }
380  }
381  }
382 
383  NS_LOG_LOGIC ("No next active channel found");
384  return m_currentChannel;
385 }
386 
387 int64_t
388 DcaTxop::AssignStreams (int64_t stream)
389 {
390  NS_LOG_FUNCTION (this << stream);
391  m_rng->AssignStreams (stream);
392  return 1;
393 }
394 
395 void
397 {
398  NS_LOG_FUNCTION (this);
399  if ((m_currentPacket != 0
400  || !m_queue->IsEmpty (m_currentChannel))
401  && !m_dcf->IsAccessRequested ())
402  {
403  m_manager->RequestAccess (m_dcf);
404  }
405 }
406 
407 void
408 DcaTxop::StartAccessIfNeeded (void)
409 {
410  NS_LOG_FUNCTION (this);
411  if (m_currentPacket == 0
412  && !m_queue->IsEmpty (m_currentChannel)
413  && !m_dcf->IsAccessRequested ())
414  {
415  m_manager->RequestAccess (m_dcf);
416  }
417 }
418 
419 
420 Ptr<MacLow>
421 DcaTxop::Low (void)
422 {
423  NS_LOG_FUNCTION (this);
424  return m_low;
425 }
426 
427 bool
428 DcaTxop::NeedRts (Ptr<const Packet> packet, const WifiMacHeader *header)
429 {
430  NS_LOG_FUNCTION (this << packet << header);
431  return m_stationManager->NeedRts (header->GetAddr1 (), header,
432  packet);
433 }
434 
435 void
437 {
438  NS_LOG_FUNCTION (this);
439  m_dcf->ResetCw ();
440  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
441  m_currentChannel = m_low->GetPhy()->GetChannelNumber();
443 }
444 bool
445 DcaTxop::NeedRtsRetransmission (void)
446 {
447  NS_LOG_FUNCTION (this);
448  return m_stationManager->NeedRtsRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
449  m_currentPacket);
450 }
451 
452 bool
453 DcaTxop::NeedDataRetransmission (void)
454 {
455  NS_LOG_FUNCTION (this);
456  return m_stationManager->NeedDataRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
457  m_currentPacket);
458 }
459 bool
460 DcaTxop::NeedFragmentation (void)
461 {
462  NS_LOG_FUNCTION (this);
463  return m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr,
464  m_currentPacket);
465 }
466 
467 void
468 DcaTxop::NextFragment (void)
469 {
470  NS_LOG_FUNCTION (this);
471  m_fragmentNumber++;
472 }
473 
474 uint32_t
475 DcaTxop::GetFragmentSize (void)
476 {
477  NS_LOG_FUNCTION (this);
478  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
479  m_currentPacket, m_fragmentNumber);
480 }
481 bool
482 DcaTxop::IsLastFragment (void)
483 {
484  NS_LOG_FUNCTION (this);
485  return m_stationManager->IsLastFragment (m_currentHdr.GetAddr1 (), &m_currentHdr,
486  m_currentPacket, m_fragmentNumber);
487 }
488 
489 uint32_t
490 DcaTxop::GetNextFragmentSize (void)
491 {
492  NS_LOG_FUNCTION (this);
493  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
494  m_currentPacket, m_fragmentNumber + 1);
495 }
496 
497 uint32_t
498 DcaTxop::GetFragmentOffset (void)
499 {
500  NS_LOG_FUNCTION (this);
501  return m_stationManager->GetFragmentOffset (m_currentHdr.GetAddr1 (), &m_currentHdr,
502  m_currentPacket, m_fragmentNumber);
503 }
504 
505 Ptr<Packet>
506 DcaTxop::GetFragmentPacket (WifiMacHeader *hdr)
507 {
508  NS_LOG_FUNCTION (this << hdr);
509  *hdr = m_currentHdr;
510  hdr->SetFragmentNumber (m_fragmentNumber);
511  uint32_t startOffset = GetFragmentOffset ();
512  Ptr<Packet> fragment;
513  if (IsLastFragment ())
514  {
515  hdr->SetNoMoreFragments ();
516  }
517  else
518  {
519  hdr->SetMoreFragments ();
520  }
521  fragment = m_currentPacket->CreateFragment (startOffset,
522  GetFragmentSize ());
523  return fragment;
524 }
525 
526 bool
527 DcaTxop::NeedsAccess (void) const
528 {
529  NS_LOG_FUNCTION (this);
530  return !m_queue->IsEmpty (m_currentChannel) || m_currentPacket != 0;
531 }
532 void
533 DcaTxop::NotifyAccessGranted (void)
534 {
535  NS_LOG_FUNCTION (this);
536  if (m_currentPacket == 0)
537  {
538  if (m_queue->IsEmpty (m_currentChannel))
539  {
540  NS_LOG_DEBUG ("queue empty");
541  return;
542  }
543  m_currentPacket = m_queue->DequeueForChannel (&m_currentHdr, m_currentChannel);
544  NS_ASSERT (m_currentPacket != 0);
545  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
546  m_currentHdr.SetSequenceNumber (sequence);
547  m_currentHdr.SetFragmentNumber (0);
548  m_currentHdr.SetNoMoreFragments ();
549  m_currentHdr.SetNoRetry ();
550  m_fragmentNumber = 0;
551  NS_LOG_DEBUG ("dequeued size=" << m_currentPacket->GetSize () <<
552  ", to=" << m_currentHdr.GetAddr1 () <<
553  ", seq=" << m_currentHdr.GetSequenceControl ());
554  }
555  MacLowTransmissionParameters params;
556  params.DisableOverrideDurationId ();
557  if (m_currentHdr.GetAddr1 ().IsGroup ())
558  {
559  params.DisableRts ();
560  params.DisableAck ();
561  params.DisableNextData ();
562  Low ()->StartTransmission (m_currentPacket,
563  &m_currentHdr,
564  params,
565  m_transmissionListener);
566  NS_LOG_DEBUG ("tx broadcast");
567  }
568  else
569  {
570  params.EnableAck ();
571 
572  if (NeedFragmentation ())
573  {
574  WifiMacHeader hdr;
575  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
576  if (NeedRts (fragment, &hdr))
577  {
578  params.EnableRts ();
579  }
580  else
581  {
582  params.DisableRts ();
583  }
584  if (IsLastFragment ())
585  {
586  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
587  params.DisableNextData ();
588  }
589  else
590  {
591  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
592  params.EnableNextData (GetNextFragmentSize ());
593  }
594  Low ()->StartTransmission (fragment, &hdr, params,
595  m_transmissionListener);
596  }
597  else
598  {
599  if (NeedRts (m_currentPacket, &m_currentHdr))
600  {
601  params.EnableRts ();
602  NS_LOG_DEBUG ("tx unicast rts");
603  }
604  else
605  {
606  params.DisableRts ();
607  NS_LOG_DEBUG ("tx unicast");
608  }
609  params.DisableNextData ();
610  Low ()->StartTransmission (m_currentPacket, &m_currentHdr,
611  params, m_transmissionListener);
612  }
613  }
614 }
615 
616 void
617 DcaTxop::NotifyInternalCollision (void)
618 {
619  NS_LOG_FUNCTION (this);
620  NotifyCollision ();
621 }
622 void
623 DcaTxop::NotifyCollision (void)
624 {
625  NS_LOG_FUNCTION (this);
626  NS_LOG_DEBUG ("collision");
627  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
629 }
630 
631 void
632 DcaTxop::NotifyChannelSwitching (Time duration, uint16_t toChannel)
633 {
634  NS_LOG_FUNCTION (this);
635  m_currentChannel = toChannel;
636  m_currentPacket = 0;
637 }
638 
639 void
640 DcaTxop::NotifyChannelSensing (void)
641 {
642  NS_LOG_FUNCTION (this);
643  m_currentPacket = 0;
644 }
645 
646 void
647 DcaTxop::GotCts (double snr, WifiMode txMode)
648 {
649  NS_LOG_FUNCTION (this << snr << txMode);
650  NS_LOG_DEBUG ("got cts");
651 }
652 void
653 DcaTxop::MissedCts (void)
654 {
655  NS_LOG_FUNCTION (this);
656  NS_LOG_DEBUG ("missed cts");
657  if (!NeedRtsRetransmission ())
658  {
659  NS_LOG_DEBUG ("Cts Fail");
660  m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
661  if (!m_txFailedCallback.IsNull ())
662  {
663  m_txFailedCallback (m_currentHdr);
664  }
665  // to reset the dcf.
666  m_currentPacket = 0;
667  m_dcf->ResetCw ();
668  }
669  else
670  {
671  m_dcf->UpdateFailedCw ();
672  }
673  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
675 }
676 void
677 DcaTxop::GotAck (double snr, WifiMode txMode)
678 {
679  NS_LOG_FUNCTION (this << snr << txMode);
680  if (!NeedFragmentation ()
681  || IsLastFragment ())
682  {
683  NS_LOG_DEBUG ("got ack. tx done.");
684  if (!m_txOkCallback.IsNull ())
685  {
686  m_txOkCallback (m_currentHdr);
687  }
688 
689  /* we are not fragmenting or we are done fragmenting
690  * so we can get rid of that packet now.
691  */
692  m_currentPacket = 0;
693  m_dcf->ResetCw ();
694  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
696  }
697  else
698  {
699  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
700  }
701 }
702 void
703 DcaTxop::MissedAck (void)
704 {
705  NS_LOG_FUNCTION (this);
706  NS_LOG_DEBUG ("missed ack");
707  if (!NeedDataRetransmission ())
708  {
709  NS_LOG_DEBUG ("Ack Fail");
710  m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
711  if (!m_txFailedCallback.IsNull ())
712  {
713  m_txFailedCallback (m_currentHdr);
714  }
715  // to reset the dcf.
716  m_currentPacket = 0;
717  m_dcf->ResetCw ();
718  }
719  else
720  {
721  NS_LOG_DEBUG ("Retransmit");
722  m_currentHdr.SetRetry ();
723  m_dcf->UpdateFailedCw ();
724  }
725  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
727 }
728 void
729 DcaTxop::StartNext (void)
730 {
731  NS_LOG_FUNCTION (this);
732  NS_LOG_DEBUG ("start next packet fragment");
733  /* this callback is used only for fragments. */
734  NextFragment ();
735  WifiMacHeader hdr;
736  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
737  MacLowTransmissionParameters params;
738  params.EnableAck ();
739  params.DisableRts ();
740  params.DisableOverrideDurationId ();
741  if (IsLastFragment ())
742  {
743  params.DisableNextData ();
744  }
745  else
746  {
747  params.EnableNextData (GetNextFragmentSize ());
748  }
749  Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener);
750 }
751 
752 void
754 {
755  NS_LOG_FUNCTION (this);
756  NS_LOG_DEBUG ("transmission cancelled");
782 }
783 
784 void
785 DcaTxop::EndTxNoAck (void)
786 {
787  NS_LOG_FUNCTION (this);
788  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
789  m_currentPacket = 0;
790  m_dcf->ResetCw ();
791  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
792  StartAccessIfNeeded ();
793 }
794 
795 void
796 DcaTxop::SwitchQueueHandler (void)
797 {
798  NS_LOG_FUNCTION (this);
799  //we must see which channels are TX active, and switch if necessary
800  uint16_t channel = GetNextActiveChannel();
801  Time nextQueueSwitch = m_queueUtilizationTime;
802  if (m_currentChannel != channel)
803  {
804  //we're switching
805  NS_LOG_DEBUG ("Queue switching on TX radio from channel "
806  << m_currentChannel << " to channel " << channel);
807 
808  m_low->GetPhy()->SetChannelNumber(channel);
809 
810  m_currentChannel = channel;
811 
812  nextQueueSwitch = nextQueueSwitch + m_low->GetPhy()->GetDelayUntilIdle();
813 
814  Ptr<YansWifiPhy> phy = DynamicCast<YansWifiPhy>(m_low->GetPhy());
815  if (phy->GetDelayUntilIdle()<phy->GetSwitchingDelay())
816  nextQueueSwitch = nextQueueSwitch + phy->GetSwitchingDelay();
817  Simulator::Schedule( (nextQueueSwitch-m_queueUtilizationTime), &DcaTxop::RestartAccessIfNeeded, this);
818  }
819 
820  //Call this function again
821  m_switchQueueTimer = Simulator::Schedule (nextQueueSwitch,
822  &DcaTxop::SwitchQueueHandler, this);
823 }
824 
825 } // namespace ns3
keep track of time unit.
Definition: nstime.h:149
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
TypeId AddConstructor(void)
Definition: type-id.h:388
virtual void DoNotifyInternalCollision(void)
Definition: dca-txop.cc:64
void SetTxFailedCallback(TxFailed callback)
Definition: dca-txop.cc:216
virtual void MissedAck(void)
Definition: dca-txop.cc:105
void RequestAccess(DcfState *state)
Definition: dcf-manager.cc:419
#define NS_ASSERT(condition)
Definition: assert.h:64
virtual int64_t AssignStreams(int64_t stream)=0
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
void SetAifsn(uint32_t aifsn)
Definition: dcf-manager.cc:57
bool IsRunning(void) const
Definition: event-id.cc:59
void ResetCw(void)
Definition: dcf-manager.cc:90
int64_t AssignStreams(int64_t stream)
Definition: dca-txop.cc:388
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
listen to events coming from ns3::MacLow.
Definition: mac-low.h:55
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:88
void Add(DcfState *dcf)
Definition: dcf-manager.cc:338
virtual void GotCts(double snr, WifiMode txMode)
Definition: dca-txop.cc:93
void SetTxOkCallback(TxOk callback)
Definition: dca-txop.cc:210
virtual void GotAck(double snr, WifiMode txMode)
Definition: dca-txop.cc:101
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:243
void Queue(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: dca-txop.cc:267
virtual uint32_t GetSerializedSize(void) const
void Cancel(void)
Definition: dca-txop.cc:753
hold objects of type ns3::Time
Definition: nstime.h:700
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
Definition: dcf-manager.h:175
keep track of the state needed for a single DCF function.Multiple instances of a DcfState can be regi...
Definition: dcf-manager.h:46
bool IsAccessRequested(void) const
Definition: dcf-manager.cc:133
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void StartBackoffNow(uint32_t nSlots)
Definition: dcf-manager.cc:109
void NotifyChannelSwitching(Time duration, uint16_t toChannel)
Definition: dca-txop.cc:632
hold objects of type Ptr<T>
Definition: pointer.h:33
void DoInitialize()
Definition: dca-txop.cc:436
bool IsGroup(void) const
virtual void EndTxNoAck(void)
Definition: dca-txop.cc:117
static Time Now(void)
Definition: simulator.cc:179
virtual void MissedCts(void)
Definition: dca-txop.cc:97
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
virtual void DoNotifyCollision(void)
Definition: dca-txop.cc:68
uint32_t GetCw(void) const
Definition: dcf-manager.cc:118
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual void StartNext(void)
Definition: dca-txop.cc:109
void Cancel(void)
Definition: event-id.cc:47
virtual void DoDispose(void)
Definition: dca-txop.cc:173
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
virtual void DoNotifyAccessGranted(void)
Definition: dca-txop.cc:60
void RestartAccessIfNeeded(void)
Definition: dca-txop.cc:396
virtual void DoNotifyChannelSwitching(Time duration, uint16_t toChannel)
Definition: dca-txop.cc:72
void UpdateFailedCw(void)
Definition: dcf-manager.cc:95
handle packet fragmentation and retransmissions.This class implements the packet fragmentation and re...
Definition: dca-txop.h:70
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
virtual void DoInitialize(void)
Definition: object.cc:342
virtual uint32_t GetSerializedSize(void) const