A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
dca-txop.cc
Go to the documentation of this file.
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 
38 NS_LOG_COMPONENT_DEFINE ("DcaTxop");
39 
40 #undef NS_LOG_APPEND_CONTEXT
41 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
42 
43 namespace ns3 {
44 
45 class DcaTxop::Dcf : public DcfState
46 {
47 public:
48  Dcf (DcaTxop * txop)
49  : m_txop (txop)
50  {
51  }
52 private:
53  virtual void DoNotifyAccessGranted (void)
54  {
56  }
57  virtual void DoNotifyInternalCollision (void)
58  {
60  }
61  virtual void DoNotifyCollision (void)
62  {
64  }
65  virtual void DoNotifyChannelSwitching (void)
66  {
68  }
70 };
71 
73 {
74 public:
77  m_txop (txop) {
78  }
79 
80  virtual ~TransmissionListener () {}
81 
82  virtual void GotCts (double snr, WifiMode txMode)
83  {
84  m_txop->GotCts (snr, txMode);
85  }
86  virtual void MissedCts (void)
87  {
88  m_txop->MissedCts ();
89  }
90  virtual void GotAck (double snr, WifiMode txMode)
91  {
92  m_txop->GotAck (snr, txMode);
93  }
94  virtual void MissedAck (void)
95  {
96  m_txop->MissedAck ();
97  }
98  virtual void StartNext (void)
99  {
100  m_txop->StartNext ();
101  }
102  virtual void Cancel (void)
103  {
104  m_txop->Cancel ();
105  }
106 
107 private:
109 };
110 
112 
113 TypeId
115 {
116  static TypeId tid = TypeId ("ns3::DcaTxop")
119  .AddAttribute ("Queue", "The WifiMacQueue object",
120  PointerValue (),
121  MakePointerAccessor (&DcaTxop::GetQueue),
122  MakePointerChecker<WifiMacQueue> ())
123  ;
124  return tid;
125 }
126 
128  : m_manager (0),
129  m_currentPacket (0)
130 {
131  NS_LOG_FUNCTION (this);
133  m_dcf = new DcaTxop::Dcf (this);
134  m_queue = CreateObject<WifiMacQueue> ();
135  m_rng = new RealRandomStream ();
136  m_txMiddle = new MacTxMiddle ();
137 }
138 
140 {
141  NS_LOG_FUNCTION (this);
142 }
143 
144 void
146 {
147  NS_LOG_FUNCTION (this);
148  m_queue = 0;
149  m_low = 0;
150  m_stationManager = 0;
151  delete m_transmissionListener;
152  delete m_dcf;
153  delete m_rng;
154  delete m_txMiddle;
156  m_dcf = 0;
157  m_rng = 0;
158  m_txMiddle = 0;
159 }
160 
161 void
163 {
164  NS_LOG_FUNCTION (this << manager);
165  m_manager = manager;
166  m_manager->Add (m_dcf);
167 }
168 
169 void
171 {
172  NS_LOG_FUNCTION (this << low);
173  m_low = low;
174 }
175 void
177 {
178  NS_LOG_FUNCTION (this << remoteManager);
179  m_stationManager = remoteManager;
180 }
181 void
183 {
184  m_txOkCallback = callback;
185 }
186 void
188 {
189  m_txFailedCallback = callback;
190 }
191 
194 {
195  NS_LOG_FUNCTION (this);
196  return m_queue;
197 }
198 
199 void
200 DcaTxop::SetMinCw (uint32_t minCw)
201 {
202  NS_LOG_FUNCTION (this << minCw);
203  m_dcf->SetCwMin (minCw);
204 }
205 void
206 DcaTxop::SetMaxCw (uint32_t maxCw)
207 {
208  NS_LOG_FUNCTION (this << maxCw);
209  m_dcf->SetCwMax (maxCw);
210 }
211 void
212 DcaTxop::SetAifsn (uint32_t aifsn)
213 {
214  NS_LOG_FUNCTION (this << aifsn);
215  m_dcf->SetAifsn (aifsn);
216 }
217 uint32_t
218 DcaTxop::GetMinCw (void) const
219 {
220  return m_dcf->GetCwMin ();
221 }
222 uint32_t
223 DcaTxop::GetMaxCw (void) const
224 {
225  return m_dcf->GetCwMax ();
226 }
227 uint32_t
228 DcaTxop::GetAifsn (void) const
229 {
230  return m_dcf->GetAifsn ();
231 }
232 
233 void
235 {
236  NS_LOG_FUNCTION (this << packet << &hdr);
237  WifiMacTrailer fcs;
238  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
240  packet, fullPacketSize);
241  m_queue->Enqueue (packet, hdr);
243 }
244 
245 int64_t
246 DcaTxop::AssignStreams (int64_t stream)
247 {
248  NS_LOG_FUNCTION (this << stream);
249  m_rng->AssignStreams (stream);
250  return 1;
251 }
252 
253 void
255 {
256  NS_LOG_FUNCTION (this);
257  if ((m_currentPacket != 0
258  || !m_queue->IsEmpty ())
259  && !m_dcf->IsAccessRequested ())
260  {
262  }
263 }
264 
265 void
267 {
268  NS_LOG_FUNCTION (this);
269  if (m_currentPacket == 0
270  && !m_queue->IsEmpty ()
271  && !m_dcf->IsAccessRequested ())
272  {
274  }
275 }
276 
277 
280 {
281  return m_low;
282 }
283 
284 bool
286 {
287  return m_stationManager->NeedRts (header->GetAddr1 (), header,
288  packet);
289 }
290 
291 void
293 {
294  m_dcf->ResetCw ();
297 }
298 bool
300 {
303 }
304 
305 bool
307 {
310 }
311 bool
313 {
316 }
317 
318 void
320 {
322 }
323 
324 uint32_t
326 {
329 }
330 bool
332 {
335 }
336 
337 uint32_t
339 {
342 }
343 
344 uint32_t
346 {
349 }
350 
353 {
354  *hdr = m_currentHdr;
356  uint32_t startOffset = GetFragmentOffset ();
357  Ptr<Packet> fragment;
358  if (IsLastFragment ())
359  {
360  hdr->SetNoMoreFragments ();
361  }
362  else
363  {
364  hdr->SetMoreFragments ();
365  }
366  fragment = m_currentPacket->CreateFragment (startOffset,
367  GetFragmentSize ());
368  return fragment;
369 }
370 
371 bool
373 {
374  return !m_queue->IsEmpty () || m_currentPacket != 0;
375 }
376 void
378 {
379  NS_LOG_FUNCTION (this);
380  if (m_currentPacket == 0)
381  {
382  if (m_queue->IsEmpty ())
383  {
384  NS_LOG_DEBUG ("queue empty");
385  return;
386  }
388  NS_ASSERT (m_currentPacket != 0);
389  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
390  m_currentHdr.SetSequenceNumber (sequence);
394  m_fragmentNumber = 0;
395  NS_LOG_DEBUG ("dequeued size=" << m_currentPacket->GetSize () <<
396  ", to=" << m_currentHdr.GetAddr1 () <<
397  ", seq=" << m_currentHdr.GetSequenceControl ());
398  }
400  params.DisableOverrideDurationId ();
401  if (m_currentHdr.GetAddr1 ().IsGroup ())
402  {
403  params.DisableRts ();
404  params.DisableAck ();
405  params.DisableNextData ();
407  &m_currentHdr,
408  params,
410  m_currentPacket = 0;
411  m_dcf->ResetCw ();
414  NS_LOG_DEBUG ("tx broadcast");
415  }
416  else
417  {
418  params.EnableAck ();
419 
420  if (NeedFragmentation ())
421  {
422  WifiMacHeader hdr;
423  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
424  if (NeedRts (fragment, &hdr))
425  {
426  params.EnableRts ();
427  }
428  else
429  {
430  params.DisableRts ();
431  }
432  if (IsLastFragment ())
433  {
434  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
435  params.DisableNextData ();
436  }
437  else
438  {
439  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
441  }
442  Low ()->StartTransmission (fragment, &hdr, params,
444  }
445  else
446  {
448  {
449  params.EnableRts ();
450  NS_LOG_DEBUG ("tx unicast rts");
451  }
452  else
453  {
454  params.DisableRts ();
455  NS_LOG_DEBUG ("tx unicast");
456  }
457  params.DisableNextData ();
459  params, m_transmissionListener);
460  }
461  }
462 }
463 
464 void
466 {
467  NS_LOG_FUNCTION (this);
468  NotifyCollision ();
469 }
470 void
472 {
473  NS_LOG_FUNCTION (this);
474  NS_LOG_DEBUG ("collision");
477 }
478 
479 void
481 {
482  m_queue->Flush ();
483  m_currentPacket = 0;
484 }
485 
486 void
487 DcaTxop::GotCts (double snr, WifiMode txMode)
488 {
489  NS_LOG_FUNCTION (this << snr << txMode);
490  NS_LOG_DEBUG ("got cts");
491 }
492 void
494 {
495  NS_LOG_FUNCTION (this);
496  NS_LOG_DEBUG ("missed cts");
497  if (!NeedRtsRetransmission ())
498  {
499  NS_LOG_DEBUG ("Cts Fail");
501  if (!m_txFailedCallback.IsNull ())
502  {
504  }
505  // to reset the dcf.
506  m_currentPacket = 0;
507  m_dcf->ResetCw ();
508  }
509  else
510  {
511  m_dcf->UpdateFailedCw ();
512  }
515 }
516 void
517 DcaTxop::GotAck (double snr, WifiMode txMode)
518 {
519  NS_LOG_FUNCTION (this << snr << txMode);
520  if (!NeedFragmentation ()
521  || IsLastFragment ())
522  {
523  NS_LOG_DEBUG ("got ack. tx done.");
524  if (!m_txOkCallback.IsNull ())
525  {
527  }
528 
529  /* we are not fragmenting or we are done fragmenting
530  * so we can get rid of that packet now.
531  */
532  m_currentPacket = 0;
533  m_dcf->ResetCw ();
536  }
537  else
538  {
539  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
540  }
541 }
542 void
544 {
545  NS_LOG_FUNCTION (this);
546  NS_LOG_DEBUG ("missed ack");
547  if (!NeedDataRetransmission ())
548  {
549  NS_LOG_DEBUG ("Ack Fail");
551  if (!m_txFailedCallback.IsNull ())
552  {
554  }
555  // to reset the dcf.
556  m_currentPacket = 0;
557  m_dcf->ResetCw ();
558  }
559  else
560  {
561  NS_LOG_DEBUG ("Retransmit");
563  m_dcf->UpdateFailedCw ();
564  }
567 }
568 void
570 {
571  NS_LOG_FUNCTION (this);
572  NS_LOG_DEBUG ("start next packet fragment");
573  /* this callback is used only for fragments. */
574  NextFragment ();
575  WifiMacHeader hdr;
576  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
578  params.EnableAck ();
579  params.DisableRts ();
580  params.DisableOverrideDurationId ();
581  if (IsLastFragment ())
582  {
583  params.DisableNextData ();
584  }
585  else
586  {
588  }
589  Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener);
590 }
591 
592 void
594 {
595  NS_LOG_FUNCTION (this);
596  NS_LOG_DEBUG ("transmission cancelled");
622 }
623 
624 } // namespace ns3