PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/nsnam/ns-3-dev
C++ | 781 lines | 658 code | 100 blank | 23 comment | 81 complexity | b83d064c21483fe91e41f084b5afff97 MD5 | raw file
Possible License(s): GPL-2.0
  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. #include "uan-mac-rc.h"
  21. #include "uan-header-rc.h"
  22. #include "uan-tx-mode.h"
  23. #include "uan-phy.h"
  24. #include "uan-header-common.h"
  25. #include "uan-phy-dual.h"
  26. #include "ns3/log.h"
  27. #include "ns3/nstime.h"
  28. #include "ns3/simulator.h"
  29. #include "ns3/assert.h"
  30. #include "ns3/double.h"
  31. #include "ns3/uinteger.h"
  32. #include <list>
  33. #include <utility>
  34. namespace ns3 {
  35. NS_LOG_COMPONENT_DEFINE ("UanMacRc");
  36. NS_OBJECT_ENSURE_REGISTERED (UanMacRc);
  37. Reservation::Reservation ()
  38. : m_length (0),
  39. m_frameNo (0),
  40. m_retryNo (0),
  41. m_transmitted (false)
  42. {
  43. }
  44. Reservation::Reservation (std::list<std::pair <Ptr<Packet>, UanAddress > > &list, uint8_t frameNo, uint32_t maxPkts)
  45. : m_frameNo (frameNo),
  46. m_retryNo (0),
  47. m_transmitted (false)
  48. {
  49. uint32_t numPkts = (maxPkts) ? maxPkts : list.size ();
  50. uint32_t length = 0;
  51. UanHeaderRcData dh;
  52. UanHeaderCommon ch;
  53. for (uint32_t i = 0; i < numPkts; i++)
  54. {
  55. length += list.front ().first->GetSize () +
  56. ch.GetSerializedSize () +
  57. dh.GetSerializedSize ();
  58. m_pktList.push_back (list.front ());
  59. list.pop_front ();
  60. }
  61. m_length = length;
  62. }
  63. Reservation::~Reservation ()
  64. {
  65. std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
  66. for (it = m_pktList.begin (); it != m_pktList.end (); it++)
  67. {
  68. it->first = Ptr<Packet> ((Packet *) 0);
  69. }
  70. m_pktList.clear ();
  71. m_timestamp.clear ();
  72. }
  73. uint32_t
  74. Reservation::GetNoFrames () const
  75. {
  76. return m_pktList.size ();
  77. }
  78. uint32_t
  79. Reservation::GetLength () const
  80. {
  81. return m_length;
  82. }
  83. const std::list<std::pair <Ptr<Packet>, UanAddress > > &
  84. Reservation::GetPktList (void) const
  85. {
  86. return m_pktList;
  87. }
  88. uint8_t
  89. Reservation::GetFrameNo () const
  90. {
  91. return m_frameNo;
  92. }
  93. uint8_t
  94. Reservation::GetRetryNo () const
  95. {
  96. return m_retryNo;
  97. }
  98. Time
  99. Reservation::GetTimestamp (uint8_t n) const
  100. {
  101. return m_timestamp[n];
  102. }
  103. bool
  104. Reservation::IsTransmitted () const
  105. {
  106. return m_transmitted;
  107. }
  108. void
  109. Reservation::SetFrameNo (uint8_t fn)
  110. {
  111. m_frameNo = fn;
  112. }
  113. void
  114. Reservation::AddTimestamp (Time t)
  115. {
  116. m_timestamp.push_back (t);
  117. }
  118. void
  119. Reservation::IncrementRetry ()
  120. {
  121. m_retryNo++;
  122. }
  123. void
  124. Reservation::SetTransmitted (bool t)
  125. {
  126. m_transmitted = true;
  127. }
  128. uint32_t UanMacRc::m_cntrlSends = 0;
  129. UanMacRc::UanMacRc ()
  130. : UanMac (),
  131. m_state (UNASSOCIATED),
  132. m_rtsBlocked (false),
  133. m_currentRate (10),
  134. m_frameNo (0),
  135. m_cleared (false)
  136. {
  137. m_ev = CreateObject<ExponentialRandomVariable> ();
  138. UanHeaderCommon ch;
  139. UanHeaderRcCts ctsh;
  140. UanHeaderRcCtsGlobal ctsg;
  141. m_ctsSizeN = ctsh.GetSerializedSize ();
  142. m_ctsSizeG = ch.GetSerializedSize () + ctsg.GetSerializedSize ();
  143. }
  144. UanMacRc::~UanMacRc ()
  145. {
  146. }
  147. void
  148. UanMacRc::Clear ()
  149. {
  150. if (m_cleared)
  151. {
  152. return;
  153. }
  154. m_cleared = true;
  155. if (m_phy)
  156. {
  157. m_phy->Clear ();
  158. m_phy = 0;
  159. }
  160. std::list<std::pair <Ptr<Packet>, UanAddress > >::iterator it;
  161. for (it = m_pktQueue.begin (); it != m_pktQueue.end (); it++)
  162. {
  163. it->first = 0;
  164. }
  165. m_pktQueue.clear ();
  166. m_resList.clear ();
  167. m_startAgain.Cancel ();
  168. m_rtsEvent.Cancel ();
  169. }
  170. void
  171. UanMacRc::DoDispose ()
  172. {
  173. Clear ();
  174. UanMac::DoDispose ();
  175. }
  176. TypeId
  177. UanMacRc::GetTypeId (void)
  178. {
  179. static TypeId tid = TypeId ("ns3::UanMacRc")
  180. .SetParent<UanMac> ()
  181. .SetGroupName ("Uan")
  182. .AddConstructor<UanMacRc> ()
  183. .AddAttribute ("RetryRate",
  184. "Number of retry attempts per second (of RTS/GWPING).",
  185. DoubleValue (1 / 5.0),
  186. MakeDoubleAccessor (&UanMacRc::m_retryRate),
  187. MakeDoubleChecker<double> ())
  188. .AddAttribute ("MaxFrames",
  189. "Maximum number of frames to include in a single RTS.",
  190. UintegerValue (1),
  191. MakeUintegerAccessor (&UanMacRc::m_maxFrames),
  192. MakeUintegerChecker<uint32_t> ())
  193. .AddAttribute ("QueueLimit",
  194. "Maximum packets to queue at MAC.",
  195. UintegerValue (10),
  196. MakeUintegerAccessor (&UanMacRc::m_queueLimit),
  197. MakeUintegerChecker<uint32_t> ())
  198. .AddAttribute ("SIFS",
  199. "Spacing to give between frames (this should match gateway).",
  200. TimeValue (Seconds (0.2)),
  201. MakeTimeAccessor (&UanMacRc::m_sifs),
  202. MakeTimeChecker ())
  203. .AddAttribute ("NumberOfRates",
  204. "Number of rate divisions supported by each PHY.",
  205. UintegerValue (0),
  206. MakeUintegerAccessor (&UanMacRc::m_numRates),
  207. MakeUintegerChecker<uint32_t> ())
  208. .AddAttribute ("MinRetryRate",
  209. "Smallest allowed RTS retry rate.",
  210. DoubleValue (0.01),
  211. MakeDoubleAccessor (&UanMacRc::m_minRetryRate),
  212. MakeDoubleChecker<double> ())
  213. .AddAttribute ("RetryStep",
  214. "Retry rate increment.",
  215. DoubleValue (0.01),
  216. MakeDoubleAccessor (&UanMacRc::m_retryStep),
  217. MakeDoubleChecker<double> ())
  218. .AddAttribute ("MaxPropDelay",
  219. "Maximum possible propagation delay to gateway.",
  220. TimeValue (Seconds (2)),
  221. MakeTimeAccessor (&UanMacRc::m_learnedProp),
  222. MakeTimeChecker ())
  223. .AddTraceSource ("Enqueue",
  224. "A (data) packet arrived at MAC for transmission.",
  225. MakeTraceSourceAccessor (&UanMacRc::m_enqueueLogger),
  226. "ns3::UanMacRc::QueueTracedCallback")
  227. .AddTraceSource ("Dequeue",
  228. "A (data) packet was passed down to PHY from MAC.",
  229. MakeTraceSourceAccessor (&UanMacRc::m_dequeueLogger),
  230. "ns3::UanMacRc::QueueTracedCallback")
  231. .AddTraceSource ("RX",
  232. "A packet was destined for and received at this MAC layer.",
  233. MakeTraceSourceAccessor (&UanMacRc::m_rxLogger),
  234. "ns3::UanMac::PacketModeTracedCallback")
  235. ;
  236. return tid;
  237. }
  238. int64_t
  239. UanMacRc::AssignStreams (int64_t stream)
  240. {
  241. NS_LOG_FUNCTION (this << stream);
  242. m_ev->SetStream (stream);
  243. return 1;
  244. }
  245. Address
  246. UanMacRc::GetAddress (void)
  247. {
  248. return m_address;
  249. }
  250. void
  251. UanMacRc::SetAddress (UanAddress addr)
  252. {
  253. m_address = addr;
  254. }
  255. bool
  256. UanMacRc::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
  257. {
  258. if (protocolNumber > 0)
  259. {
  260. NS_LOG_WARN ("Warning: UanMacRc does not support multiple protocols. protocolNumber argument to Enqueue is being ignored");
  261. }
  262. if (m_pktQueue.size () >= m_queueLimit)
  263. {
  264. return false;
  265. }
  266. m_pktQueue.push_back (std::make_pair (packet, UanAddress::ConvertFrom (dest)));
  267. switch (m_state)
  268. {
  269. case UNASSOCIATED:
  270. Associate ();
  271. return true;
  272. case IDLE:
  273. if (!m_rtsEvent.IsRunning ())
  274. {
  275. SendRts ();
  276. }
  277. return true;
  278. case GWPSENT:
  279. case RTSSENT:
  280. case DATATX:
  281. return true;
  282. }
  283. return true;
  284. }
  285. void
  286. UanMacRc::SetForwardUpCb (Callback<void, Ptr<Packet>, const UanAddress&> cb)
  287. {
  288. m_forwardUpCb = cb;
  289. }
  290. void
  291. UanMacRc::AttachPhy (Ptr<UanPhy> phy)
  292. {
  293. m_phy = phy;
  294. m_phy->SetReceiveOkCallback (MakeCallback (&UanMacRc::ReceiveOkFromPhy, this));
  295. }
  296. Address
  297. UanMacRc::GetBroadcast (void) const
  298. {
  299. return UanAddress::GetBroadcast ();
  300. }
  301. void
  302. UanMacRc::ReceiveOkFromPhy (Ptr<Packet> pkt, double sinr, UanTxMode mode)
  303. {
  304. UanHeaderCommon ch;
  305. pkt->RemoveHeader (ch);
  306. if (ch.GetDest () == m_address || ch.GetDest () == UanAddress::GetBroadcast ())
  307. {
  308. m_rxLogger (pkt, mode);
  309. }
  310. switch (ch.GetType ())
  311. {
  312. case TYPE_DATA:
  313. if (ch.GetDest () == m_address)
  314. {
  315. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " UanMacRc Receiving DATA packet from PHY");
  316. UanHeaderRcData dh;
  317. pkt->RemoveHeader (dh);
  318. m_forwardUpCb (pkt, ch.GetSrc ());
  319. }
  320. break;
  321. case TYPE_RTS:
  322. // Currently don't respond to RTS packets at non-gateway nodes
  323. // (Code assumes single network neighberhood)
  324. break;
  325. case TYPE_CTS:
  326. {
  327. uint32_t ctsBytes = ch.GetSerializedSize () + pkt->GetSize ();
  328. m_assocAddr = ch.GetSrc ();
  329. UanHeaderRcCtsGlobal ctsg;
  330. pkt->RemoveHeader (ctsg);
  331. m_currentRate = ctsg.GetRateNum ();
  332. m_retryRate = m_minRetryRate + m_retryStep*ctsg.GetRetryRate ();
  333. UanHeaderRcRts rhtmp;
  334. Time winDelay = ctsg.GetWindowTime ();
  335. if (winDelay.GetSeconds () > 0)
  336. {
  337. m_rtsBlocked = false;
  338. Simulator::Schedule (winDelay, &UanMacRc::BlockRtsing, this);
  339. }
  340. else
  341. {
  342. NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received window period < 0");
  343. }
  344. UanHeaderRcCts ctsh;
  345. ctsh.SetAddress (UanAddress::GetBroadcast ());
  346. while (pkt->GetSize () > 0)
  347. {
  348. pkt->RemoveHeader (ctsh);
  349. if (ctsh.GetAddress () == m_address)
  350. {
  351. if (m_state == GWPSENT)
  352. {
  353. m_assocAddr = ch.GetSrc ();
  354. ScheduleData (ctsh, ctsg, ctsBytes);
  355. }
  356. else if (m_state == RTSSENT)
  357. {
  358. ScheduleData (ctsh, ctsg, ctsBytes);
  359. }
  360. else
  361. {
  362. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS while state != RTSSENT or GWPING");
  363. }
  364. }
  365. }
  366. }
  367. break;
  368. case TYPE_GWPING:
  369. // Do not respond to GWPINGS at non-gateway nodes
  370. break;
  371. case TYPE_ACK:
  372. m_rtsBlocked = true;
  373. if (ch.GetDest () != m_address)
  374. {
  375. return;
  376. }
  377. ProcessAck (pkt);
  378. break;
  379. default:
  380. NS_FATAL_ERROR ("Unknown packet type " << ch.GetType () << " received at node " << GetAddress ());
  381. }
  382. }
  383. void
  384. UanMacRc::ScheduleData (const UanHeaderRcCts &ctsh, const UanHeaderRcCtsGlobal &ctsg, uint32_t ctsBytes)
  385. {
  386. NS_ASSERT (m_state == RTSSENT || m_state == GWPSENT);
  387. std::list<Reservation>::iterator it = m_resList.begin ();
  388. for (; it != m_resList.end (); it++)
  389. {
  390. if (it->GetFrameNo () == ctsh.GetFrameNo ())
  391. {
  392. break;
  393. }
  394. }
  395. if (it == m_resList.end ())
  396. {
  397. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet with no corresponding reservation!");
  398. return;
  399. }
  400. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received CTS packet. Scheduling data");
  401. it->SetTransmitted ();
  402. double currentBps = m_phy->GetMode (m_currentRate).GetDataRateBps ();
  403. m_learnedProp = Simulator::Now () - ctsg.GetTxTimeStamp () - Seconds (ctsBytes * 8.0 / currentBps);
  404. Time arrTime = ctsg.GetTxTimeStamp () + ctsh.GetDelayToTx ();
  405. Time txTime = arrTime - m_learnedProp;
  406. Time startDelay = txTime - Simulator::Now ();
  407. Time frameDelay = Seconds (0);
  408. const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
  409. std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
  410. pit = l.begin ();
  411. for (uint32_t i = 0; i < it->GetNoFrames (); i++, pit++)
  412. {
  413. Ptr<Packet> pkt = (*pit).first->Copy ();
  414. UanHeaderRcData dh;
  415. dh.SetFrameNo (i);
  416. dh.SetPropDelay (m_learnedProp);
  417. pkt->AddHeader (dh);
  418. UanHeaderCommon ch;
  419. ch.SetType (TYPE_DATA);
  420. ch.SetDest (m_assocAddr);
  421. ch.SetSrc (m_address);
  422. pkt->AddHeader (ch);
  423. Time eventTime = startDelay + frameDelay;
  424. if (eventTime.GetSeconds () < 0)
  425. {
  426. if (eventTime.GetSeconds () > -0.001)
  427. {
  428. eventTime = Seconds (0);
  429. }
  430. else
  431. {
  432. NS_FATAL_ERROR ("Scheduling error resulted in very negative data transmission time! eventTime = " << eventTime.GetSeconds ());
  433. }
  434. }
  435. 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 ());
  436. Simulator::Schedule (eventTime, &UanMacRc::SendPacket, this, pkt, m_currentRate);
  437. frameDelay = frameDelay + m_sifs + Seconds (pkt->GetSize () / currentBps);
  438. }
  439. m_state = IDLE;
  440. if (!m_pktQueue.empty ())
  441. {
  442. if (m_rtsEvent.IsRunning ())
  443. {
  444. m_rtsEvent.Cancel ();
  445. }
  446. m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
  447. double timeout = m_ev->GetValue ();
  448. m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::SendRts, this);
  449. }
  450. }
  451. void
  452. UanMacRc::SendPacket (Ptr<Packet> pkt, uint32_t rate)
  453. {
  454. UanHeaderCommon ch;
  455. pkt->PeekHeader (ch);
  456. std::string type;
  457. switch (ch.GetType ())
  458. {
  459. case TYPE_DATA:
  460. type = "DATA";
  461. break;
  462. case TYPE_RTS:
  463. type = "RTS";
  464. break;
  465. case TYPE_CTS:
  466. type = "CTS";
  467. break;
  468. case TYPE_ACK:
  469. type = "ACK";
  470. break;
  471. case TYPE_GWPING:
  472. type = "GWPING";
  473. break;
  474. default:
  475. type = "UNKNOWN";
  476. break;
  477. }
  478. 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 ());
  479. m_dequeueLogger (pkt, rate);
  480. m_phy->SendPacket (pkt, rate);
  481. }
  482. void
  483. UanMacRc::ProcessAck (Ptr<Packet> ack)
  484. {
  485. UanHeaderRcAck ah;
  486. ack->RemoveHeader (ah);
  487. std::list<Reservation>::iterator it = m_resList.begin ();
  488. for (; it != m_resList.end (); it++)
  489. {
  490. if (it->GetFrameNo () == ah.GetFrameNo ())
  491. {
  492. break;
  493. }
  494. }
  495. if (it == m_resList.end ())
  496. {
  497. NS_LOG_DEBUG ("In " << __func__ << " could not find reservation corresponding to received ACK");
  498. return;
  499. }
  500. if (!it->IsTransmitted ())
  501. {
  502. return;
  503. }
  504. if (ah.GetNoNacks () > 0)
  505. {
  506. const std::list<std::pair <Ptr<Packet>, UanAddress > > l = it->GetPktList ();
  507. std::list<std::pair <Ptr<Packet>, UanAddress > >::const_iterator pit;
  508. pit = l.begin ();
  509. const std::set<uint8_t> &nacks = ah.GetNackedFrames ();
  510. std::set<uint8_t>::iterator nit = nacks.begin ();
  511. uint8_t pnum = 0;
  512. for (; nit != nacks.end (); nit++)
  513. {
  514. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " Received NACK for " << (uint32_t) *nit);
  515. while (pnum < *nit)
  516. {
  517. pit++;
  518. pnum++;
  519. }
  520. UanHeaderRcData dh;
  521. UanHeaderCommon ch;
  522. m_pktQueue.push_front (*pit);
  523. }
  524. }
  525. else
  526. {
  527. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Node " << m_address << " received ACK for all frames");
  528. }
  529. m_resList.erase (it);
  530. }
  531. UanHeaderRcRts
  532. UanMacRc::CreateRtsHeader (const Reservation &res)
  533. {
  534. UanHeaderRcRts rh = UanHeaderRcRts ();
  535. rh.SetLength (res.GetLength ());
  536. rh.SetNoFrames (res.GetNoFrames ());
  537. rh.SetTimeStamp (res.GetTimestamp (res.GetRetryNo ()));
  538. rh.SetFrameNo (res.GetFrameNo ());
  539. rh.SetRetryNo (res.GetRetryNo ());
  540. return rh;
  541. }
  542. void
  543. UanMacRc::Associate (void)
  544. {
  545. m_cntrlSends++;
  546. Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
  547. res.AddTimestamp (Simulator::Now ());
  548. m_frameNo++;
  549. m_resList.push_back (res);
  550. Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
  551. bool phy1ok = IsPhy1Ok ();
  552. if (phy1ok && !phyDual->IsPhy2Tx () & !m_rtsBlocked)
  553. {
  554. Ptr<Packet> pkt = Create<Packet> (0);
  555. pkt->AddHeader (CreateRtsHeader (res));
  556. pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
  557. NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending first GWPING " << *pkt);
  558. SendPacket (pkt,m_currentRate + m_numRates);
  559. }
  560. m_state = GWPSENT;
  561. NS_ASSERT (!m_rtsEvent.IsRunning ());
  562. m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
  563. double timeout = m_ev->GetValue ();
  564. m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
  565. }
  566. void
  567. UanMacRc::AssociateTimeout ()
  568. {
  569. m_cntrlSends++;
  570. if (m_state != GWPSENT)
  571. {
  572. return;
  573. }
  574. Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
  575. bool phy1ok = IsPhy1Ok ();
  576. if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
  577. {
  578. Ptr<Packet> pkt = Create<Packet> ();
  579. Reservation res = m_resList.back ();
  580. m_resList.pop_back ();
  581. res.AddTimestamp (Simulator::Now ());
  582. res.IncrementRetry ();
  583. pkt->AddHeader (CreateRtsHeader (res));
  584. pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_GWPING));
  585. SendPacket (pkt,m_currentRate + m_numRates);
  586. m_resList.push_back (res);
  587. }
  588. NS_ASSERT (!m_rtsEvent.IsRunning ());
  589. m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
  590. double timeout = m_ev->GetValue ();
  591. m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::AssociateTimeout, this);
  592. }
  593. void
  594. UanMacRc::SendRts (void)
  595. {
  596. m_cntrlSends++;
  597. if (m_state == RTSSENT)
  598. {
  599. return;
  600. }
  601. NS_ASSERT (!m_pktQueue.empty ());
  602. Reservation res (m_pktQueue, m_frameNo, m_maxFrames);
  603. res.AddTimestamp (Simulator::Now ());
  604. m_frameNo++;
  605. m_resList.push_back (res);
  606. Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
  607. bool phy1ok = IsPhy1Ok ();
  608. if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked )
  609. {
  610. Ptr<Packet> pkt = Create<Packet> (0);
  611. pkt->AddHeader (CreateRtsHeader (res));
  612. pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
  613. SendPacket (pkt,m_currentRate + m_numRates);
  614. }
  615. m_state = RTSSENT;
  616. NS_ASSERT (!m_rtsEvent.IsRunning ());
  617. m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
  618. double timeout = m_ev->GetValue ();
  619. m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
  620. }
  621. // We assume here that packet types are known at detection.
  622. bool
  623. UanMacRc::IsPhy1Ok ()
  624. {
  625. Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
  626. bool phy1ok = true;
  627. if (phyDual->IsPhy1Rx ())
  628. {
  629. Ptr<Packet> pkt = phyDual->GetPhy1PacketRx ();
  630. UanHeaderCommon ch;
  631. pkt->PeekHeader (ch);
  632. if (ch.GetType () == TYPE_CTS || ch.GetType () == TYPE_ACK)
  633. {
  634. phy1ok = false;
  635. }
  636. else if (ch.GetDest () == m_address)
  637. {
  638. phy1ok = false;
  639. }
  640. }
  641. return phy1ok;
  642. }
  643. void
  644. UanMacRc::RtsTimeout (void)
  645. {
  646. m_cntrlSends++;
  647. if (m_state != RTSSENT)
  648. {
  649. return;
  650. }
  651. Ptr<UanPhyDual> phyDual = m_phy->GetObject<UanPhyDual> ();
  652. bool phy1ok = IsPhy1Ok ();
  653. if (phy1ok && !phyDual->IsPhy2Tx () && !m_rtsBlocked)
  654. {
  655. if (m_resList.empty ())
  656. {
  657. NS_FATAL_ERROR (Simulator::Now ().GetSeconds () << " Node " << m_address << " tried to retry RTS with empty reservation list");
  658. }
  659. Ptr<Packet> pkt = Create<Packet> (0);
  660. Reservation res = m_resList.back ();
  661. NS_ASSERT (!res.IsTransmitted ());
  662. m_resList.pop_back ();
  663. res.AddTimestamp (Simulator::Now ());
  664. res.IncrementRetry ();
  665. m_resList.push_back (res);
  666. pkt->AddHeader (CreateRtsHeader (res));
  667. pkt->AddHeader (UanHeaderCommon (m_address, UanAddress::GetBroadcast (), (uint8_t) TYPE_RTS));
  668. SendPacket (pkt,m_currentRate + m_numRates);
  669. }
  670. m_state = RTSSENT;
  671. NS_ASSERT (!m_rtsEvent.IsRunning ());
  672. m_ev->SetAttribute ("Mean", DoubleValue (1 / m_retryRate));
  673. double timeout = m_ev->GetValue ();
  674. m_rtsEvent = Simulator::Schedule (Seconds (timeout), &UanMacRc::RtsTimeout, this);
  675. }
  676. void
  677. UanMacRc::BlockRtsing (void)
  678. {
  679. m_rtsBlocked = true;
  680. }
  681. } // namespace ns3