A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
uan-mac-cw.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-cw.h"
22 #include "ns3/attribute.h"
23 #include "ns3/uinteger.h"
24 #include "ns3/double.h"
25 #include "ns3/nstime.h"
26 #include "ns3/uan-header-common.h"
27 #include "ns3/trace-source-accessor.h"
28 #include "ns3/log.h"
29 
30 NS_LOG_COMPONENT_DEFINE ("UanMacCw");
31 
32 namespace ns3 {
33 
34 NS_OBJECT_ENSURE_REGISTERED (UanMacCw);
35 
36 UanMacCw::UanMacCw ()
37  : UanMac (),
38  m_phy (0),
39  m_pktTx (0),
40  m_state (IDLE),
41  m_cleared (false)
42 
43 {
44  m_rv = CreateObject<UniformRandomVariable> ();
45 }
46 
47 UanMacCw::~UanMacCw ()
48 {
49 }
50 
51 void
53 {
54  if (m_cleared)
55  {
56  return;
57  }
58  m_cleared = true;
59  m_pktTx = 0;
60  if (m_phy)
61  {
62  m_phy->Clear ();
63  m_phy = 0;
64  }
65  m_sendEvent.Cancel ();
66  m_txEndEvent.Cancel ();
67 }
68 
69 void
71 {
72  Clear ();
74 }
75 
76 TypeId
77 UanMacCw::GetTypeId (void)
78 {
79  static TypeId tid = TypeId ("ns3::UanMacCw")
80  .SetParent<Object> ()
81  .AddConstructor<UanMacCw> ()
82  .AddAttribute ("CW",
83  "The MAC parameter CW",
84  UintegerValue (10),
85  MakeUintegerAccessor (&UanMacCw::m_cw),
86  MakeUintegerChecker<uint32_t> ())
87  .AddAttribute ("SlotTime",
88  "Time slot duration for MAC backoff",
89  TimeValue (MilliSeconds (20)),
90  MakeTimeAccessor (&UanMacCw::m_slotTime),
91  MakeTimeChecker ())
92  .AddTraceSource ("Enqueue",
93  "A packet arrived at the MAC for transmission",
94  MakeTraceSourceAccessor (&UanMacCw::m_enqueueLogger))
95  .AddTraceSource ("Dequeue",
96  "A was passed down to the PHY from the MAC",
97  MakeTraceSourceAccessor (&UanMacCw::m_dequeueLogger))
98  .AddTraceSource ("RX",
99  "A packet was destined for this MAC and was received",
100  MakeTraceSourceAccessor (&UanMacCw::m_rxLogger))
101 
102  ;
103  return tid;
104 }
105 
106 Address
108 {
109  return this->m_address;
110 }
111 
112 void
114 {
115  m_address = addr;
116 }
117 
118 bool
119 UanMacCw::Enqueue (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)
120 {
121 
122  switch (m_state)
123  {
124  case CCABUSY:
125  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " MAC " << GetAddress () << " Starting enqueue CCABUSY");
126  if (m_txEndEvent.IsRunning () == TX)
127  {
128  NS_LOG_DEBUG ("State is TX");
129  }
130  else
131  {
132  NS_LOG_DEBUG ("State is not TX");
133  }
134 
135  NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () >= 1 || m_phy->IsStateTx ());
136  return false;
137  case RUNNING:
138  NS_LOG_DEBUG ("MAC " << GetAddress () << " Starting enqueue RUNNING");
139  NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () == 0 && !m_phy->IsStateTx ());
140  return false;
141  case TX:
142  case IDLE:
143  {
144  NS_ASSERT (!m_pktTx);
145 
146  UanHeaderCommon header;
147  header.SetDest (UanAddress::ConvertFrom (dest));
148  header.SetSrc (m_address);
149  header.SetType (0);
150  packet->AddHeader (header);
151 
152  m_enqueueLogger (packet, protocolNumber);
153 
154  if (m_phy->IsStateBusy ())
155  {
156  m_pktTx = packet;
157  m_pktTxProt = protocolNumber;
158  m_state = CCABUSY;
159  uint32_t cw = (uint32_t) m_rv->GetValue (0,m_cw);
160  m_savedDelayS = Seconds ((double)(cw) * m_slotTime.GetSeconds ());
161  m_sendTime = Simulator::Now () + m_savedDelayS;
162  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << ": Addr " << GetAddress () << ": Enqueuing new packet while busy: (Chose CW " << cw << ", Sending at " << m_sendTime.GetSeconds () << " Packet size: " << packet->GetSize ());
163  NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () >= 1 || m_phy->IsStateTx ());
164  }
165  else
166  {
167  NS_ASSERT (m_state != TX);
168  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << ": Addr " << GetAddress () << ": Enqueuing new packet while idle (sending)");
169  NS_ASSERT (m_phy->GetTransducer ()->GetArrivalList ().size () == 0 && !m_phy->IsStateTx ());
170  m_state = TX;
171  m_phy->SendPacket (packet,protocolNumber);
172 
173  }
174  break;
175  }
176  default:
177  NS_LOG_DEBUG ("MAC " << GetAddress () << " Starting enqueue SOMETHING ELSE");
178  return false;
179  }
180 
181  return true;
182 
183 
184 }
185 
186 void
188 {
189  m_forwardUpCb = cb;
190 }
191 
192 void
194 {
195  m_phy = phy;
196  m_phy->SetReceiveOkCallback (MakeCallback (&UanMacCw::PhyRxPacketGood, this));
197  m_phy->SetReceiveErrorCallback (MakeCallback (&UanMacCw::PhyRxPacketError, this));
198  m_phy->RegisterListener (this);
199 }
200 
201 Address
203 {
204  return UanAddress::GetBroadcast ();
205 }
206 
207 
208 void
210 {
211  if (m_state == RUNNING)
212  {
213 
214  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel busy");
215  SaveTimer ();
216  m_state = CCABUSY;
217  }
218 
219 }
220 void
222 {
223  if (m_state == CCABUSY && !m_phy->IsStateCcaBusy ())
224  {
225  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
226  m_state = RUNNING;
227  StartTimer ();
228 
229  }
230 
231 }
232 void
234 {
235  if (m_state == CCABUSY && !m_phy->IsStateCcaBusy ())
236  {
237  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
238  m_state = RUNNING;
239  StartTimer ();
240 
241  }
242 
243 }
244 void
246 {
247  if (m_state == RUNNING)
248  {
249  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel busy");
250  m_state = CCABUSY;
251  SaveTimer ();
252 
253  }
254 
255 }
256 void
258 {
259  if (m_state == CCABUSY)
260  {
261  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle");
262  m_state = RUNNING;
263  StartTimer ();
264 
265  }
266 
267 }
268 void
270 {
271 
272  if (m_txEndEvent.IsRunning ())
273  {
274  Simulator::Cancel (m_txEndEvent);
275  }
276 
277  m_txEndEvent = Simulator::Schedule (duration, &UanMacCw::EndTx, this);
278  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " scheduling TxEndEvent with delay " << duration.GetSeconds ());
279  if (m_state == RUNNING)
280  {
281  NS_ASSERT (0);
282  m_state = CCABUSY;
283  SaveTimer ();
284 
285  }
286 
287 }
288 
289 int64_t
290 UanMacCw::AssignStreams (int64_t stream)
291 {
292  NS_LOG_FUNCTION (this << stream);
293  m_rv->SetStream (stream);
294  return 1;
295 }
296 
297 void
298 UanMacCw::EndTx (void)
299 {
300  NS_ASSERT (m_state == TX || m_state == CCABUSY);
301  if (m_state == TX)
302  {
303  m_state = IDLE;
304  }
305  else if (m_state == CCABUSY)
306  {
307  if (m_phy->IsStateIdle ())
308  {
309  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << ": Switching to channel idle (After TX!)");
310  m_state = RUNNING;
311  StartTimer ();
312  }
313  }
314  else
315  {
316  NS_FATAL_ERROR ("In strange state at UanMacCw EndTx");
317  }
318 }
319 void
320 UanMacCw::SetCw (uint32_t cw)
321 {
322  m_cw = cw;
323 }
324 void
326 {
327  m_slotTime = duration;
328 }
329 uint32_t
331 {
332  return m_cw;
333 }
334 Time
336 {
337  return m_slotTime;
338 }
339 void
340 UanMacCw::PhyRxPacketGood (Ptr<Packet> packet, double sinr, UanTxMode mode)
341 {
342  UanHeaderCommon header;
343  packet->RemoveHeader (header);
344 
345  if (header.GetDest () == m_address || header.GetDest () == UanAddress::GetBroadcast ())
346  {
347  m_forwardUpCb (packet, header.GetSrc ());
348  }
349 }
350 void
351 UanMacCw::PhyRxPacketError (Ptr<Packet> packet, double sinr)
352 {
353 
354 }
355 void
356 UanMacCw::SaveTimer (void)
357 {
358  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Saving timer (Delay = " << (m_savedDelayS = m_sendTime - Simulator::Now ()).GetSeconds () << ")");
359  NS_ASSERT (m_pktTx);
360  NS_ASSERT (m_sendTime >= Simulator::Now ());
361  m_savedDelayS = m_sendTime - Simulator::Now ();
362  Simulator::Cancel (m_sendEvent);
363 
364 
365 }
366 void
367 UanMacCw::StartTimer (void)
368 {
369 
370  m_sendTime = Simulator::Now () + m_savedDelayS;
371  if (m_sendTime == Simulator::Now ())
372  {
373  SendPacket ();
374  }
375  else
376  {
377  m_sendEvent = Simulator::Schedule (m_savedDelayS, &UanMacCw::SendPacket, this);
378  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Starting timer (New send time = " << this->m_sendTime.GetSeconds () << ")");
379  }
380 }
381 
382 void
383 UanMacCw::SendPacket (void)
384 {
385  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Transmitting ");
386  NS_ASSERT (m_state == RUNNING);
387  m_state = TX;
388  m_phy->SendPacket (m_pktTx,m_pktTxProt);
389  m_pktTx = 0;
390  m_sendTime = Seconds (0);
391  m_savedDelayS = Seconds (0);
392 }
393 
394 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
keep track of time unit.
Definition: nstime.h:149
virtual Address GetAddress()
Definition: uan-mac-cw.cc:107
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
Callback template class.
Definition: callback.h:369
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
virtual void SetSlotTime(Time duration)
Definition: uan-mac-cw.cc:325
virtual void DoDispose(void)
Definition: object.cc:335
virtual void AttachPhy(Ptr< UanPhy > phy)
Definition: uan-mac-cw.cc:193
virtual void Clear(void)
Definition: uan-mac-cw.cc:52
static void Cancel(const EventId &id)
Definition: simulator.cc:267
bool IsRunning(void) const
Definition: event-id.cc:59
virtual Address GetBroadcast(void) const
Definition: uan-mac-cw.cc:202
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
virtual void NotifyRxEndError(void)
Function called by UanPhy object to notify of packet received in error.
Definition: uan-mac-cw.cc:233
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
a polymophic address class
Definition: address.h:86
virtual void SetAddress(UanAddress addr)
Definition: uan-mac-cw.cc:113
virtual bool Enqueue(Ptr< Packet > pkt, const Address &dest, uint16_t protocolNumber)
Definition: uan-mac-cw.cc:119
double GetSeconds(void) const
Definition: nstime.h:262
hold objects of type ns3::Time
Definition: nstime.h:700
static UanAddress ConvertFrom(const Address &address)
Definition: uan-address.cc:54
Hold an unsigned integer type.
Definition: uinteger.h:46
void SetSrc(UanAddress src)
virtual void SetCw(uint32_t cw)
Definition: uan-mac-cw.cc:320
virtual void NotifyRxStart(void)
Function called by UanPhy object to notify of packet reception.
Definition: uan-mac-cw.cc:209
Abstraction of packet modulation information.
Definition: uan-tx-mode.h:36
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
Ptr< UniformRandomVariable > m_rv
Provides uniform random variables.
Definition: uan-mac-cw.h:129
void SetDest(UanAddress dest)
virtual void NotifyRxEndOk(void)
Function called by UanPhy object to notify of packet received successfully.
Definition: uan-mac-cw.cc:221
static UanAddress GetBroadcast(void)
Definition: uan-address.cc:92
virtual void NotifyCcaStart(void)
Function called by UanPhy object to notify of channel sensed busy.
Definition: uan-mac-cw.cc:245
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
UanAddress GetDest(void) const
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
virtual Time GetSlotTime(void)
Definition: uan-mac-cw.cc:335
static Time Now(void)
Definition: simulator.cc:179
virtual void NotifyTxStart(Time duration)
Function called by UanPhy object to notify of outgoing transmission start.
Definition: uan-mac-cw.cc:269
virtual void DoDispose()
Definition: uan-mac-cw.cc:70
virtual uint32_t GetCw(void)
Definition: uan-mac-cw.cc:330
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
int64_t AssignStreams(int64_t stream)
Definition: uan-mac-cw.cc:290
virtual void SetForwardUpCb(Callback< void, Ptr< Packet >, const UanAddress & > cb)
Definition: uan-mac-cw.cc:187
void Cancel(void)
Definition: event-id.cc:47
void SetType(uint8_t type)
UanAddress GetSrc(void) const
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
a base class which provides memory management and object aggregation
Definition: object.h:63
a unique identifier for an interface.
Definition: type-id.h:44
virtual void NotifyCcaEnd(void)
Function called by UanPhy object to notify of channel no longer sensed busy.
Definition: uan-mac-cw.cc:257
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void AddHeader(const Header &header)
Definition: packet.cc:270