A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
uan-mac-rc.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
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: Leonard Tracy <lentracy@gmail.com>
19  */
20 
21 #include "uan-mac-rc.h"
22 #include "uan-header-rc.h"
23 #include "uan-tx-mode.h"
24 #include "uan-phy.h"
25 #include "uan-header-common.h"
26 #include "uan-phy-dual.h"
27 
28 #include "ns3/log.h"
29 #include "ns3/nstime.h"
30 #include "ns3/simulator.h"
31 #include "ns3/assert.h"
32 #include "ns3/double.h"
33 #include "ns3/uinteger.h"
34 
35 #include <list>
36 #include <utility>
37 
38 
39 
40 NS_LOG_COMPONENT_DEFINE ("UanMacRc");
41 namespace ns3 {
42 
44 
46  : m_length (0),
47  m_frameNo (0),
48  m_retryNo (0),
49  m_transmitted (false)
50 {
51 
52 }
53 
54 Reservation::Reservation (std::list<std::pair <Ptr<Packet>, UanAddress > > &list, uint8_t frameNo, uint32_t maxPkts)
55  : m_frameNo (frameNo),
56  m_retryNo (0),
57  m_transmitted (false)
58 {
59  uint32_t numPkts = (maxPkts) ? maxPkts : list.size ();
60  uint32_t length = 0;
61  UanHeaderRcData dh;
62  UanHeaderCommon ch;
63 
64  for (uint32_t i = 0; i < numPkts; i++)
65  {
66  length += list.front ().first->GetSize () +
67  ch.GetSerializedSize () +
68  dh.GetSerializedSize ();
69  m_pktList.push_back (list.front ());
70  list.pop_front ();
71  }
72  m_length = length;
73 }
74 
76 {
77  std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
78  for (it = m_pktList.begin (); it != m_pktList.end (); it++)
79  {
80  it->first = Ptr<Packet> ((Packet *) 0);
81  }
82  m_pktList.clear ();
83  m_timestamp.clear ();
84 }
85 uint32_t
87 {
88  return m_pktList.size ();
89 }
90 
91 uint32_t
93 {
94  return m_length;
95 }
96 
97 const std::list<std::pair <Ptr<Packet>, UanAddress > > &
99 {
100  return m_pktList;
101 }
102 
103 uint8_t
105 {
106  return m_frameNo;
107 }
108 
109 uint8_t
111 {
112  return m_retryNo;
113 }
114 
115 Time
116 Reservation::GetTimestamp (uint8_t n) const
117 {
118  return m_timestamp[n];
119 }
120 
121 bool
123 {
124  return m_transmitted;
125 }
126 
127 void
129 {
130  m_frameNo = fn;
131 }
132 
133 void
135 {
136  m_timestamp.push_back (t);
137 }
138 
139 void
141 {
142  m_retryNo++;
143 }
144 
145 void
147 {
148  m_transmitted = true;
149 }
150 
151 uint32_t UanMacRc::m_cntrlSends = 0;
152 
154  : UanMac (),
155  m_state (UNASSOCIATED),
156  m_rtsBlocked (false),
157  m_currentRate (10),
158  m_frameNo (0),
159  m_cleared (false)
160 {
161  m_ev = CreateObject<ExponentialRandomVariable> ();
162 
163  UanHeaderCommon ch;
164  UanHeaderRcCts ctsh;
166 
167  m_ctsSizeN = ctsh.GetSerializedSize ();
168  m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
169 }
170 
172 {
173 }
174 
175 void
177 {
178  if (m_cleared)
179  {
180  return;
181  }
182  m_cleared = true;
183  if (m_phy)
184  {
185  m_phy->Clear ();
186  m_phy = 0;
187  }
188  std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
189  for (it = m_pktQueue.begin (); it != m_pktQueue.end (); it++)
190  {
191  it->first = 0;
192  }
193  m_pktQueue.clear ();
194  m_resList.clear ();
195  m_startAgain.Cancel ();
196  m_rtsEvent.Cancel ();
197 }
198 
199 void
201 {
202  Clear ();
204 }
205 
206 TypeId
208 {
209  static TypeId tid = TypeId ("ns3::UanMacRc")
210  .SetParent<UanMac> ()
211  .AddConstructor<UanMacRc> ()
212  .AddAttribute ("RetryRate",
213  "Number of retry attempts per second (of RTS/GWPING)",
214  DoubleValue (1 / 5.0),
215  MakeDoubleAccessor (&UanMacRc::m_retryRate),
216  MakeDoubleChecker<double> ())
217  .AddAttribute ("MaxFrames",
218  "Maximum number of frames to include in a single RTS",
219  UintegerValue (1),
220  MakeUintegerAccessor (&UanMacRc::m_maxFrames),
221  MakeUintegerChecker<uint32_t> ())
222  .AddAttribute ("QueueLimit",
223  "Maximum packets to queue at MAC",
224  UintegerValue (10),
225  MakeUintegerAccessor (&UanMacRc::m_queueLimit),
226  MakeUintegerChecker<uint32_t> ())
227  .AddAttribute ("SIFS",
228  "Spacing to give between frames (this should match gateway)",
229  TimeValue (Seconds (0.2)),
230  MakeTimeAccessor (&UanMacRc::m_sifs),
231  MakeTimeChecker ())
232  .AddAttribute ("NumberOfRates",
233  "Number of rate divisions supported by each PHY",
234  UintegerValue (0),
235  MakeUintegerAccessor (&UanMacRc::m_numRates),
236  MakeUintegerChecker<uint32_t> ())
237  .AddAttribute ("MinRetryRate",
238  "Smallest allowed RTS retry rate",
239  DoubleValue (0.01),
240  MakeDoubleAccessor (&UanMacRc::m_minRetryRate),
241  MakeDoubleChecker<double> ())
242  .AddAttribute ("RetryStep",
243  "Retry rate increment",
244  DoubleValue (0.01),
245  MakeDoubleAccessor (&UanMacRc::m_retryStep),
246  MakeDoubleChecker<double> ())
247  .AddAttribute ("NumberOfRetryRates",
248  "Number of retry rates",
249  UintegerValue (100),
250  MakeUintegerAccessor (&UanMacRc::m_numRetryRates),
251  MakeUintegerChecker<uint16_t> ())
252  .AddAttribute ("MaxPropDelay",
253  "Maximum possible propagation delay to gateway",
254  TimeValue (Seconds (2)),
255  MakeTimeAccessor (&UanMacRc::m_learnedProp),
256  MakeTimeChecker ())
257  .AddTraceSource ("Enqueue",
258  "A (data) packet arrived at MAC for transmission",
260  .AddTraceSource ("Dequeue",
261  "A (data) packet was passed down to PHY from MAC",
263  .AddTraceSource ("RX",
264  "A packet was destined for and received at this MAC layer",
266  ;
267  return tid;
268 }
269 
270 int64_t
271 UanMacRc::AssignStreams (int64_t stream)
272 {
273  NS_LOG_FUNCTION (this << stream);
274  m_ev->SetStream (stream);
275  return 1;
276 }
277 
278 Address
280 {
281  return m_address;
282 }
283 
284 void
286 {
287  m_address = addr;
288 }
289 
290 bool
291 UanMacRc::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
292 {
293  if (protocolNumber > 0)
294  {
295  NS_LOG_WARN ("Warning: UanMacRc does not support multiple protocols. protocolNumber argument to Enqueue is being ignored");
296  }
297 
298 
299  if (m_pktQueue.size () >= m_queueLimit)
300  {
301  return false;
302  }
303 
304  m_pktQueue.push_back (std::make_pair (packet, UanAddress::ConvertFrom (dest)));
305 
306  switch (m_state)
307  {
308  case UNASSOCIATED:
309  Associate ();
310  return true;
311  case IDLE:
312  if (!m_rtsEvent.IsRunning ())
313  {
314  SendRts ();
315  }
316  return true;
317  case GWPSENT:
318  case RTSSENT:
319  case DATATX:
320  return true;
321  }
322 
323  return true;
324 }
325 
326 void
328 {
329  m_forwardUpCb = cb;
330 }
331 
332 void
334 {
335  m_phy = phy;
337 }
338 
339 Address
341 {
342  return UanAddress::GetBroadcast ();
343 }
344 
345 void
347 {
348 
349  UanHeaderCommon ch;
350  pkt->RemoveHeader (ch);
351  if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ())
352  {
353  m_rxLogger (pkt, mode);
354  }
355 
356  switch (ch.GetType ())
357  {
358  case TYPE_DATA:
359 
360  if (ch.GetDest () == m_address)
361  {
362  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " UanMacRc Receiving DATA packet from PHY");
363  UanHeaderRcData dh;
364  pkt->RemoveHeader (dh);
365  m_forwardUpCb (pkt, ch.GetSrc ());
366  }
367  break;
368  case TYPE_RTS:
369  // Currently don't respond to RTS packets at non-gateway nodes
370  // (Code assumes single network neighberhood)
371  break;
372  case TYPE_CTS:
373  {
374  uint32_t ctsBytes = ch.GetSerializedSize () + pkt->GetSize ();
375  m_assocAddr = ch.GetSrc ();
377  pkt->RemoveHeader (ctsg);
378  m_currentRate = ctsg.GetRateNum ();
380 
381  UanHeaderRcRts rhtmp;
382 
383  Time winDelay = ctsg.GetWindowTime ();
384 
385  if (winDelay.GetSeconds () > 0)
386  {
387  m_rtsBlocked = false;
388  Simulator::Schedule (winDelay, &UanMacRc::BlockRtsing, this);
389  }
390  else
391  {
392  NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received window period < 0");
393  }
394 
395  UanHeaderRcCts ctsh;
397  while (pkt->GetSize () > 0)
398  {
399  pkt->RemoveHeader (ctsh);
400  if (ctsh.GetAddress () == m_address)
401  {
402  if (m_state == GWPSENT)
403  {
404  m_assocAddr = ch.GetSrc ();
405  ScheduleData (ctsh, ctsg, ctsBytes);
406  }
407  else if (m_state == RTSSENT)
408  {
409  ScheduleData (ctsh, ctsg, ctsBytes);
410  }
411  else
412  {
413  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS while state != RTSSENT or GWPING");
414  }
415  }
416  }
417  }
418  break;
419  case TYPE_GWPING:
420  // Do not respond to GWPINGS at non-gateway nodes
421  break;
422  case TYPE_ACK:
423  m_rtsBlocked = true;
424  if (ch.GetDest () != m_address)
425  {
426  return;
427  }
428  ProcessAck (pkt);
429  break;
430  default:
431  NS_FATAL_ERROR ("Unknown packet type " << ch.GetType () << " received at node " << GetAddress ());
432  }
433 
434 }
435 
436 void
437 UanMacRc::ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes)
438 {
440 
441 
442 
443  std::list<Reservation>::iterator it = m_resList.begin ();
444  for (; it != m_resList.end (); it++)
445  {
446  if (it->GetFrameNo () == ctsh.GetFrameNo ())
447  {
448  break;
449  }
450  }
451  if (it == m_resList.end ())
452  {
453  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet with no corresponding reservation!");
454  return;
455  }
456  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet. Scheduling data");
457  it->SetTransmitted ();
458 
459  double currentBps = m_phy->GetMode (m_currentRate).GetDataRateBps ();
460 
461  m_learnedProp = Simulator::Now () - ctsg.GetTxTimeStamp () - Seconds (ctsBytes * 8.0 / currentBps);
462 
463 
464  Time arrTime = ctsg.GetTxTimeStamp () + ctsh.GetDelayToTx ();
465  Time txTime = arrTime - m_learnedProp;
466 
467  Time startDelay = txTime - Simulator::Now ();
468 
469  Time frameDelay = Seconds (0);
470 
471  const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
472  std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
473  pit = l.begin ();
474 
475 
476 
477  for (uint32_t i = 0; i < it->GetNoFrames (); i++, pit++)
478  {
479  Ptr<Packet> pkt = (*pit).first->Copy ();
480 
481  UanHeaderRcData dh;
482  dh.SetFrameNo (i);
483  dh.SetPropDelay (m_learnedProp);
484  pkt->AddHeader (dh);
485 
486  UanHeaderCommon ch;
487  ch.SetType (TYPE_DATA);
488  ch.SetDest (m_assocAddr);
489  ch.SetSrc (m_address);
490 
491  pkt->AddHeader (ch);
492  Time eventTime = startDelay + frameDelay;
493  if (eventTime.GetSeconds () < 0)
494  {
495  if (eventTime.GetSeconds () > -0.001)
496  {
497  eventTime = Seconds (0);
498  }
499  else
500  {
501  NS_FATAL_ERROR ("Scheduling error resulted in very negative data transmission time! eventTime = " << eventTime.GetSeconds ());
502  }
503  }
504  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " scheduling with delay " << eventTime.GetSeconds () << " propDelay " << m_learnedProp.GetSeconds () << " start delay " << startDelay.GetSeconds () << " arrival time " << arrTime.GetSeconds ());
505  Simulator::Schedule (eventTime, &UanMacRc::SendPacket, this, pkt, m_currentRate);
506  frameDelay = frameDelay + m_sifs + Seconds (pkt->GetSize () / currentBps);
507  }
508 
509  m_state = IDLE;
510  if (!m_pktQueue.empty ())
511  {
512 
513  if (m_rtsEvent.IsRunning ())
514  {
515  m_rtsEvent.Cancel ();
516  }
517 
518  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
519  double timeout = m_ev->GetValue ();
521  }
522 
523 }
524 
525 void
526 UanMacRc::SendPacket (Ptr<Packet> pkt, uint32_t rate)
527 {
528  UanHeaderCommon ch;
529  pkt->PeekHeader (ch);
530  std::string type;
531  switch (ch.GetType ())
532  {
533  case TYPE_DATA:
534  type = "DATA";
535  break;
536  case TYPE_RTS:
537  type = "RTS";
538  break;
539  case TYPE_CTS:
540  type = "CTS";
541  break;
542  case TYPE_ACK:
543  type = "ACK";
544  break;
545  case TYPE_GWPING:
546  type = "GWPING";
547  break;
548  default:
549  type = "UNKNOWN";
550  break;
551  }
552  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " transmitting " << pkt->GetSize () << " byte packet of type " << type << " with rate " << rate << "(" << m_phy->GetMode (rate).GetDataRateBps () << ") to " << ch.GetDest ());
553  m_dequeueLogger (pkt, rate);
554  m_phy->SendPacket (pkt, rate);
555 }
556 
557 void
559 {
560  UanHeaderRcAck ah;
561  ack->RemoveHeader (ah);
562 
563  std::list<Reservation>::iterator it = m_resList.begin ();
564  for (; it != m_resList.end (); it++)
565  {
566  if (it->GetFrameNo () == ah.GetFrameNo ())
567  {
568  break;
569  }
570  }
571  if (it == m_resList.end ())
572  {
573  NS_LOG_DEBUG ("In " << __func__ << " could not find reservation corresponding to received ACK");
574  return;
575  }
576  if (!it->IsTransmitted ())
577  {
578  return;
579  }
580  if (ah.GetNoNacks () > 0)
581  {
582  const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
583  std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
584  pit = l.begin ();
585 
586  const std::set<uint8_t> &nacks = ah.GetNackedFrames ();
587  std::set<uint8_t>::iterator nit = nacks.begin ();
588  uint8_t pnum = 0;
589  for (; nit != nacks.end (); nit++)
590  {
591  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received NACK for " << (uint32_t) *nit);
592  while (pnum < *nit)
593  {
594  pit++;
595  pnum++;
596  }
597  UanHeaderRcData dh;
598  UanHeaderCommon ch;
599  m_pktQueue.push_front (*pit);
600  }
601  }
602  else
603  {
604  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received ACK for all frames");
605  }
606  m_resList.erase (it);
607 }
608 
611 {
613 
614  rh.SetLength (res.GetLength ());
615  rh.SetNoFrames (res.GetNoFrames ());
616  rh.SetTimeStamp (res.GetTimestamp (res.GetRetryNo ()));
617  rh.SetFrameNo (res.GetFrameNo ());
618  rh.SetRetryNo (res.GetRetryNo ());
619  return rh;
620 }
621 
622 void
624 {
625  m_cntrlSends++;
626 
628  res.AddTimestamp (Simulator::Now ());
629  m_frameNo++;
630  m_resList.push_back (res);
631  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
632  bool phy1ok = IsPhy1Ok ();
633  if (phy1ok && !phyDual->IsPhy2Tx () & !m_rtsBlocked)
634  {
635  Ptr<Packet> pkt = Create<Packet> (0);
636  pkt->AddHeader (CreateRtsHeader (res));
638  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending first GWPING " << *pkt);
640  }
641  m_state = GWPSENT;
643  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
644  double timeout = m_ev->GetValue ();
646 }
647 
648 void
650 {
651  m_cntrlSends++;
652  if (m_state != GWPSENT)
653  {
654  return;
655  }
656  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
657  bool phy1ok = IsPhy1Ok ();
658  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
659  {
660  Ptr<Packet> pkt = Create<Packet> ();
661 
662  Reservation res = m_resList.back ();
663  m_resList.pop_back ();
664  res.AddTimestamp (Simulator::Now ());
665  res.IncrementRetry ();
666 
667  pkt->AddHeader (CreateRtsHeader (res));
669 
671  m_resList.push_back (res);
672  }
674  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
675  double timeout = m_ev->GetValue ();
677 }
678 
679 
680 void
682 {
683  m_cntrlSends++;
684  if (m_state == RTSSENT)
685  {
686  return;
687  }
688 
689  NS_ASSERT (!m_pktQueue.empty ());
690 
692  res.AddTimestamp (Simulator::Now ());
693  m_frameNo++;
694  m_resList.push_back (res);
695  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
696  bool phy1ok = IsPhy1Ok ();
697  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked )
698  {
699  Ptr<Packet> pkt = Create<Packet> (0);
700  pkt->AddHeader (CreateRtsHeader (res));
703  }
704  m_state = RTSSENT;
706  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
707  double timeout = m_ev->GetValue ();
709 
710 }
711 
712 // We assume here that packet types are known at detection.
713 bool
715 {
716  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
717 
718  bool phy1ok = true;
719  if (phyDual->IsPhy1Rx ())
720  {
721  Ptr<Packet> pkt = phyDual->GetPhy1PacketRx ();
722  UanHeaderCommon ch;
723  pkt->PeekHeader (ch);
724  if (ch.GetType () == TYPE_CTS || ch.GetType () == TYPE_ACK)
725  {
726  phy1ok = false;
727  }
728  else if (ch.GetDest () == m_address)
729  {
730  phy1ok = false;
731  }
732  }
733  return phy1ok;
734 }
735 
736 void
738 {
739  m_cntrlSends++;
740 
741  if (m_state != RTSSENT)
742  {
743  return;
744  }
745  Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
746 
747  bool phy1ok = IsPhy1Ok ();
748  if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
749  {
750 
751  if (m_resList.empty ())
752  {
753  NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " tried to retry RTS with empty reservation list");
754  }
755  Ptr<Packet> pkt = Create<Packet> (0);
756 
757  Reservation res = m_resList.back ();
758  NS_ASSERT (!res.IsTransmitted ());
759  m_resList.pop_back ();
760  res.AddTimestamp (Simulator::Now ());
761  res.IncrementRetry ();
762  m_resList.push_back (res);
763  pkt->AddHeader (CreateRtsHeader (res));
766 
767  }
768  m_state = RTSSENT;
770  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
771  double timeout = m_ev->GetValue ();
773 }
774 
775 void
777 {
778  m_rtsBlocked = true;
779 }
780 
781 } // namespace ns3