A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
uan-mac-rc-gw.cc
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-gw.h"
22 #include "uan-mac-rc.h"
23 #include "uan-header-common.h"
24 #include "uan-header-rc.h"
25 #include "uan-phy.h"
26 #include "uan-tx-mode.h"
27 
28 #include "ns3/assert.h"
29 #include "ns3/log.h"
30 #include "ns3/trace-source-accessor.h"
31 #include "ns3/nstime.h"
32 #include "ns3/double.h"
33 #include "ns3/uinteger.h"
34 
35 #include <utility>
36 #include <set>
37 #include <map>
38 #include <vector>
39 #include <algorithm>
40 
41 NS_LOG_COMPONENT_DEFINE ("UanMacRcGw");
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (UanMacRcGw);
46 
47 bool
48 operator < (UanAddress &a, UanAddress &b)
49 {
50  return a.GetAsInt () < b.GetAsInt ();
51 }
52 
53 
54 UanMacRcGw::UanMacRcGw ()
55  : UanMac (),
56  m_state (IDLE),
57  m_currentRateNum (0),
58  m_cleared (false)
59 {
60  UanHeaderCommon ch;
61  UanHeaderRcRts rts;
62  UanHeaderRcCts cts;
63  UanHeaderRcAck ack;
64  UanHeaderRcCtsGlobal ctsg;
65 
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 ();
70 
71  NS_LOG_DEBUG ("Gateway initialized");
72 }
73 
74 UanMacRcGw::~UanMacRcGw ()
75 {
76 }
77 
78 void
79 UanMacRcGw::Clear ()
80 {
81  if (m_cleared)
82  {
83  return;
84  }
85  m_cleared = true;
86  if (m_phy)
87  {
88  m_phy->Clear ();
89  m_phy = 0;
90  }
91  m_propDelay.clear ();
92  std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
93  for (; it != m_ackData.end (); it++)
94  {
95  it->second.rxFrames.clear ();
96  }
97  m_ackData.clear ();
98  m_requests.clear ();
99  m_sortedRes.clear ();
100 }
101 
102 void
103 UanMacRcGw::DoDispose ()
104 {
105  Clear ();
106  UanMac::DoDispose ();
107 }
108 TypeId
109 UanMacRcGw::GetTypeId (void)
110 {
111  static TypeId tid = TypeId ("ns3::UanMacRcGw")
112  .SetParent<UanMac> ()
113  .AddConstructor<UanMacRcGw> ()
114  .AddAttribute ("MaxReservations",
115  "Maximum number of reservations to accept per cycle",
116  UintegerValue (10),
117  MakeUintegerAccessor (&UanMacRcGw::m_maxRes),
118  MakeUintegerChecker<uint32_t> ())
119  .AddAttribute ("NumberOfRates",
120  "Number of rates per Phy layer",
121  UintegerValue (1023),
122  MakeUintegerAccessor (&UanMacRcGw::m_numRates),
123  MakeUintegerChecker<uint32_t> ())
124  .AddAttribute ("RetryRate",
125  "Number of retry rates per second at non-gateway nodes",
126  DoubleValue (1 / 10.0),
127  MakeDoubleAccessor (&UanMacRcGw::m_retryRate),
128  MakeDoubleChecker<double> ())
129  .AddAttribute ("MaxPropDelay",
130  "Maximum propagation delay between gateway and non-gateway nodes",
131  TimeValue (Seconds (2)),
132  MakeTimeAccessor (&UanMacRcGw::m_maxDelta),
133  MakeTimeChecker ())
134  .AddAttribute ("SIFS",
135  "Spacing between frames to account for timing error and processing delay",
136  TimeValue (Seconds (0.2)),
137  MakeTimeAccessor (&UanMacRcGw::m_sifs),
138  MakeTimeChecker ())
139  .AddAttribute ("NumberOfNodes",
140  "Number of non-gateway nodes in this gateway's neighborhood",
141  UintegerValue (10),
142  MakeUintegerAccessor (&UanMacRcGw::m_numNodes),
143  MakeUintegerChecker<uint32_t> ())
144  .AddAttribute ("MinRetryRate",
145  "Smallest allowed RTS retry rate",
146  DoubleValue (0.01),
147  MakeDoubleAccessor (&UanMacRcGw::m_minRetryRate),
148  MakeDoubleChecker<double> ())
149  .AddAttribute ("RetryStep",
150  "Retry rate increment",
151  DoubleValue (0.01),
152  MakeDoubleAccessor (&UanMacRcGw::m_retryStep),
153  MakeDoubleChecker<double> ())
154  .AddAttribute ("NumberOfRetryRates",
155  "Number of retry rates",
156  UintegerValue (100),
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)",
161  UintegerValue (4096),
162  MakeUintegerAccessor (&UanMacRcGw::m_totalRate),
163  MakeUintegerChecker<uint32_t> ())
164  .AddAttribute ("RateStep",
165  "Increments available for rate assignment in bps",
166  UintegerValue (4),
167  MakeUintegerAccessor (&UanMacRcGw::m_rateStep),
168  MakeUintegerChecker<uint32_t> ())
169  .AddAttribute ("FrameSize",
170  "Size of data frames in bytes",
171  UintegerValue (1000),
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))
180 
181  ;
182 
183  return tid;
184 }
185 
186 Address
187 UanMacRcGw::GetAddress (void)
188 {
189  return m_address;
190 }
191 
192 void
193 UanMacRcGw::SetAddress (UanAddress addr)
194 {
195  m_address = addr;
196 }
197 
198 bool
199 UanMacRcGw::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
200 {
201  NS_LOG_WARN ("RCMAC Gateway transmission to acoustic nodes is not yet implemented");
202  return false;
203 }
204 
205 void
206 UanMacRcGw::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
207 {
208  m_forwardUpCb = cb;
209 }
210 
211 void
212 UanMacRcGw::AttachPhy (Ptr<UanPhy> phy)
213 {
214  m_phy = phy;
215  phy->SetReceiveOkCallback (MakeCallback (&UanMacRcGw::ReceivePacket, this));
216  phy->SetReceiveErrorCallback (MakeCallback (&UanMacRcGw::ReceiveError, this));
217 }
218 
219 void
220 UanMacRcGw::ReceiveError (Ptr<Packet> pkt, double sinr)
221 {
222 }
223 
224 Address
225 UanMacRcGw::GetBroadcast (void) const
226 {
227  return UanAddress::GetBroadcast ();
228 }
229 
230 void
231 UanMacRcGw::ReceivePacket (Ptr<Packet> pkt, double sinr, UanTxMode mode)
232 {
233  UanHeaderCommon ch;
234  pkt->PeekHeader (ch);
235 
236  if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ())
237  {
238  m_rxLogger (pkt, mode);
239  }
240  else
241  {
242  return;
243  }
244 
245  pkt->RemoveHeader (ch);
246 
247  switch (ch.GetType ())
248  {
249  case UanMacRc::TYPE_DATA:
250  {
251  UanHeaderRcData dh;
252  pkt->RemoveHeader (dh);
253  m_propDelay[ch.GetSrc ()] = dh.GetPropDelay ();
254  if (m_ackData.find (ch.GetSrc ()) == m_ackData.end ())
255  {
256  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GATEWAY Received unexpected data packet");
257  }
258  else
259  {
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 ());
262  }
263  m_forwardUpCb (pkt, ch.GetSrc ());
264  }
265  break;
266  case UanMacRc::TYPE_GWPING:
267  case UanMacRc::TYPE_RTS:
268  if (m_state == CTSING)
269  {
270  return;
271  }
272 
273  {
274  UanHeaderRcRts rh;
275  pkt->RemoveHeader (rh);
276 
277  if (m_requests.find (ch.GetSrc ()) == m_requests.end ())
278  {
279  Request req;
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 ())
289  {
290  m_sortedRes.insert (std::make_pair (m_maxDelta, ch.GetSrc ()));
291  }
292  else
293  {
294  m_sortedRes.insert (std::make_pair ( (*it).second, ch.GetSrc ()));
295  }
296  }
297  }
298  if (m_state == IDLE)
299  {
300  StartCycle ();
301  }
302  break;
303  case UanMacRc::TYPE_CTS:
304  NS_FATAL_ERROR ("Received CTS at GW. Currently only support single GW network!");
305  break;
306  case UanMacRc::TYPE_ACK:
307  NS_FATAL_ERROR ("Received ACK at GW. Currently only support single GW network!");
308  break;
309  default:
310  NS_FATAL_ERROR ("Received unknown packet at GW!");
311  }
312 }
313 
314 void
315 UanMacRcGw::StartCycle (void)
316 {
317  uint32_t numRts = m_sortedRes.size ();
318 
319  if (numRts)
320  {
321  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting non-empty cycle");
322  }
323  else
324  {
325  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting EMPTY cycle");
326  }
327 
328  // Calculate dataRate
329  uint32_t totalBytes = 0;
330  uint32_t totalFrames = 0;
331  double pDelay = 0;
332  if (numRts > 0)
333  {
334  std::map<UanAddress, Request>::iterator rit = m_requests.begin ();
335  for (; rit != m_requests.end (); rit++)
336  {
337  totalBytes += (*rit).second.length;
338  totalFrames += (*rit).second.numFrames;
339  }
340  pDelay = 2 * m_sortedRes.begin ()->first.GetSeconds ();
341  }
342 
343 
344  double minRate = m_phy->GetMode (m_numRates).GetDataRateBps ();
345 
346  uint32_t optA = m_maxRes;
347  if (m_maxRes == 0)
348  {
349  optA = FindOptA ();
350  }
351  double thAlpha = ComputeAlpha (totalFrames, totalBytes, m_numNodes, optA, pDelay / 2.0);
352 
353  double thCtlRate = m_totalRate * thAlpha;
354 
355  double temprate = (thCtlRate - minRate) / ((double) m_rateStep) + 0.5;
356  m_currentRateNum = (uint32_t) temprate;
357  if (m_currentRateNum >= m_numRates)
358  {
359  m_currentRateNum = m_numRates - 1;
360  }
361 
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);
364 
365  double dataRate = m_phy->GetMode (m_currentRateNum).GetDataRateBps ();
366 
367 
368  if (thX < m_minRetryRate)
369  {
370  NS_LOG_WARN ("Gateway found optimum RTS retry rate is below minimum");
371  m_currentRetryRate = 0;
372  }
373  else
374  {
375  m_currentRetryRate = (uint16_t)((thX - m_minRetryRate) / m_retryStep + 0.5);
376  }
377 
378  double actualX = m_currentRetryRate * m_retryStep + m_minRetryRate;
379 
380  uint32_t ctlRate = m_phy->GetMode (m_currentRateNum + m_numRates).GetDataRateBps ();
381 
382 
383  double winSize = (double)(totalBytes) * 8.0 / dataRate + m_sifs.GetSeconds () * totalFrames + pDelay;
384  if (numRts == 0)
385  {
386  winSize = (optA * std::exp (1.0) + 0.5) * 2.0 * 8.0 * m_rtsSize / (thAlpha * m_totalRate) + 2 * m_maxDelta.GetSeconds ();
387  }
388  double effWinSize = winSize - m_rtsSize * 8 / ctlRate - 2 * m_maxDelta.GetSeconds ();
389 
390 
391  // Before fast CTS/ACK(below)
392  double cycleSeconds = winSize + (totalFrames + 1.0) * m_sifs.GetSeconds () + m_ctsSizeG * 8.0 / dataRate + (m_ctsSizeN + m_ackSize) * 8.0 * numRts / dataRate;
393 
394  Time ctsTxTimeG = Seconds (m_ctsSizeG * 8.0 / dataRate);
395  Time ctsTxTimeTotal = Seconds (m_ctsSizeN * 8.0 * numRts / dataRate) + ctsTxTimeG;
396  if (numRts == 0)
397  {
398  UanHeaderRcCtsGlobal ctsg;
399  ctsg.SetWindowTime (Seconds (effWinSize));
400  ctsg.SetRateNum (m_currentRateNum);
401  ctsg.SetRetryRate (m_currentRetryRate);
402  ctsg.SetTxTimeStamp (Simulator::Now ());
403 
404  UanHeaderCommon ch (m_address, UanAddress::GetBroadcast (), UanMacRc::TYPE_CTS);
405  Ptr<Packet> p = Create<Packet> ();
406  p->AddHeader (ctsg);
407  p->AddHeader (ch);
408  SendPacket (p, m_currentRateNum);
409 
410 
411  Simulator::Schedule (Seconds (cycleSeconds), &UanMacRcGw::StartCycle, this);
412  m_state = INCYCLE;
413  m_cycleLogger (Simulator::Now (), Seconds (0), numRts, totalBytes, effWinSize, ctlRate, actualX);
414  return;
415  }
416 
417  Time nextEarliest = ctsTxTimeTotal + m_sifs;
418 
419  m_state = CTSING;
420  Simulator::Schedule (nextEarliest, &UanMacRcGw::CycleStarted, this);
421 
422  std::set<std::pair<Time, UanAddress> >::iterator it = m_sortedRes.begin ();
423  Time minPdelay = (*it).first;
424  Ptr<Packet> cts = Create<Packet> ();
425 
426  for (; it != m_sortedRes.end (); it++)
427  {
428  Request req = m_requests[(*it).second];
429  Time pdelay = (*it).first;
430 
431  AckData newData;
432  newData.expFrames = req.numFrames;
433  newData.frameNo = req.frameNo;
434  UanAddress dest = (*it).second;
435  m_ackData.insert (std::make_pair (dest, newData));
436 
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);
441 
442  UanHeaderRcCts ctsh;
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);
449 
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");
451  }
452 
453  UanHeaderRcCtsGlobal ctsg;
454  ctsg.SetRateNum (m_currentRateNum);
455  ctsg.SetRetryRate (m_currentRetryRate);
456  ctsg.SetWindowTime (Seconds (effWinSize));
457  ctsg.SetTxTimeStamp (Simulator::Now ());
458  UanHeaderCommon ch;
459  ch.SetDest (UanAddress::GetBroadcast ());
460  ch.SetSrc (m_address);
461  ch.SetType (UanMacRc::TYPE_CTS);
462  cts->AddHeader (ctsg);
463  cts->AddHeader (ch);
464  SendPacket (cts, m_currentRateNum);
465 
466  m_requests.clear ();
467  m_sortedRes.clear ();
468  Simulator::Schedule (nextEarliest, &UanMacRcGw::EndCycle, this);
469 
470 
471  m_cycleLogger (Simulator::Now (), minPdelay, numRts, totalBytes, cycleSeconds, ctlRate, actualX);
472 }
473 
474 void
475 UanMacRcGw::CycleStarted ()
476 {
477  m_state = INCYCLE;
478 }
479 void
480 UanMacRcGw::EndCycle ()
481 {
482 
483  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Ending cycle");
484 
485  Time nextAck = Seconds (0);
486 
487  Time ackTime = Seconds (m_ackSize * 8.0 / m_phy->GetMode (m_currentRateNum).GetDataRateBps ());
488 
489  std::map<UanAddress, AckData>::iterator it = m_ackData.begin ();
490  for (; it != m_ackData.end (); it++)
491  {
492  UanAddress dest = (*it).first;
493  AckData &data = (*it).second;
494 
495  std::list<uint32_t> toNack;
496  for (uint32_t i = 0; i < data.expFrames; i++)
497  {
498  if (data.rxFrames.find (i) == data.rxFrames.end ())
499  {
500  toNack.push_back (i);
501  }
502  }
503  UanHeaderCommon ch;
504  ch.SetDest (dest);
505  ch.SetSrc (m_address);
506  ch.SetType (UanMacRc::TYPE_ACK);
507  UanHeaderRcAck ah;
508  ah.SetFrameNo (data.frameNo);
509  std::list<uint32_t>::iterator nit = toNack.begin ();
510  for (; nit != toNack.end (); nit++)
511  {
512  ah.AddNackedFrame (*nit);
513  }
514 
515  Ptr<Packet> ack = Create<Packet> ();
516  ack->AddHeader (ah);
517  ack->AddHeader (ch);
518  Simulator::Schedule (nextAck, &UanMacRcGw::SendPacket, this, ack, m_currentRateNum);
519  nextAck = nextAck + ackTime + m_sifs;
520  }
521  m_ackData.clear ();
522  Simulator::Schedule (nextAck, &UanMacRcGw::StartCycle, this);
523 
524 }
525 void
526 UanMacRcGw::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 UanMacRc::TYPE_DATA:
534  type = "DATA";
535  break;
536  case UanMacRc::TYPE_RTS:
537  type = "RTS";
538  break;
539  case UanMacRc::TYPE_CTS:
540  type = "CTS";
541  break;
542  case UanMacRc::TYPE_ACK:
543  type = "ACK";
544  break;
545  case UanMacRc::TYPE_GWPING:
546  type = "GWPING";
547  break;
548  default:
549  type = "UNKNOWN";
550  break;
551  }
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);
554 }
555 
556 
557 double
558 UanMacRcGw::ComputeAlpha (uint32_t totalFrames, uint32_t totalBytes, uint32_t n, uint32_t a, double deltaK)
559 {
560 
561  double alpha;
562  double lrae = m_rtsSize * 8.0 * a * std::exp (1.0);
563  if (totalFrames == 0)
564  {
565 
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);
568  }
569  else
570  {
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;
574 
575  double gamma = (w - u + v) / (2 * (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
576 
577  alpha = -gamma + std::sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
578 
579  if (alpha < 0 || alpha > 1)
580  {
581  alpha = -gamma - std::sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSeconds () * m_totalRate));
582  }
583  }
584  NS_ASSERT_MSG (alpha > 0 && alpha < 1, "Error computing alpha. Alpha out of valid range!");
585  return alpha;
586 }
587 
588 std::vector<double>
589 UanMacRcGw::GetExpPdk (void)
590 {
591  uint32_t n = m_numNodes;
592  std::vector<double> pds;
593  std::map<UanAddress, Time>::iterator pdit = m_propDelay.begin ();
594 
595  for (; pdit != m_propDelay.end (); pdit++)
596  {
597  pds.push_back (pdit->second.GetSeconds ());
598  }
599  while (pds.size () < m_numNodes)
600  {
601  pds.push_back (m_maxDelta.GetSeconds ());
602  }
603 
604  std::sort (pds.begin (), pds.end ());
605  // Find expected min. prop. delay for k nodes
606  std::vector<double> exppdk;
607  exppdk.push_back (m_maxDelta.GetSeconds ());
608  for (uint32_t k = 1; k <= n; k++)
609  {
610  uint32_t ind = CompExpMinIndex (n,k) - 1;
611  exppdk.push_back (pds[ind]);
612  }
613  return exppdk;
614 }
615 
616 double
617 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld, std::vector<double> exppdk)
618 {
619  UanHeaderCommon ch;
620  uint32_t lh = ch.GetSerializedSize ();
621 
622  uint32_t n = m_numNodes;
623  double expk = n * (1 - std::exp (-((double) a) / (double) n));
624  NS_LOG_DEBUG ("expk = " << expk);
625 
626  // Compute expected data per cycle
627  double expdata = 8 * ld * expk;
628 
629  // Compute expected time per cycle
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;
633  double expp = 0;
634  for (uint32_t i = 1; i <= n; i++)
635  {
636  expp += ComputePiK (a,n,i) * exppdk[i - 1];
637  }
638 
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;
641 
642  return s;
643 }
644 
645 double
646 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld)
647 {
648  return ComputeExpS (a, ld, GetExpPdk ());
649 }
650 
651 uint32_t
652 UanMacRcGw::CompExpMinIndex (uint32_t n, uint32_t k)
653 {
654  double sum = 0;
655  for (uint32_t i = 1; i <= n - k + 1; i++)
656  {
657  double p = (double) NchooseK (n - i, k - 1) / NchooseK (n, k);
658  sum += p * i;
659  }
660  return (uint32_t)(sum + 0.5);
661 }
662 
663 double
664 UanMacRcGw::ComputePiK (uint32_t a, uint32_t n, uint32_t k)
665 {
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));
668 }
669 
670 double
671 UanMacRcGw::ComputeExpBOverA (uint32_t n, uint32_t a, uint32_t ldlh, std::vector<double> deltaK)
672 {
673 
674  double sum = 0;
675  uint32_t lt = 8 * (m_ctsSizeN + ldlh + m_ackSize);
676  for (uint32_t k = 1; k <= n; k++)
677  {
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;
682 
683  sum += term;
684  }
685 
686  return sum;
687 }
688 
689 uint64_t
690 UanMacRcGw::NchooseK (uint32_t n, uint32_t k)
691 {
692  if (k > n)
693  {
694  return 0;
695  }
696 
697  if (k > n / 2)
698  {
699  k = n - k;
700  }
701 
702  double accum = 1;
703  for (uint32_t i = 1; i <= k; i++)
704  {
705  accum = accum * (n - k + i) / i;
706  }
707 
708  return (uint64_t)(accum + 0.5);
709 
710 }
711 
712 uint32_t
713 UanMacRcGw::FindOptA (void)
714 {
715  double tput = 0;
716  uint32_t a = 1;
717  while (1)
718  {
719 
720  double newtput = ComputeExpS (a, m_frameSize);
721  if (newtput < tput)
722  {
723  a--;
724  break;
725  }
726  else
727  {
728  tput = newtput;
729  a++;
730  }
731  }
732  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW: Found optimum a = " << a);
733  return a;
734 }
735 
736 int64_t
737 UanMacRcGw::AssignStreams (int64_t stream)
738 {
739  NS_LOG_FUNCTION (this << stream);
740  return 0;
741 }
742 
743 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Callback template class.
Definition: callback.h:369
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
uint8_t GetType(void) const
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
a polymophic address class
Definition: address.h:86
Virtual base class for all UAN MAC protocols.
Definition: uan-mac.h:47
hold objects of type ns3::Time
Definition: nstime.h:700
Hold an unsigned integer type.
Definition: uinteger.h:46
Abstraction of packet modulation information.
Definition: uan-tx-mode.h:36
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void SetDest(UanAddress dest)
uint32_t PeekHeader(Header &header) const
Definition: packet.cc:294
uint8_t GetAsInt(void) const
Definition: uan-address.cc:63
UanAddress GetDest(void) const
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
#define NS_LOG_WARN(msg)
Definition: log.h:246
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
UanAddress GetSrc(void) const
Hold an floating point type.
Definition: double.h:41
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471