OLD | NEW |
(Empty) | |
| 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 : m_state (IDLE), |
| 56 m_currentRateNum (0) |
| 57 { |
| 58 UanHeaderCommon ch; |
| 59 UanHeaderRcRts rts; |
| 60 UanHeaderRcCts cts; |
| 61 UanHeaderRcAck ack; |
| 62 UanHeaderRcCtsGlobal ctsg; |
| 63 |
| 64 m_rtsSize = ch.GetSerializedSize () + rts.GetSerializedSize (); |
| 65 m_ctsSizeN = cts.GetSerializedSize (); |
| 66 m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize (); |
| 67 m_ackSize = ch.GetSerializedSize () + ack.GetSerializedSize (); |
| 68 |
| 69 NS_LOG_DEBUG ("Gateway initialized"); |
| 70 } |
| 71 |
| 72 UanMacRcGw::~UanMacRcGw () |
| 73 { |
| 74 } |
| 75 |
| 76 void |
| 77 UanMacRcGw::DoDispose () |
| 78 { |
| 79 m_propDelay.clear (); |
| 80 std::map<UanAddress, AckData>::iterator it = m_ackData.begin (); |
| 81 for (; it != m_ackData.end (); it++) |
| 82 { |
| 83 it->second.rxFrames.clear (); |
| 84 } |
| 85 m_ackData.clear (); |
| 86 m_requests.clear (); |
| 87 m_sortedRes.clear (); |
| 88 // Object::DoDispose (); |
| 89 } |
| 90 TypeId |
| 91 UanMacRcGw::GetTypeId (void) |
| 92 { |
| 93 TypeId tid = TypeId ("ns3::UanMacRcGw") |
| 94 .SetParent<UanMac> () |
| 95 .AddConstructor<UanMacRcGw> () |
| 96 .AddAttribute ("MaxReservations", |
| 97 "Maximum number of reservations to accept per cycle", |
| 98 UintegerValue (10), |
| 99 MakeUintegerAccessor (&UanMacRcGw::m_maxRes), |
| 100 MakeUintegerChecker<uint32_t> ()) |
| 101 .AddAttribute ("NumberOfRates", |
| 102 "Number of rates per Phy layer", |
| 103 UintegerValue (1023), |
| 104 MakeUintegerAccessor (&UanMacRcGw::m_numRates), |
| 105 MakeUintegerChecker<uint32_t> ()) |
| 106 .AddAttribute ("RetryRate", |
| 107 "Number of retry rates per second at non-gateway nodes", |
| 108 DoubleValue (1 / 10.0), |
| 109 MakeDoubleAccessor (&UanMacRcGw::m_retryRate), |
| 110 MakeDoubleChecker<double> ()) |
| 111 .AddAttribute ("MaxPropDelay", |
| 112 "Maximum propagation delay between gateway and non-gateway no
des", |
| 113 TimeValue (Seconds (2)), |
| 114 MakeTimeAccessor (&UanMacRcGw::m_maxDelta), |
| 115 MakeTimeChecker ()) |
| 116 .AddAttribute ("SIFS", |
| 117 "Spacing between frames to account for timing error and proce
ssing delay", |
| 118 TimeValue (Seconds (0.2)), |
| 119 MakeTimeAccessor (&UanMacRcGw::m_sifs), |
| 120 MakeTimeChecker ()) |
| 121 .AddAttribute ("NumberOfNodes", |
| 122 "Number of non-gateway nodes in this gateway's neighborhood", |
| 123 UintegerValue (10), |
| 124 MakeUintegerAccessor (&UanMacRcGw::m_numNodes), |
| 125 MakeUintegerChecker<uint32_t> ()) |
| 126 .AddAttribute ("MinRetryRate", |
| 127 "Smallest allowed RTS retry rate", |
| 128 DoubleValue (0.01), |
| 129 MakeDoubleAccessor (&UanMacRcGw::m_minRetryRate), |
| 130 MakeDoubleChecker<double> ()) |
| 131 .AddAttribute ("RetryStep", |
| 132 "Retry rate increment", |
| 133 DoubleValue (0.01), |
| 134 MakeDoubleAccessor (&UanMacRcGw::m_retryStep), |
| 135 MakeDoubleChecker<double> ()) |
| 136 .AddAttribute ("NumberOfRetryRates", |
| 137 "Number of retry rates", |
| 138 UintegerValue (100), |
| 139 MakeUintegerAccessor (&UanMacRcGw::m_numRetryRates), |
| 140 MakeUintegerChecker<uint16_t> ()) |
| 141 .AddAttribute ("TotalRate", |
| 142 "Total available channel rate in bps (for a single channel, w
ithout splitting reservation channel)", |
| 143 UintegerValue (4096), |
| 144 MakeUintegerAccessor (&UanMacRcGw::m_totalRate), |
| 145 MakeUintegerChecker<uint32_t> ()) |
| 146 .AddAttribute ("RateStep", |
| 147 "Increments available for rate assignment in bps", |
| 148 UintegerValue (4), |
| 149 MakeUintegerAccessor (&UanMacRcGw::m_rateStep), |
| 150 MakeUintegerChecker<uint32_t> ()) |
| 151 .AddAttribute ("FrameSize", |
| 152 "Size of data frames in bytes", |
| 153 UintegerValue (1000), |
| 154 MakeUintegerAccessor (&UanMacRcGw::m_frameSize), |
| 155 MakeUintegerChecker<uint32_t> ()) |
| 156 .AddTraceSource ("RX", |
| 157 "A packet was destined for and received at this MAC layer", |
| 158 MakeTraceSourceAccessor (&UanMacRcGw::m_rxLogger)) |
| 159 .AddTraceSource ("Cycle", |
| 160 "Trace cycle statistics", |
| 161 MakeTraceSourceAccessor (&UanMacRcGw::m_cycleLogger)) |
| 162 |
| 163 ; |
| 164 |
| 165 return tid; |
| 166 } |
| 167 |
| 168 Address |
| 169 UanMacRcGw::GetAddress (void) |
| 170 { |
| 171 return m_address; |
| 172 } |
| 173 |
| 174 void |
| 175 UanMacRcGw::SetAddress (UanAddress addr) |
| 176 { |
| 177 m_address = addr; |
| 178 } |
| 179 |
| 180 bool |
| 181 UanMacRcGw::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolN
umber) |
| 182 { |
| 183 NS_LOG_WARN ("RCMAC Gateway transmission to acoustic nodes is not yet implemen
ted"); |
| 184 return false; |
| 185 } |
| 186 |
| 187 void |
| 188 UanMacRcGw::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb) |
| 189 { |
| 190 m_forwardUpCb = cb; |
| 191 } |
| 192 |
| 193 void |
| 194 UanMacRcGw::AttachPhy (Ptr<UanPhy> phy) |
| 195 { |
| 196 m_phy = phy; |
| 197 phy->SetReceiveOkCallback (MakeCallback (&UanMacRcGw::ReceivePacket, this)); |
| 198 phy->SetReceiveErrorCallback (MakeCallback (&UanMacRcGw::ReceiveError, this)); |
| 199 } |
| 200 |
| 201 void |
| 202 UanMacRcGw::ReceiveError (Ptr<Packet> pkt, double sinr) |
| 203 { |
| 204 // std::string type; |
| 205 // UanHeaderCommon ch; |
| 206 // pkt->PeekHeader(ch); |
| 207 // switch(ch.GetType()) |
| 208 // { |
| 209 // case UanMacRc::TYPE_DATA: |
| 210 // type = "DATA"; |
| 211 // break; |
| 212 // case UanMacRc::TYPE_RTS: |
| 213 // type= "RTS"; |
| 214 // break; |
| 215 // case UanMacRc::TYPE_CTS: |
| 216 // type="CTS"; |
| 217 // break; |
| 218 // case UanMacRc::TYPE_ACK: |
| 219 // type="ACK"; |
| 220 // break; |
| 221 // case UanMacRc::TYPE_GWPING: |
| 222 // type="GWPING"; |
| 223 // break; |
| 224 // default: |
| 225 // type="UNKNOWN"; |
| 226 // break; |
| 227 // } |
| 228 // NS_LOG_DEBUG(Simulator::Now().GetSeconds() << " GW Received in error: Packet
of type " << type << " from " << ch.GetSrc() << " with SINR " << sinr << " and
mode ?"); |
| 229 } |
| 230 Address |
| 231 UanMacRcGw::GetBroadcast (void) const |
| 232 { |
| 233 return UanAddress::GetBroadcast (); |
| 234 } |
| 235 |
| 236 void |
| 237 UanMacRcGw::ReceivePacket (Ptr<Packet> pkt, double sinr, UanTxMode mode) |
| 238 { |
| 239 UanHeaderCommon ch; |
| 240 pkt->PeekHeader (ch); |
| 241 |
| 242 if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ()
) |
| 243 { |
| 244 m_rxLogger (pkt, mode); |
| 245 } |
| 246 else |
| 247 { |
| 248 return; |
| 249 } |
| 250 |
| 251 pkt->RemoveHeader (ch); |
| 252 |
| 253 switch (ch.GetType ()) |
| 254 { |
| 255 case UanMacRc::TYPE_DATA: |
| 256 { |
| 257 UanHeaderRcData dh; |
| 258 pkt->RemoveHeader (dh); |
| 259 m_propDelay[ch.GetSrc ()] = dh.GetPropDelay (); |
| 260 if (m_ackData.find (ch.GetSrc ()) == m_ackData.end ()) |
| 261 { |
| 262 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GATEWAY Received
unexpected data packet"); |
| 263 } |
| 264 else |
| 265 { |
| 266 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Received data
packet from " << ch.GetSrc () << " length = " << pkt->GetSize ()); |
| 267 m_ackData[ch.GetSrc ()].rxFrames.insert (dh.GetFrameNo ()); |
| 268 } |
| 269 m_forwardUpCb (pkt, ch.GetSrc ()); |
| 270 } |
| 271 break; |
| 272 case UanMacRc::TYPE_GWPING: |
| 273 case UanMacRc::TYPE_RTS: |
| 274 if (m_state == CTSING) |
| 275 { |
| 276 return; |
| 277 } |
| 278 |
| 279 { |
| 280 UanHeaderRcRts rh; |
| 281 pkt->RemoveHeader (rh); |
| 282 |
| 283 if (m_requests.find (ch.GetSrc ()) == m_requests.end ()) |
| 284 { |
| 285 Request req; |
| 286 req.numFrames = rh.GetNoFrames (); |
| 287 req.rxTime = Simulator::Now (); |
| 288 req.frameNo = rh.GetFrameNo (); |
| 289 req.retryNo = rh.GetRetryNo (); |
| 290 req.length = rh.GetLength (); |
| 291 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW storing reserv
ation from " << ch.GetSrc () << " with length " << req.length); |
| 292 m_requests.insert (std::make_pair (ch.GetSrc (), req)); |
| 293 std::map<UanAddress, Time>::iterator it = m_propDelay.find (ch.GetSr
c ()); |
| 294 if (it == m_propDelay.end ()) |
| 295 { |
| 296 m_sortedRes.insert (std::make_pair (m_maxDelta, ch.GetSrc ())); |
| 297 } |
| 298 else |
| 299 { |
| 300 m_sortedRes.insert (std::make_pair ( (*it).second, ch.GetSrc ())
); |
| 301 } |
| 302 } |
| 303 } |
| 304 if (m_state == IDLE) |
| 305 { |
| 306 StartCycle (); |
| 307 } |
| 308 break; |
| 309 case UanMacRc::TYPE_CTS: |
| 310 NS_FATAL_ERROR ("Received CTS at GW. Currently only support single GW net
work!"); |
| 311 break; |
| 312 case UanMacRc::TYPE_ACK: |
| 313 NS_FATAL_ERROR ("Received ACK at GW. Currently only support single GW net
work!"); |
| 314 break; |
| 315 default: |
| 316 NS_FATAL_ERROR ("Received unknown packet at GW!"); |
| 317 } |
| 318 } |
| 319 |
| 320 void |
| 321 UanMacRcGw::StartCycle (void) |
| 322 { |
| 323 uint32_t numRts = m_sortedRes.size (); |
| 324 |
| 325 if (numRts) |
| 326 { |
| 327 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting non-
empty cycle"); |
| 328 } |
| 329 else |
| 330 { |
| 331 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Simulator starting EMPT
Y cycle"); |
| 332 } |
| 333 |
| 334 // Calculate dataRate |
| 335 uint32_t totalBytes = 0; |
| 336 uint32_t totalFrames = 0; |
| 337 double pDelay = 0; |
| 338 if (numRts > 0) |
| 339 { |
| 340 std::map<UanAddress, Request>::iterator rit = m_requests.begin (); |
| 341 for (; rit != m_requests.end (); rit++) |
| 342 { |
| 343 totalBytes += (*rit).second.length; |
| 344 totalFrames += (*rit).second.numFrames; |
| 345 } |
| 346 pDelay = 2 * m_sortedRes.begin ()->first.GetSeconds (); |
| 347 } |
| 348 |
| 349 |
| 350 double minRate = m_phy->GetMode (m_numRates).GetDataRateBps (); |
| 351 |
| 352 uint32_t optA = m_maxRes; |
| 353 if (m_maxRes == 0) |
| 354 { |
| 355 optA = FindOptA (); |
| 356 } |
| 357 double thAlpha = ComputeAlpha (totalFrames, totalBytes, m_numNodes, optA, pDel
ay / 2.0); |
| 358 |
| 359 double thCtlRate = m_totalRate * thAlpha; |
| 360 |
| 361 double temprate = (thCtlRate - minRate) / ((double) m_rateStep) + 0.5; |
| 362 m_currentRateNum = (uint32_t) temprate; |
| 363 if (m_currentRateNum >= m_numRates) |
| 364 { |
| 365 m_currentRateNum = m_numRates - 1; |
| 366 } |
| 367 |
| 368 NS_LOG_DEBUG ("Found theoretical alpha: " << thAlpha << " Found associated rat
e = " << thCtlRate << " Giving rate number: " << temprate); |
| 369 double thX = thAlpha * m_totalRate / (2.0 * m_numNodes * m_rtsSize * 8.0); |
| 370 |
| 371 double dataRate = m_phy->GetMode (m_currentRateNum).GetDataRateBps (); |
| 372 |
| 373 |
| 374 if (thX < m_minRetryRate) |
| 375 { |
| 376 NS_LOG_WARN ("Gateway found optimum RTS retry rate is below minimum"); |
| 377 m_currentRetryRate = 0; |
| 378 } |
| 379 else |
| 380 { |
| 381 m_currentRetryRate = (uint16_t)((thX - m_minRetryRate) / m_retryStep + 0.5
) ; |
| 382 } |
| 383 |
| 384 double actualX = m_currentRetryRate * m_retryStep + m_minRetryRate; |
| 385 |
| 386 uint32_t ctlRate = m_phy->GetMode (m_currentRateNum + m_numRates).GetDataRate
Bps (); |
| 387 |
| 388 |
| 389 double winSize = (double)(totalBytes) * 8.0 / dataRate + m_sifs.GetSeconds ()
* totalFrames + pDelay; |
| 390 if (numRts == 0) |
| 391 { |
| 392 winSize = (optA * exp (1.0) + 0.5) * 2.0 * 8.0 * m_rtsSize / (thAlpha * m_
totalRate) + 2 * m_maxDelta.GetSeconds (); |
| 393 } |
| 394 double effWinSize = winSize - m_rtsSize * 8 / ctlRate - 2 * m_maxDelta.GetSec
onds (); |
| 395 |
| 396 |
| 397 // Before fast CTS/ACK(below) |
| 398 double cycleSeconds = winSize + (totalFrames + 1.0) * m_sifs.GetSeconds () + m
_ctsSizeG * 8.0 / dataRate + (m_ctsSizeN + m_ackSize) * 8.0 * numRts / dataRate; |
| 399 |
| 400 Time ctsTxTimeG = Seconds (m_ctsSizeG * 8.0 / dataRate); |
| 401 Time ctsTxTimeTotal = Seconds (m_ctsSizeN * 8.0 * numRts / dataRate) + ctsTxTi
meG; |
| 402 if (numRts == 0) |
| 403 { |
| 404 UanHeaderRcCtsGlobal ctsg; |
| 405 ctsg.SetWindowTime (Seconds (effWinSize)); |
| 406 ctsg.SetRateNum (m_currentRateNum); |
| 407 ctsg.SetRetryRate (m_currentRetryRate); |
| 408 ctsg.SetTxTimeStamp (Simulator::Now ()); |
| 409 |
| 410 UanHeaderCommon ch (m_address, UanAddress::GetBroadcast (), UanMacRc::TYPE
_CTS); |
| 411 Ptr<Packet> p = Create<Packet> (); |
| 412 p->AddHeader (ctsg); |
| 413 p->AddHeader (ch); |
| 414 SendPacket (p, m_currentRateNum); |
| 415 |
| 416 |
| 417 Simulator::Schedule (Seconds (cycleSeconds), &UanMacRcGw::StartCycle, this
); |
| 418 m_state = INCYCLE; |
| 419 m_cycleLogger (Simulator::Now (), Seconds (0), numRts, totalBytes, effWinS
ize, ctlRate, actualX); |
| 420 return; |
| 421 } |
| 422 |
| 423 Time nextEarliest = ctsTxTimeTotal + m_sifs; |
| 424 |
| 425 m_state = CTSING; |
| 426 Simulator::Schedule (nextEarliest, &UanMacRcGw::CycleStarted, this); |
| 427 |
| 428 std::set<std::pair<Time, UanAddress> >::iterator it = m_sortedRes.begin (); |
| 429 Time minPdelay = (*it).first; |
| 430 Ptr<Packet> cts = Create<Packet> (); |
| 431 |
| 432 for (; it != m_sortedRes.end (); it++) |
| 433 { |
| 434 Request req = m_requests[(*it).second]; |
| 435 Time pdelay = (*it).first; |
| 436 |
| 437 AckData newData; |
| 438 newData.expFrames = req.numFrames; |
| 439 newData.frameNo = req.frameNo; |
| 440 UanAddress dest = (*it).second; |
| 441 m_ackData.insert (std::make_pair (dest, newData)); |
| 442 |
| 443 Time earliestArr = ctsTxTimeTotal + pdelay + pdelay + m_sifs; |
| 444 Time arrivalTime = std::max (earliestArr, nextEarliest); |
| 445 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW: Scheduling request
for prop. delay " << pdelay.GetSeconds () << " for " << (*it).second << " Earlie
st possible arrival=" << earliestArr.GetSeconds () << " Next arrival time=" <<
nextEarliest.GetSeconds ()); |
| 446 nextEarliest = arrivalTime + Seconds (req.length * 8.0 / dataRate) + Secon
ds (m_sifs.GetSeconds () * req.numFrames); |
| 447 |
| 448 UanHeaderRcCts ctsh; |
| 449 ctsh.SetAddress (dest); |
| 450 ctsh.SetRtsTimeStamp (req.rxTime); |
| 451 ctsh.SetFrameNo (req.frameNo); |
| 452 ctsh.SetRetryNo (req.retryNo); |
| 453 ctsh.SetDelayToTx (arrivalTime); |
| 454 cts->AddHeader (ctsh); |
| 455 |
| 456 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Scheduling reception
for " << (uint32_t) req.numFrames << " frames at " << (Simulator::Now () + arri
valTime).GetSeconds () << " (delaytiltx of " << arrivalTime.GetSeconds () << ")
Total length is " << req.length << " with txtime " << req.length * 8 / dataRat
e << " seconds"); |
| 457 } |
| 458 |
| 459 UanHeaderRcCtsGlobal ctsg; |
| 460 ctsg.SetRateNum (m_currentRateNum); |
| 461 ctsg.SetRetryRate (m_currentRetryRate); |
| 462 ctsg.SetWindowTime (Seconds (effWinSize)); |
| 463 ctsg.SetTxTimeStamp (Simulator::Now ()); |
| 464 UanHeaderCommon ch; |
| 465 ch.SetDest (UanAddress::GetBroadcast ()); |
| 466 ch.SetSrc (m_address); |
| 467 ch.SetType (UanMacRc::TYPE_CTS); |
| 468 cts->AddHeader (ctsg); |
| 469 cts->AddHeader (ch); |
| 470 SendPacket (cts, m_currentRateNum); |
| 471 |
| 472 m_requests.clear (); |
| 473 m_sortedRes.clear (); |
| 474 Simulator::Schedule (nextEarliest, &UanMacRcGw::EndCycle, this); |
| 475 |
| 476 |
| 477 m_cycleLogger (Simulator::Now (), minPdelay, numRts, totalBytes, cycleSeconds,
ctlRate, actualX); |
| 478 } |
| 479 |
| 480 void |
| 481 UanMacRcGw::CycleStarted () |
| 482 { |
| 483 m_state = INCYCLE; |
| 484 } |
| 485 void |
| 486 UanMacRcGw::EndCycle () |
| 487 { |
| 488 |
| 489 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW Ending cycle"); |
| 490 |
| 491 Time nextAck = Seconds (0); |
| 492 |
| 493 Time ackTime = Seconds (m_ackSize * 8.0 / m_phy->GetMode (m_currentRateNum).Ge
tDataRateBps ()); |
| 494 |
| 495 std::map<UanAddress, AckData>::iterator it = m_ackData.begin (); |
| 496 for (; it != m_ackData.end (); it++) |
| 497 { |
| 498 UanAddress dest = (*it).first; |
| 499 AckData &data = (*it).second; |
| 500 |
| 501 std::list<uint32_t> toNack; |
| 502 for (uint32_t i = 0; i < data.expFrames; i++) |
| 503 { |
| 504 if (data.rxFrames.find (i) == data.rxFrames.end ()) |
| 505 { |
| 506 toNack.push_back (i); |
| 507 } |
| 508 } |
| 509 UanHeaderCommon ch; |
| 510 ch.SetDest (dest); |
| 511 ch.SetSrc (m_address); |
| 512 ch.SetType (UanMacRc::TYPE_ACK); |
| 513 UanHeaderRcAck ah; |
| 514 ah.SetFrameNo (data.frameNo); |
| 515 std::list<uint32_t>::iterator nit = toNack.begin (); |
| 516 for (; nit != toNack.end (); nit++) |
| 517 { |
| 518 ah.AddNackedFrame (*nit); |
| 519 } |
| 520 |
| 521 Ptr<Packet> ack = Create<Packet> (); |
| 522 ack->AddHeader (ah); |
| 523 ack->AddHeader (ch); |
| 524 Simulator::Schedule (nextAck, &UanMacRcGw::SendPacket, this, ack, m_curren
tRateNum); |
| 525 nextAck = nextAck + ackTime + m_sifs; |
| 526 } |
| 527 m_ackData.clear (); |
| 528 Simulator::Schedule (nextAck, &UanMacRcGw::StartCycle, this); |
| 529 |
| 530 } |
| 531 void |
| 532 UanMacRcGw::SendPacket (Ptr<Packet> pkt, uint32_t rate) |
| 533 { |
| 534 UanHeaderCommon ch; |
| 535 pkt->PeekHeader (ch); |
| 536 std::string type; |
| 537 switch (ch.GetType ()) |
| 538 { |
| 539 case UanMacRc::TYPE_DATA: |
| 540 type = "DATA"; |
| 541 break; |
| 542 case UanMacRc::TYPE_RTS: |
| 543 type = "RTS"; |
| 544 break; |
| 545 case UanMacRc::TYPE_CTS: |
| 546 type = "CTS"; |
| 547 break; |
| 548 case UanMacRc::TYPE_ACK: |
| 549 type = "ACK"; |
| 550 break; |
| 551 case UanMacRc::TYPE_GWPING: |
| 552 type = "GWPING"; |
| 553 break; |
| 554 default: |
| 555 type = "UNKNOWN"; |
| 556 break; |
| 557 } |
| 558 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW sending " << type << " p
acket with size " << pkt->GetSize () << " to " << ch.GetDest () << " at rate " <
< rate); |
| 559 m_phy->SendPacket (pkt, rate); |
| 560 } |
| 561 |
| 562 |
| 563 double |
| 564 UanMacRcGw::ComputeAlpha (uint32_t totalFrames, uint32_t totalBytes, uint32_t n,
uint32_t a, double deltaK) |
| 565 { |
| 566 |
| 567 double alpha; |
| 568 double lrae = m_rtsSize * 8.0*a*std::exp (1.0); |
| 569 if (totalFrames == 0) |
| 570 { |
| 571 |
| 572 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)) ) / |
| 573 (2 * lrae + 8.0 * m_rtsSize - 8.0 * m_ctsSizeG); |
| 574 } |
| 575 else |
| 576 { |
| 577 double w = totalBytes * 8.0 + totalFrames*m_sifs.GetSeconds () * m_totalRa
te; |
| 578 double v = m_rtsSize * 8.0 + 2 * lrae; |
| 579 double u = (2 * m_maxDelta.GetSeconds () - 2 * deltaK) * m_totalRate; |
| 580 |
| 581 double gamma = (w - u + v) / (2 * (u - totalFrames * m_sifs.GetSeconds ()
* m_totalRate)); |
| 582 |
| 583 alpha = -gamma + sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.GetSe
conds () * m_totalRate)); |
| 584 |
| 585 if (alpha < 0 || alpha > 1) |
| 586 { |
| 587 alpha = -gamma - sqrt (gamma * gamma + v / (u - totalFrames * m_sifs.G
etSeconds () * m_totalRate)); |
| 588 } |
| 589 } |
| 590 NS_ASSERT_MSG (alpha > 0 && alpha < 1, "Error computing alpha. Alpha out of v
alid range!"); |
| 591 return alpha; |
| 592 } |
| 593 |
| 594 std::vector<double> |
| 595 UanMacRcGw::GetExpPdk (void) |
| 596 { |
| 597 uint32_t n = m_numNodes; |
| 598 std::vector<double> pds; |
| 599 std::map<UanAddress, Time>::iterator pdit = m_propDelay.begin (); |
| 600 |
| 601 for (; pdit != m_propDelay.end (); pdit++) |
| 602 { |
| 603 pds.push_back (pdit->second.GetSeconds ()); |
| 604 } |
| 605 while (pds.size () < m_numNodes) |
| 606 { |
| 607 pds.push_back (m_maxDelta.GetSeconds ()); |
| 608 } |
| 609 |
| 610 std::sort (pds.begin (), pds.end ()); |
| 611 // Find expected min. prop. delay for k nodes |
| 612 std::vector<double> exppdk; |
| 613 exppdk.push_back (m_maxDelta.GetSeconds ()); |
| 614 for (uint32_t k = 1; k <= n; k++) |
| 615 { |
| 616 uint32_t ind = CompExpMinIndex (n,k) - 1; |
| 617 exppdk.push_back (pds[ind]); |
| 618 } |
| 619 return exppdk; |
| 620 } |
| 621 |
| 622 double |
| 623 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld, std::vector<double> exppdk) |
| 624 { |
| 625 UanHeaderCommon ch; |
| 626 uint32_t lh = ch.GetSerializedSize (); |
| 627 |
| 628 uint32_t n = m_numNodes; |
| 629 double expk = n * (1 - std::exp (-((double) a) / (double) n)); |
| 630 NS_LOG_DEBUG ("expk = " << expk); |
| 631 |
| 632 // Compute expected data per cycle |
| 633 double expdata = 8 * ld * expk; |
| 634 |
| 635 // Compute expected time per cycle |
| 636 double alpha0 = ComputeAlpha (0,0,n,a,exppdk[0]); |
| 637 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_t
otalRate); |
| 638 double exptime = ComputePiK (a,n,0) * c0; |
| 639 double expp = 0; |
| 640 for (uint32_t i = 1; i <= n; i++) |
| 641 { |
| 642 expp += ComputePiK (a,n,i) * exppdk[i - 1]; |
| 643 } |
| 644 |
| 645 exptime += ComputeExpBOverA (n,a,ld + lh,exppdk) + expk * 2 * m_sifs.GetSecond
s () + m_sifs.GetSeconds () + 2 * expp; |
| 646 double s = (1.0 / m_totalRate) * expdata / exptime; |
| 647 |
| 648 return s; |
| 649 } |
| 650 |
| 651 double |
| 652 UanMacRcGw::ComputeExpS (uint32_t a, uint32_t ld) |
| 653 { |
| 654 return ComputeExpS (a, ld, GetExpPdk ()); |
| 655 } |
| 656 |
| 657 uint32_t |
| 658 UanMacRcGw::CompExpMinIndex (uint32_t n, uint32_t k) |
| 659 { |
| 660 double sum = 0; |
| 661 for (uint32_t i = 1; i <= n - k + 1; i++) |
| 662 { |
| 663 double p = (double) NchooseK (n - i, k - 1) / NchooseK (n, k); |
| 664 sum += p * i; |
| 665 } |
| 666 return (uint32_t)(sum + 0.5); |
| 667 } |
| 668 |
| 669 double |
| 670 UanMacRcGw::ComputePiK (uint32_t a, uint32_t n, uint32_t k) |
| 671 { |
| 672 double nck = (double) NchooseK (n, k); |
| 673 return nck * std::pow ( (std::exp ( (double) a / (double) n) - 1.0), (double)
k) * std::exp (-( (double) a)); |
| 674 } |
| 675 |
| 676 double |
| 677 UanMacRcGw::ComputeExpBOverA (uint32_t n, uint32_t a, uint32_t ldlh, std::vector
<double> deltaK) |
| 678 { |
| 679 |
| 680 double sum = 0; |
| 681 uint32_t lt = 8.0 * (m_ctsSizeN + ldlh + m_ackSize); |
| 682 for (uint32_t k = 1; k <= n; k++) |
| 683 { |
| 684 double num = 8.0 * m_ctsSizeG + k * lt; |
| 685 double denom = (1.0 - ComputeAlpha (k, k * ldlh, n, a, deltaK[k])) * m_tot
alRate; |
| 686 double pik = ComputePiK (a, n, k); |
| 687 double term = pik * num / denom; |
| 688 |
| 689 sum += term; |
| 690 } |
| 691 |
| 692 return sum; |
| 693 } |
| 694 |
| 695 uint64_t |
| 696 UanMacRcGw::NchooseK (uint32_t n, uint32_t k) |
| 697 { |
| 698 if (k > n) |
| 699 { |
| 700 return 0; |
| 701 } |
| 702 |
| 703 if (k > n / 2) |
| 704 { |
| 705 k = n - k; |
| 706 } |
| 707 |
| 708 double accum = 1; |
| 709 for (uint32_t i = 1; i <= k; i++) |
| 710 { |
| 711 accum = accum * (n - k + i) / i; |
| 712 } |
| 713 |
| 714 return (uint64_t)(accum + 0.5); |
| 715 |
| 716 } |
| 717 |
| 718 uint32_t |
| 719 UanMacRcGw::FindOptA (void) |
| 720 { |
| 721 double tput = 0; |
| 722 uint32_t a = 1; |
| 723 while (1) |
| 724 { |
| 725 |
| 726 double newtput = ComputeExpS (a, m_frameSize); |
| 727 if (newtput < tput) |
| 728 { |
| 729 a--; |
| 730 break; |
| 731 } |
| 732 else |
| 733 { |
| 734 tput = newtput; |
| 735 a++; |
| 736 } |
| 737 } |
| 738 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " GW: Found optimum a = " <<
a); |
| 739 return a; |
| 740 } |
| 741 } // namespace ns3 |
OLD | NEW |