PageRenderTime 403ms CodeModel.GetById 141ms app.highlight 179ms RepoModel.GetById 63ms app.codeStats 0ms

/src/uan/model/uan-mac-rc.cc

https://bitbucket.org/klenkovic/ns-3-dev-logging-fixes
C++ | 781 lines | 659 code | 99 blank | 23 comment | 81 complexity | 8b49f163bf59510e1ee4617caca15d60 MD5 | raw 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
 40NS_LOG_COMPONENT_DEFINE ("UanMacRc");
 41namespace ns3 {
 42
 43NS_OBJECT_ENSURE_REGISTERED (UanMacRc);
 44
 45Reservation::Reservation ()
 46  : m_length (0),
 47    m_frameNo (0),
 48    m_retryNo (0),
 49    m_transmitted (false)
 50{
 51
 52}
 53
 54Reservation::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
 75Reservation::~Reservation ()
 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}
 85uint32_t
 86Reservation::GetNoFrames () const
 87{
 88  return m_pktList.size ();
 89}
 90
 91uint32_t
 92Reservation::GetLength () const
 93{
 94  return m_length;
 95}
 96
 97const std::list<std::pair <Ptr<Packet>, UanAddress > > &
 98Reservation::GetPktList (void) const
 99{
100  return m_pktList;
101}
102
103uint8_t
104Reservation::GetFrameNo () const
105{
106  return m_frameNo;
107}
108
109uint8_t
110Reservation::GetRetryNo () const
111{
112  return m_retryNo;
113}
114
115Time
116Reservation::GetTimestamp (uint8_t n) const
117{
118  return m_timestamp[n];
119}
120
121bool
122Reservation::IsTransmitted () const
123{
124  return m_transmitted;
125}
126
127void
128Reservation::SetFrameNo (uint8_t fn)
129{
130  m_frameNo = fn;
131}
132
133void
134Reservation::AddTimestamp (Time t)
135{
136  m_timestamp.push_back (t);
137}
138
139void
140Reservation::IncrementRetry ()
141{
142  m_retryNo++;
143}
144
145void
146Reservation::SetTransmitted (bool t)
147{
148  m_transmitted = true;
149}
150
151uint32_t UanMacRc::m_cntrlSends = 0;
152
153UanMacRc::UanMacRc ()
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;
165  UanHeaderRcCtsGlobal ctsg;
166
167  m_ctsSizeN = ctsh.GetSerializedSize ();
168  m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
169}
170
171UanMacRc::~UanMacRc ()
172{
173}
174
175void
176UanMacRc::Clear ()
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
199void
200UanMacRc::DoDispose ()
201{
202  Clear ();
203  UanMac::DoDispose ();
204}
205
206TypeId
207UanMacRc::GetTypeId (void)
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",
259                     MakeTraceSourceAccessor (&UanMacRc::m_enqueueLogger))
260    .AddTraceSource ("Dequeue",
261                     "A  (data) packet was passed down to PHY from MAC",
262                     MakeTraceSourceAccessor (&UanMacRc::m_dequeueLogger))
263    .AddTraceSource ("RX",
264                     "A packet was destined for and received at this MAC layer",
265                     MakeTraceSourceAccessor (&UanMacRc::m_rxLogger))
266  ;
267  return tid;
268}
269
270int64_t
271UanMacRc::AssignStreams (int64_t stream)
272{
273  NS_LOG_FUNCTION (this << stream);
274  m_ev->SetStream (stream);
275  return 1;
276}
277
278Address
279UanMacRc::GetAddress (void)
280{
281  return m_address;
282}
283
284void
285UanMacRc::SetAddress (UanAddress addr)
286{
287  m_address = addr;
288}
289
290bool
291UanMacRc::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
326void
327UanMacRc::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
328{
329  m_forwardUpCb = cb;
330}
331
332void
333UanMacRc::AttachPhy (Ptr<UanPhy> phy)
334{
335  m_phy = phy;
336  m_phy->SetReceiveOkCallback (MakeCallback (&UanMacRc::ReceiveOkFromPhy, this));
337}
338
339Address
340UanMacRc::GetBroadcast (void) const
341{
342  return UanAddress::GetBroadcast ();
343}
344
345void
346UanMacRc::ReceiveOkFromPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode)
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 ();
376        UanHeaderRcCtsGlobal ctsg;
377        pkt->RemoveHeader (ctsg);
378        m_currentRate = ctsg.GetRateNum ();
379        m_retryRate = m_minRetryRate + m_retryStep*ctsg.GetRetryRate ();
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;
396        ctsh.SetAddress (UanAddress::GetBroadcast ());
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
436void
437UanMacRc::ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes)
438{
439  NS_ASSERT (m_state == RTSSENT || m_state == GWPSENT);
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 ();
520      m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::SendRts, this);
521    }
522
523}
524
525void
526UanMacRc::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
557void
558UanMacRc::ProcessAck (Ptr<Packet> ack)
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
609UanHeaderRcRts
610UanMacRc::CreateRtsHeader (const Reservation &res)
611{
612  UanHeaderRcRts rh = UanHeaderRcRts ();
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
622void
623UanMacRc::Associate (void)
624{
625  m_cntrlSends++;
626
627  Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
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));
637      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
638      NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending first GWPING " << *pkt);
639      SendPacket (pkt,m_currentRate + m_numRates);
640    }
641  m_state = GWPSENT;
642  NS_ASSERT (!m_rtsEvent.IsRunning ());
643  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
644  double timeout = m_ev->GetValue ();
645  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
646}
647
648void
649UanMacRc::AssociateTimeout ()
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));
668      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
669
670      SendPacket (pkt,m_currentRate + m_numRates);
671      m_resList.push_back (res);
672    }
673  NS_ASSERT (!m_rtsEvent.IsRunning ());
674  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
675  double timeout = m_ev->GetValue ();
676  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
677}
678
679
680void
681UanMacRc::SendRts (void)
682{
683  m_cntrlSends++;
684  if (m_state == RTSSENT)
685    {
686      return;
687    }
688
689  NS_ASSERT (!m_pktQueue.empty ());
690
691  Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
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));
701      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
702      SendPacket (pkt,m_currentRate + m_numRates);
703    }
704  m_state = RTSSENT;
705  NS_ASSERT (!m_rtsEvent.IsRunning ());
706  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
707  double timeout = m_ev->GetValue ();
708  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
709
710}
711
712// We assume here that packet types are known at detection.
713bool
714UanMacRc::IsPhy1Ok ()
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
736void
737UanMacRc::RtsTimeout (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));
764      pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
765      SendPacket (pkt,m_currentRate + m_numRates);
766
767    }
768  m_state = RTSSENT;
769  NS_ASSERT (!m_rtsEvent.IsRunning ());
770  m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
771  double timeout = m_ev->GetValue ();
772  m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
773}
774
775void 
776UanMacRc::BlockRtsing (void)
777{
778  m_rtsBlocked = true;
779}
780
781} // namespace ns3