A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
uan-mac-cw.cc
Go to the documentation of this file.
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 
35 
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 
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  }
67 }
68 
69 void
71 {
72  Clear ();
74 }
75 
76 TypeId
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",
95  .AddTraceSource ("Dequeue",
96  "A was passed down to the PHY from the MAC",
98  .AddTraceSource ("RX",
99  "A packet was destined for this MAC and was received",
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 ());
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;
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  {
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
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
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
352 {
353 
354 }
355 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);
363 
364 
365 }
366 void
368 {
369 
371  if (m_sendTime == Simulator::Now ())
372  {
373  SendPacket ();
374  }
375  else
376  {
378  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Starting timer (New send time = " << this->m_sendTime.GetSeconds () << ")");
379  }
380 }
381 
382 void
384 {
385  NS_LOG_DEBUG ("Time " << Simulator::Now ().GetSeconds () << " Addr " << GetAddress () << " Transmitting ");
387  m_state = TX;
389  m_pktTx = 0;
390  m_sendTime = Seconds (0);
391  m_savedDelayS = Seconds (0);
392 }
393 
394 } // namespace ns3