21 #include "uan-mac-rc.h"
22 #include "uan-header-rc.h"
23 #include "uan-tx-mode.h"
25 #include "uan-header-common.h"
26 #include "uan-phy-dual.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"
43 NS_OBJECT_ENSURE_REGISTERED (UanMacRc);
55 : m_frameNo (frameNo),
59 uint32_t numPkts = (maxPkts) ? maxPkts : list.size ();
64 for (uint32_t i = 0; i < numPkts; i++)
66 length += list.front ().first->GetSize () +
69 m_pktList.push_back (list.front ());
75 Reservation::~Reservation ()
77 std::list<std::pair <Ptr<Packet>,
UanAddress > >::iterator it;
78 for (it = m_pktList.begin (); it != m_pktList.end (); it++)
88 return m_pktList.size ();
97 const std::list<std::pair <Ptr<Packet>,
UanAddress > > &
118 return m_timestamp[n];
124 return m_transmitted;
136 m_timestamp.push_back (t);
148 m_transmitted =
true;
151 uint32_t UanMacRc::m_cntrlSends = 0;
153 UanMacRc::UanMacRc ()
155 m_state (UNASSOCIATED),
156 m_rtsBlocked (false),
161 m_ev = CreateObject<ExponentialRandomVariable> ();
171 UanMacRc::~UanMacRc ()
188 std::list<std::pair <Ptr<Packet>,
UanAddress > >::iterator it;
189 for (it = m_pktQueue.begin (); it != m_pktQueue.end (); it++)
207 UanMacRc::GetTypeId (
void)
211 .AddConstructor<UanMacRc> ()
212 .AddAttribute (
"RetryRate",
213 "Number of retry attempts per second (of RTS/GWPING)",
215 MakeDoubleAccessor (&UanMacRc::m_retryRate),
216 MakeDoubleChecker<double> ())
217 .AddAttribute (
"MaxFrames",
218 "Maximum number of frames to include in a single RTS",
220 MakeUintegerAccessor (&UanMacRc::m_maxFrames),
221 MakeUintegerChecker<uint32_t> ())
222 .AddAttribute (
"QueueLimit",
223 "Maximum packets to queue at MAC",
225 MakeUintegerAccessor (&UanMacRc::m_queueLimit),
226 MakeUintegerChecker<uint32_t> ())
227 .AddAttribute (
"SIFS",
228 "Spacing to give between frames (this should match gateway)",
230 MakeTimeAccessor (&UanMacRc::m_sifs),
232 .AddAttribute (
"NumberOfRates",
233 "Number of rate divisions supported by each PHY",
235 MakeUintegerAccessor (&UanMacRc::m_numRates),
236 MakeUintegerChecker<uint32_t> ())
237 .AddAttribute (
"MinRetryRate",
238 "Smallest allowed RTS retry rate",
240 MakeDoubleAccessor (&UanMacRc::m_minRetryRate),
241 MakeDoubleChecker<double> ())
242 .AddAttribute (
"RetryStep",
243 "Retry rate increment",
245 MakeDoubleAccessor (&UanMacRc::m_retryStep),
246 MakeDoubleChecker<double> ())
247 .AddAttribute (
"NumberOfRetryRates",
248 "Number of retry rates",
250 MakeUintegerAccessor (&UanMacRc::m_numRetryRates),
251 MakeUintegerChecker<uint16_t> ())
252 .AddAttribute (
"MaxPropDelay",
253 "Maximum possible propagation delay to gateway",
255 MakeTimeAccessor (&UanMacRc::m_learnedProp),
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",
274 m_ev->SetStream (stream);
293 if (protocolNumber > 0)
295 NS_LOG_WARN (
"Warning: UanMacRc does not support multiple protocols. protocolNumber argument to Enqueue is being ignored");
299 if (m_pktQueue.size () >= m_queueLimit)
336 m_phy->SetReceiveOkCallback (
MakeCallback (&UanMacRc::ReceiveOkFromPhy,
this));
353 m_rxLogger (pkt, mode);
360 if (ch.
GetDest () == m_address)
365 m_forwardUpCb (pkt, ch.
GetSrc ());
375 m_assocAddr = ch.
GetSrc ();
376 UanHeaderRcCtsGlobal ctsg;
378 m_currentRate = ctsg.GetRateNum ();
379 m_retryRate = m_minRetryRate + m_retryStep*ctsg.GetRetryRate ();
381 UanHeaderRcRts rhtmp;
383 Time winDelay = ctsg.GetWindowTime ();
385 if (winDelay.GetSeconds () > 0)
387 m_rtsBlocked =
false;
400 if (ctsh.GetAddress () == m_address)
402 if (m_state == GWPSENT)
404 m_assocAddr = ch.
GetSrc ();
405 ScheduleData (ctsh, ctsg, ctsBytes);
407 else if (m_state == RTSSENT)
409 ScheduleData (ctsh, ctsg, ctsBytes);
424 if (ch.
GetDest () != m_address)
437 UanMacRc::ScheduleData (
const UanHeaderRcCts &ctsh,
const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes)
439 NS_ASSERT (m_state == RTSSENT || m_state == GWPSENT);
443 std::list<Reservation>::iterator it = m_resList.begin ();
444 for (; it != m_resList.end (); it++)
446 if (it->GetFrameNo () == ctsh.GetFrameNo ())
451 if (it == m_resList.end ())
453 NS_LOG_DEBUG (
Simulator::Now ().GetSeconds () <<
" Node " << m_address <<
" received CTS packet with no corresponding reservation!");
457 it->SetTransmitted ();
459 double currentBps = m_phy->GetMode (m_currentRate).GetDataRateBps ();
464 Time arrTime = ctsg.GetTxTimeStamp () + ctsh.GetDelayToTx ();
465 Time txTime = arrTime - m_learnedProp;
471 const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
472 std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
477 for (uint32_t i = 0; i < it->GetNoFrames (); i++, pit++)
479 Ptr<Packet> pkt = (*pit).first->
Copy ();
483 dh.SetPropDelay (m_learnedProp);
488 ch.SetDest (m_assocAddr);
489 ch.SetSrc (m_address);
492 Time eventTime = startDelay + frameDelay;
493 if (eventTime.GetSeconds () < 0)
495 if (eventTime.GetSeconds () > -0.001)
501 NS_FATAL_ERROR (
"Scheduling error resulted in very negative data transmission time! eventTime = " << eventTime.GetSeconds ());
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 ());
506 frameDelay = frameDelay + m_sifs +
Seconds (pkt->GetSize () / currentBps);
510 if (!m_pktQueue.empty ())
518 m_ev->SetAttribute (
"Mean", DoubleValue (1 / m_retryRate));
519 double timeout =
m_ev->GetValue ();
526 UanMacRc::SendPacket (Ptr<Packet> pkt, uint32_t rate)
529 pkt->PeekHeader (ch);
531 switch (ch.GetType ())
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);
558 UanMacRc::ProcessAck (Ptr<Packet> ack)
561 ack->RemoveHeader (ah);
563 std::list<Reservation>::iterator it = m_resList.begin ();
564 for (; it != m_resList.end (); it++)
566 if (it->GetFrameNo () == ah.GetFrameNo ())
571 if (it == m_resList.end ())
573 NS_LOG_DEBUG (
"In " << __func__ <<
" could not find reservation corresponding to received ACK");
576 if (!it->IsTransmitted ())
580 if (ah.GetNoNacks () > 0)
582 const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
583 std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
586 const std::set<uint8_t> &nacks = ah.GetNackedFrames ();
587 std::set<uint8_t>::iterator nit = nacks.begin ();
589 for (; nit != nacks.end (); nit++)
599 m_pktQueue.push_front (*pit);
606 m_resList.erase (it);
610 UanMacRc::CreateRtsHeader (
const Reservation &res)
612 UanHeaderRcRts rh = UanHeaderRcRts ();
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 ());
623 UanMacRc::Associate (
void)
627 Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
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)
635 Ptr<Packet> pkt = Create<Packet> (0);
636 pkt->AddHeader (CreateRtsHeader (res));
639 SendPacket (pkt,m_currentRate + m_numRates);
643 m_ev->SetAttribute (
"Mean", DoubleValue (1 / m_retryRate));
644 double timeout =
m_ev->GetValue ();
649 UanMacRc::AssociateTimeout ()
652 if (m_state != GWPSENT)
656 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
657 bool phy1ok = IsPhy1Ok ();
658 if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
660 Ptr<Packet> pkt = Create<Packet> ();
662 Reservation res = m_resList.back ();
663 m_resList.pop_back ();
665 res.IncrementRetry ();
667 pkt->AddHeader (CreateRtsHeader (res));
670 SendPacket (pkt,m_currentRate + m_numRates);
671 m_resList.push_back (res);
674 m_ev->SetAttribute (
"Mean", DoubleValue (1 / m_retryRate));
675 double timeout =
m_ev->GetValue ();
681 UanMacRc::SendRts (
void)
684 if (m_state == RTSSENT)
691 Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
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 )
699 Ptr<Packet> pkt = Create<Packet> (0);
700 pkt->AddHeader (CreateRtsHeader (res));
702 SendPacket (pkt,m_currentRate + m_numRates);
706 m_ev->SetAttribute (
"Mean", DoubleValue (1 / m_retryRate));
707 double timeout =
m_ev->GetValue ();
714 UanMacRc::IsPhy1Ok ()
716 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
719 if (phyDual->IsPhy1Rx ())
721 Ptr<Packet> pkt = phyDual->GetPhy1PacketRx ();
723 pkt->PeekHeader (ch);
724 if (ch.GetType () == TYPE_CTS || ch.GetType () == TYPE_ACK)
728 else if (ch.GetDest () == m_address)
737 UanMacRc::RtsTimeout (
void)
741 if (m_state != RTSSENT)
745 Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
747 bool phy1ok = IsPhy1Ok ();
748 if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
751 if (m_resList.empty ())
755 Ptr<Packet> pkt = Create<Packet> (0);
757 Reservation res = m_resList.back ();
759 m_resList.pop_back ();
761 res.IncrementRetry ();
762 m_resList.push_back (res);
763 pkt->AddHeader (CreateRtsHeader (res));
765 SendPacket (pkt,m_currentRate + m_numRates);
770 m_ev->SetAttribute (
"Mean", DoubleValue (1 / m_retryRate));
771 double timeout =
m_ev->GetValue ();
776 UanMacRc::BlockRtsing (
void)
uint32_t RemoveHeader(Header &header)
#define NS_LOG_FUNCTION(parameters)
void AddTimestamp(Time t)
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
uint32_t GetSize(void) const
virtual void DoDispose(void)
bool IsRunning(void) const
virtual Address GetAddress(void)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
#define NS_FATAL_ERROR(msg)
fatal error handling
a polymophic address class
virtual Address GetBroadcast(void) const
uint32_t GetNoFrames() const
void SetTransmitted(bool t=true)
Sets reservation transmitted state.
double GetSeconds(void) const
Virtual base class for all UAN MAC protocols.
Reservation()
Create empty object with default values.
uint8_t GetRetryNo() const
hold objects of type ns3::Time
virtual void SetForwardUpCb(Callback< void, Ptr< Packet >, const UanAddress & > cb)
static UanAddress ConvertFrom(const Address &address)
Hold an unsigned integer type.
Abstraction of packet modulation information.
bool IsTransmitted() const
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Ptr< ExponentialRandomVariable > m_ev
Provides exponential random variables.
static UanAddress GetBroadcast(void)
void SetFrameNo(uint8_t fn)
Ptr< Packet > Copy(void) const
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
const std::list< std::pair< Ptr< Packet >, UanAddress > > & GetPktList(void) const
int64_t AssignStreams(int64_t stream)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
virtual void SetAddress(UanAddress addr)
virtual void AttachPhy(Ptr< UanPhy > phy)
uint32_t GetLength() const
#define NS_LOG_DEBUG(msg)
uint8_t GetFrameNo() const
Hold an floating point type.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
void IncrementRetry()
Increments retry count by 1.
void AddHeader(const Header &header)
Time GetTimestamp(uint8_t n) const
virtual bool Enqueue(Ptr< Packet > pkt, const Address &dest, uint16_t protocolNumber)