21 #include "uan-mac-rc-gw.h"
22 #include "uan-mac-rc.h"
23 #include "uan-header-common.h"
24 #include "uan-header-rc.h"
26 #include "uan-tx-mode.h"
28 #include "ns3/assert.h"
30 #include "ns3/trace-source-accessor.h"
31 #include "ns3/nstime.h"
32 #include "ns3/double.h"
33 #include "ns3/uinteger.h"
45 NS_OBJECT_ENSURE_REGISTERED (UanMacRcGw);
54 UanMacRcGw::UanMacRcGw ()
64 UanHeaderRcCtsGlobal ctsg;
66 m_rtsSize = ch.GetSerializedSize () + rts.GetSerializedSize ();
67 m_ctsSizeN = cts.GetSerializedSize ();
68 m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
69 m_ackSize = ch.GetSerializedSize () + ack.GetSerializedSize ();
74 UanMacRcGw::~UanMacRcGw ()
92 std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
93 for (; it != m_ackData.end (); it++)
95 it->second.rxFrames.clear ();
103 UanMacRcGw::DoDispose ()
106 UanMac::DoDispose ();
109 UanMacRcGw::GetTypeId (
void)
113 .AddConstructor<UanMacRcGw> ()
114 .AddAttribute (
"MaxReservations",
115 "Maximum number of reservations to accept per cycle",
117 MakeUintegerAccessor (&UanMacRcGw::m_maxRes),
118 MakeUintegerChecker<uint32_t> ())
119 .AddAttribute (
"NumberOfRates",
120 "Number of rates per Phy layer",
122 MakeUintegerAccessor (&UanMacRcGw::m_numRates),
123 MakeUintegerChecker<uint32_t> ())
124 .AddAttribute (
"RetryRate",
125 "Number of retry rates per second at non-gateway nodes",
127 MakeDoubleAccessor (&UanMacRcGw::m_retryRate),
128 MakeDoubleChecker<double> ())
129 .AddAttribute (
"MaxPropDelay",
130 "Maximum propagation delay between gateway and non-gateway nodes",
132 MakeTimeAccessor (&UanMacRcGw::m_maxDelta),
134 .AddAttribute (
"SIFS",
135 "Spacing between frames to account for timing error and processing delay",
137 MakeTimeAccessor (&UanMacRcGw::m_sifs),
139 .AddAttribute (
"NumberOfNodes",
140 "Number of non-gateway nodes in this gateway's neighborhood",
142 MakeUintegerAccessor (&UanMacRcGw::m_numNodes),
143 MakeUintegerChecker<uint32_t> ())
144 .AddAttribute (
"MinRetryRate",
145 "Smallest allowed RTS retry rate",
147 MakeDoubleAccessor (&UanMacRcGw::m_minRetryRate),
148 MakeDoubleChecker<double> ())
149 .AddAttribute (
"RetryStep",
150 "Retry rate increment",
152 MakeDoubleAccessor (&UanMacRcGw::m_retryStep),
153 MakeDoubleChecker<double> ())
154 .AddAttribute (
"NumberOfRetryRates",
155 "Number of retry rates",
157 MakeUintegerAccessor (&UanMacRcGw::m_numRetryRates),
158 MakeUintegerChecker<uint16_t> ())
159 .AddAttribute (
"TotalRate",
160 "Total available channel rate in bps (for a single channel, without splitting reservation channel)",
162 MakeUintegerAccessor (&UanMacRcGw::m_totalRate),
163 MakeUintegerChecker<uint32_t> ())
164 .AddAttribute (
"RateStep",
165 "Increments available for rate assignment in bps",
167 MakeUintegerAccessor (&UanMacRcGw::m_rateStep),
168 MakeUintegerChecker<uint32_t> ())
169 .AddAttribute (
"FrameSize",
170 "Size of data frames in bytes",
172 MakeUintegerAccessor (&UanMacRcGw::m_frameSize),
173 MakeUintegerChecker<uint32_t> ())
174 .AddTraceSource (
"RX",
175 "A packet was destined for and received at this MAC layer",
176 MakeTraceSourceAccessor (&UanMacRcGw::m_rxLogger))
177 .AddTraceSource (
"Cycle",
178 "Trace cycle statistics",
179 MakeTraceSourceAccessor (&UanMacRcGw::m_cycleLogger))
187 UanMacRcGw::GetAddress (
void)
201 NS_LOG_WARN (
"RCMAC Gateway transmission to acoustic nodes is not yet implemented");
215 phy->SetReceiveOkCallback (
MakeCallback (&UanMacRcGw::ReceivePacket,
this));
216 phy->SetReceiveErrorCallback (
MakeCallback (&UanMacRcGw::ReceiveError,
this));
220 UanMacRcGw::ReceiveError (
Ptr<Packet> pkt,
double sinr)
225 UanMacRcGw::GetBroadcast (
void)
const
227 return UanAddress::GetBroadcast ();
236 if (ch.
GetDest () == m_address || ch.
GetDest () == UanAddress::GetBroadcast ())
238 m_rxLogger (pkt, mode);
249 case UanMacRc::TYPE_DATA:
253 m_propDelay[ch.
GetSrc ()] = dh.GetPropDelay ();
254 if (m_ackData.find (ch.
GetSrc ()) == m_ackData.end ())
256 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GATEWAY Received unexpected data packet");
260 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW Received data packet from " << ch.
GetSrc () <<
" length = " << pkt->
GetSize ());
261 m_ackData[ch.
GetSrc ()].rxFrames.insert (dh.GetFrameNo ());
263 m_forwardUpCb (pkt, ch.
GetSrc ());
266 case UanMacRc::TYPE_GWPING:
267 case UanMacRc::TYPE_RTS:
268 if (m_state == CTSING)
277 if (m_requests.find (ch.
GetSrc ()) == m_requests.end ())
280 req.numFrames = rh.GetNoFrames ();
281 req.rxTime = Simulator::Now ();
282 req.frameNo = rh.GetFrameNo ();
283 req.retryNo = rh.GetRetryNo ();
284 req.length = rh.GetLength ();
285 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW storing reservation from " << ch.
GetSrc () <<
" with length " << req.length);
286 m_requests.insert (std::make_pair (ch.
GetSrc (), req));
287 std::map<UanAddress, Time>::iterator it = m_propDelay.find (ch.
GetSrc ());
288 if (it == m_propDelay.end ())
290 m_sortedRes.insert (std::make_pair (m_maxDelta, ch.
GetSrc ()));
294 m_sortedRes.insert (std::make_pair ( (*it).second, ch.
GetSrc ()));
303 case UanMacRc::TYPE_CTS:
304 NS_FATAL_ERROR (
"Received CTS at GW. Currently only support single GW network!");
306 case UanMacRc::TYPE_ACK:
307 NS_FATAL_ERROR (
"Received ACK at GW. Currently only support single GW network!");
315 UanMacRcGw::StartCycle (
void)
317 uint32_t numRts = m_sortedRes.size ();
321 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" Simulator starting non-empty cycle");
325 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" Simulator starting EMPTY cycle");
329 uint32_t totalBytes = 0;
330 uint32_t totalFrames = 0;
334 std::map<UanAddress, Request>::iterator rit = m_requests.begin ();
335 for (; rit != m_requests.end (); rit++)
337 totalBytes += (*rit).second.length;
338 totalFrames += (*rit).second.numFrames;
340 pDelay = 2 * m_sortedRes.begin ()->first.GetSeconds ();
344 double minRate = m_phy->GetMode (m_numRates).GetDataRateBps ();
346 uint32_t optA = m_maxRes;
351 double thAlpha = ComputeAlpha (totalFrames, totalBytes, m_numNodes, optA, pDelay / 2.0);
353 double thCtlRate = m_totalRate * thAlpha;
355 double temprate = (thCtlRate - minRate) / ((
double) m_rateStep) + 0.5;
356 m_currentRateNum = (uint32_t) temprate;
357 if (m_currentRateNum >= m_numRates)
359 m_currentRateNum = m_numRates - 1;
362 NS_LOG_DEBUG (
"Found theoretical alpha: " << thAlpha <<
" Found associated rate = " << thCtlRate <<
" Giving rate number: " << temprate);
363 double thX = thAlpha * m_totalRate / (2.0 * m_numNodes * m_rtsSize * 8.0);
365 double dataRate = m_phy->GetMode (m_currentRateNum).GetDataRateBps ();
368 if (thX < m_minRetryRate)
370 NS_LOG_WARN (
"Gateway found optimum RTS retry rate is below minimum");
371 m_currentRetryRate = 0;
375 m_currentRetryRate = (uint16_t)((thX - m_minRetryRate) / m_retryStep + 0.5);
378 double actualX = m_currentRetryRate * m_retryStep + m_minRetryRate;
380 uint32_t ctlRate = m_phy->GetMode (m_currentRateNum + m_numRates).GetDataRateBps ();
383 double winSize = (double)(totalBytes) * 8.0 / dataRate + m_sifs.GetSeconds () * totalFrames + pDelay;
386 winSize = (optA * std::exp (1.0) + 0.5) * 2.0 * 8.0 * m_rtsSize / (thAlpha * m_totalRate) + 2 * m_maxDelta.GetSeconds ();
388 double effWinSize = winSize - m_rtsSize * 8 / ctlRate - 2 * m_maxDelta.GetSeconds ();
392 double cycleSeconds = winSize + (totalFrames + 1.0) * m_sifs.GetSeconds () + m_ctsSizeG * 8.0 / dataRate + (m_ctsSizeN + m_ackSize) * 8.0 * numRts / dataRate;
394 Time ctsTxTimeG =
Seconds (m_ctsSizeG * 8.0 / dataRate);
395 Time ctsTxTimeTotal =
Seconds (m_ctsSizeN * 8.0 * numRts / dataRate) + ctsTxTimeG;
398 UanHeaderRcCtsGlobal ctsg;
399 ctsg.SetWindowTime (Seconds (effWinSize));
400 ctsg.SetRateNum (m_currentRateNum);
401 ctsg.SetRetryRate (m_currentRetryRate);
402 ctsg.SetTxTimeStamp (Simulator::Now ());
404 UanHeaderCommon ch (m_address, UanAddress::GetBroadcast (), UanMacRc::TYPE_CTS);
405 Ptr<Packet> p = Create<Packet> ();
408 SendPacket (p, m_currentRateNum);
411 Simulator::Schedule (Seconds (cycleSeconds), &UanMacRcGw::StartCycle,
this);
413 m_cycleLogger (Simulator::Now (), Seconds (0), numRts, totalBytes, effWinSize, ctlRate, actualX);
417 Time nextEarliest = ctsTxTimeTotal + m_sifs;
420 Simulator::Schedule (nextEarliest, &UanMacRcGw::CycleStarted,
this);
422 std::set<std::pair<Time, UanAddress> >::iterator it = m_sortedRes.begin ();
423 Time minPdelay = (*it).first;
424 Ptr<Packet> cts = Create<Packet> ();
426 for (; it != m_sortedRes.end (); it++)
428 Request req = m_requests[(*it).second];
429 Time pdelay = (*it).first;
432 newData.expFrames = req.numFrames;
433 newData.frameNo = req.frameNo;
434 UanAddress dest = (*it).second;
435 m_ackData.insert (std::make_pair (dest, newData));
437 Time earliestArr = ctsTxTimeTotal + pdelay + pdelay + m_sifs;
438 Time arrivalTime = std::max (earliestArr, nextEarliest);
439 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW: Scheduling request for prop. delay " << pdelay.GetSeconds () <<
" for " << (*it).second <<
" Earliest possible arrival=" << earliestArr.GetSeconds () <<
" Next arrival time=" << nextEarliest.GetSeconds ());
440 nextEarliest = arrivalTime +
Seconds (req.length * 8.0 / dataRate) +
Seconds (m_sifs.GetSeconds () * req.numFrames);
443 ctsh.SetAddress (dest);
444 ctsh.SetRtsTimeStamp (req.rxTime);
445 ctsh.SetFrameNo (req.frameNo);
446 ctsh.SetRetryNo (req.retryNo);
447 ctsh.SetDelayToTx (arrivalTime);
448 cts->AddHeader (ctsh);
450 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW Scheduling reception for " << (uint32_t) req.numFrames <<
" frames at " << (Simulator::Now () + arrivalTime).GetSeconds () <<
" (delaytiltx of " << arrivalTime.GetSeconds () <<
") Total length is " << req.length <<
" with txtime " << req.length * 8 / dataRate <<
" seconds");
453 UanHeaderRcCtsGlobal ctsg;
454 ctsg.SetRateNum (m_currentRateNum);
455 ctsg.SetRetryRate (m_currentRetryRate);
456 ctsg.SetWindowTime (Seconds (effWinSize));
457 ctsg.SetTxTimeStamp (Simulator::Now ());
459 ch.
SetDest (UanAddress::GetBroadcast ());
460 ch.SetSrc (m_address);
461 ch.SetType (UanMacRc::TYPE_CTS);
462 cts->AddHeader (ctsg);
464 SendPacket (cts, m_currentRateNum);
467 m_sortedRes.clear ();
468 Simulator::Schedule (nextEarliest, &UanMacRcGw::EndCycle,
this);
471 m_cycleLogger (Simulator::Now (), minPdelay, numRts, totalBytes, cycleSeconds, ctlRate, actualX);
475 UanMacRcGw::CycleStarted ()
480 UanMacRcGw::EndCycle ()
483 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW Ending cycle");
487 Time ackTime =
Seconds (m_ackSize * 8.0 / m_phy->GetMode (m_currentRateNum).GetDataRateBps ());
489 std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
490 for (; it != m_ackData.end (); it++)
492 UanAddress dest = (*it).first;
493 AckData &data = (*it).second;
495 std::list<uint32_t> toNack;
496 for (uint32_t i = 0; i < data.expFrames; i++)
498 if (data.rxFrames.find (i) == data.rxFrames.end ())
500 toNack.push_back (i);
505 ch.SetSrc (m_address);
506 ch.SetType (UanMacRc::TYPE_ACK);
508 ah.SetFrameNo (data.frameNo);
509 std::list<uint32_t>::iterator nit = toNack.begin ();
510 for (; nit != toNack.end (); nit++)
512 ah.AddNackedFrame (*nit);
515 Ptr<Packet> ack = Create<Packet> ();
518 Simulator::Schedule (nextAck, &UanMacRcGw::SendPacket,
this, ack, m_currentRateNum);
519 nextAck = nextAck + ackTime + m_sifs;
522 Simulator::Schedule (nextAck, &UanMacRcGw::StartCycle,
this);
526 UanMacRcGw::SendPacket (Ptr<Packet> pkt, uint32_t rate)
529 pkt->PeekHeader (ch);
531 switch (ch.GetType ())
533 case UanMacRc::TYPE_DATA:
536 case UanMacRc::TYPE_RTS:
539 case UanMacRc::TYPE_CTS:
542 case UanMacRc::TYPE_ACK:
545 case UanMacRc::TYPE_GWPING:
552 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW sending " << type <<
" packet with size " << pkt->GetSize () <<
" to " << ch.GetDest () <<
" at rate " << rate);
553 m_phy->SendPacket (pkt, rate);
558 UanMacRcGw::ComputeAlpha (uint32_t totalFrames, uint32_t totalBytes, uint32_t n, uint32_t a,
double deltaK)
562 double lrae = m_rtsSize * 8.0 * a * std::exp (1.0);
563 if (totalFrames == 0)
566 alpha = (2.0 * lrae + 8.0 * m_rtsSize - std::sqrt (m_ctsSizeG * 8.0 * 8.0 * m_rtsSize + 2 * 8.0 * m_ctsSizeG * 8.0 * m_rtsSize * a * std::exp (1.0)) ) /
567 (2 * lrae + 8.0 * m_rtsSize - 8.0 * m_ctsSizeG);
571 double w = totalBytes * 8.0 + totalFrames*m_sifs.GetSeconds () * m_totalRate;
572 double v = m_rtsSize * 8.0 + 2 * lrae;
573 double u = (2 * m_maxDelta.GetSeconds () - 2 * deltaK) * m_totalRate;
575 double gamma = (w - u + v) / (2 * (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
577 alpha = -gamma + std::sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
579 if (alpha < 0 || alpha > 1)
581 alpha = -gamma - std::sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
584 NS_ASSERT_MSG (alpha > 0 && alpha < 1,
"Error computing alpha. Alpha out of valid range!");
589 UanMacRcGw::GetExpPdk (
void)
591 uint32_t n = m_numNodes;
592 std::vector<double> pds;
593 std::map<UanAddress, Time>::iterator pdit = m_propDelay.begin ();
595 for (; pdit != m_propDelay.end (); pdit++)
597 pds.push_back (pdit->second.GetSeconds ());
599 while (pds.size () < m_numNodes)
601 pds.push_back (m_maxDelta.GetSeconds ());
604 std::sort (pds.begin (), pds.end ());
606 std::vector<double> exppdk;
607 exppdk.push_back (m_maxDelta.GetSeconds ());
608 for (uint32_t k = 1; k <= n; k++)
610 uint32_t ind = CompExpMinIndex (n,k) - 1;
611 exppdk.push_back (pds[ind]);
617 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld, std::vector<double> exppdk)
620 uint32_t lh = ch.GetSerializedSize ();
622 uint32_t n = m_numNodes;
623 double expk = n * (1 - std::exp (-((
double) a) / (
double) n));
627 double expdata = 8 * ld * expk;
630 double alpha0 = ComputeAlpha (0,0,n,a,exppdk[0]);
631 double c0 = 8.0 * m_ctsSizeG / ( m_totalRate * (1 - alpha0)) + 2 * m_maxDelta.GetSeconds () + (a * std::exp (1.0) + 0.5) * 2 * m_rtsSize * 8.0 / (alpha0 * m_totalRate);
632 double exptime = ComputePiK (a,n,0) * c0;
634 for (uint32_t i = 1; i <= n; i++)
636 expp += ComputePiK (a,n,i) * exppdk[i - 1];
639 exptime += ComputeExpBOverA (n,a,ld + lh,exppdk) + expk * 2 * m_sifs.GetSeconds () + m_sifs.GetSeconds () + 2 * expp;
640 double s = (1.0 / m_totalRate) * expdata / exptime;
646 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld)
648 return ComputeExpS (a, ld, GetExpPdk ());
652 UanMacRcGw::CompExpMinIndex (uint32_t n, uint32_t k)
655 for (uint32_t i = 1; i <= n - k + 1; i++)
657 double p = (double) NchooseK (n - i, k - 1) / NchooseK (n, k);
660 return (uint32_t)(sum + 0.5);
664 UanMacRcGw::ComputePiK (uint32_t a, uint32_t n, uint32_t k)
666 double nck = (double) NchooseK (n, k);
667 return nck * std::pow ( (std::exp ( (
double) a / (
double) n) - 1.0), (
double) k) * std::exp (-( (
double) a));
671 UanMacRcGw::ComputeExpBOverA (uint32_t n, uint32_t a, uint32_t ldlh, std::vector<double> deltaK)
675 uint32_t lt = 8 * (m_ctsSizeN + ldlh + m_ackSize);
676 for (uint32_t k = 1; k <= n; k++)
678 double num = 8.0 * m_ctsSizeG + k * lt;
679 double denom = (1.0 - ComputeAlpha (k, k * ldlh, n, a, deltaK[k])) * m_totalRate;
680 double pik = ComputePiK (a, n, k);
681 double term = pik * num / denom;
690 UanMacRcGw::NchooseK (uint32_t n, uint32_t k)
703 for (uint32_t i = 1; i <= k; i++)
705 accum = accum * (n - k + i) / i;
708 return (uint64_t)(accum + 0.5);
713 UanMacRcGw::FindOptA (
void)
720 double newtput = ComputeExpS (a, m_frameSize);
732 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () <<
" GW: Found optimum a = " << a);
737 UanMacRcGw::AssignStreams (int64_t stream)
uint32_t RemoveHeader(Header &header)
#define NS_LOG_FUNCTION(parameters)
#define NS_LOG_COMPONENT_DEFINE(name)
uint32_t GetSize(void) const
#define NS_FATAL_ERROR(msg)
fatal error handling
a polymophic address class
Virtual base class for all UAN MAC protocols.
hold objects of type ns3::Time
Hold an unsigned integer type.
Abstraction of packet modulation information.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
uint32_t PeekHeader(Header &header) const
uint8_t GetAsInt(void) const
#define NS_ASSERT_MSG(condition, message)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
#define NS_LOG_DEBUG(msg)
Hold an floating point type.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)