A Discrete-Event Network Simulator
API
default-channel-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * Author: Junling Bu <linlinjavaer@gmail.com>
17  */
19 #include "ns3/log.h"
20 #include "ns3/simulator.h"
21 
22 namespace ns3 {
23 
24 NS_LOG_COMPONENT_DEFINE ("DefaultChannelScheduler");
25 
26 NS_OBJECT_ENSURE_REGISTERED (DefaultChannelScheduler);
27 
29 {
30 public:
32  : m_scheduler (scheduler)
33  {
34  }
36  {
37  }
38  virtual void NotifyCchSlotStart (Time duration)
39  {
40  m_scheduler->NotifyCchSlotStart (duration);
41  }
42  virtual void NotifySchSlotStart (Time duration)
43  {
44  m_scheduler->NotifySchSlotStart (duration);
45  }
46  virtual void NotifyGuardSlotStart (Time duration, bool cchi)
47  {
48  m_scheduler->NotifyGuardSlotStart (duration, cchi);
49  }
50 private:
52 };
53 
54 TypeId
56 {
57  static TypeId tid = TypeId ("ns3::DefaultChannelScheduler")
59  .AddConstructor<DefaultChannelScheduler> ()
60  ;
61  return tid;
62 }
63 
65  : m_channelNumber (0),
66  m_extend (EXTENDED_CONTINUOUS),
67  m_channelAccess (NoAccess),
68  m_waitChannelNumber (0),
69  m_waitExtend (0),
70  m_coordinationListener (0)
71 {
72  NS_LOG_FUNCTION (this);
73 }
75 {
76  NS_LOG_FUNCTION (this);
77 }
78 
79 void
81 {
82  NS_LOG_FUNCTION (this);
84 }
85 
86 void
88 {
89  NS_LOG_FUNCTION (this);
90  m_coordinator = 0;
91  if (m_coordinationListener != 0)
92  {
94  }
95  if (!m_waitEvent.IsExpired ())
96  {
98  }
99  if (!m_extendEvent.IsExpired ())
100  {
101  m_waitEvent.Cancel ();
102  }
104 }
105 
106 void
108 {
109  NS_LOG_FUNCTION (this << device);
111  std::vector<Ptr<WifiPhy> > phys = device->GetPhys ();
112  if (phys.size () > 1)
113  {
114  NS_LOG_WARN ("The class is only in the context of single-PHY device, while there are more than one PHY devices");
115  }
116  // since default channel scheduler is in the context of single-PHY, we only use one phy object.
117  m_phy = device->GetPhy (0);
119  m_coordinationListener = Create<CoordinationListener> (this);
121 }
122 
123 enum ChannelAccess
125 {
126  NS_LOG_FUNCTION (this << channelNumber);
127  if (m_channelAccess == AlternatingAccess && channelNumber == CCH)
128  {
129  return AlternatingAccess;
130  }
131  return (m_channelNumber == channelNumber) ? m_channelAccess : NoAccess;
132 }
133 
134 
135 bool
136 DefaultChannelScheduler::AssignAlternatingAccess (uint32_t channelNumber, bool immediate)
137 {
138  NS_LOG_FUNCTION (this << channelNumber << immediate);
140  uint32_t sch = channelNumber;
141 
143  {
144  return false;
145  }
146 
148  {
149  if (m_channelNumber != sch)
150  {
151  return false;
152  }
153  else
154  {
155  return true;
156  }
157  }
158 
159  // if we need immediately switch SCH in CCHI, or we are in SCHI now,
160  // we switch to specific SCH.
161  if ((immediate || m_coordinator->IsSchInterval ()))
162  {
164  SwitchToNextChannel (CCH, sch);
165  }
166 
167  m_channelNumber = sch;
169  return true;
170 }
171 
172 bool
173 DefaultChannelScheduler::AssignContinuousAccess (uint32_t channelNumber, bool immediate)
174 {
175  NS_LOG_FUNCTION (this << channelNumber << immediate);
177  uint32_t sch = channelNumber;
179  {
180  return false;
181  }
182 
184  {
185  if (m_channelNumber != sch)
186  {
187  return false;
188  }
189  else
190  {
191  return true;
192  }
193  }
194 
195  // if there is already an wait event for previous non-immediate request
196  if (!m_waitEvent.IsExpired ())
197  {
198  if (m_waitChannelNumber != sch)
199  {
200  // then the coming new request will be rejected because of FCFS
201  return false;
202  }
203  else
204  {
205  if (!immediate)
206  {
207  return true;
208  }
209  // then cancel this wait event and assign access for request immediately
210  m_waitEvent.Cancel ();
211  }
212  }
213 
214  if (immediate || m_coordinator->IsSchInterval ())
215  {
217  m_channelNumber = sch;
219  }
220  else
221  {
224  m_waitChannelNumber = sch;
225  }
226 
227  return true;
228 }
229 
230 bool
231 DefaultChannelScheduler::AssignExtendedAccess (uint32_t channelNumber, uint32_t extends, bool immediate)
232 {
233  NS_LOG_FUNCTION (this << channelNumber << extends << immediate);
235  uint32_t sch = channelNumber;
237  {
238  return false;
239  }
240 
242  {
243  if (m_channelNumber != sch)
244  {
245  return false;
246  }
247  else
248  {
249  // if current remain extends cannot fulfill the requirement for extends
251  uint32_t remainExtends = remainTime / m_coordinator->GetSyncInterval ();
252  if (remainExtends > extends)
253  {
254  return true;
255  }
256  else
257  {
258  return false;
259  }
260  }
261  }
262 
263  // if there is already an wait event for previous non-immediate request
264  if (!m_waitEvent.IsExpired ())
265  {
267  if (m_waitChannelNumber != sch)
268  {
269  // then the coming new request will be rejected because of FCFS
270  return false;
271  }
272  else
273  {
274  if (m_waitExtend < extends)
275  {
276  return false;
277  }
278 
279  if (immediate)
280  {
281  // then cancel previous wait event and
282  // go to below code to assign access for request immediately
283  m_waitEvent.Cancel ();
284  }
285  else
286  {
287  return true;
288  }
289  }
290  }
291 
292  if (immediate || m_coordinator->IsSchInterval ())
293  {
295  m_channelNumber = sch;
297  m_extend = extends;
298 
300  // the wait time to proper interval will not be calculated as extended time.
301  Time extendedDuration = m_coordinator->NeedTimeToCchInterval () + MilliSeconds (extends * sync.GetMilliSeconds ());
302  // after end_duration time, DefaultChannelScheduler will release channel access automatically
304  }
305  else
306  {
309  m_waitChannelNumber = sch;
310  m_waitExtend = extends;
311  }
312  return true;
313 }
314 
315 bool
317 {
318  NS_LOG_FUNCTION (this);
320  {
321  return true;
322  }
323  if (m_channelNumber != 0)
324  {
325  // This class does not support preemptive scheduling
326  NS_LOG_DEBUG ("channel access is already assigned for other SCHs, thus cannot assign default CCH access.");
327  return false;
328  }
329  // CCH MAC is to attach single-PHY device and wake up for transmission.
330  Ptr<OcbWifiMac> cchMacEntity = m_device->GetMac (CCH);
332  cchMacEntity->SetWifiPhy (m_phy);
333  cchMacEntity->Resume ();
334 
338  return true;
339 }
340 
341 void
342 DefaultChannelScheduler::SwitchToNextChannel (uint32_t curChannelNumber, uint32_t nextChannelNumber)
343 {
344  NS_LOG_FUNCTION (this << curChannelNumber << curChannelNumber);
345  if (m_phy->GetChannelNumber () == nextChannelNumber)
346  {
347  return;
348  }
349  Ptr<OcbWifiMac> curMacEntity = m_device->GetMac (curChannelNumber);
350  Ptr<OcbWifiMac> nextMacEntity = m_device->GetMac (nextChannelNumber);
351  // Perfect channel switch operation among multiple MAC entities in the context of single PHY device.
352  // first make current MAC entity in sleep mode.
353  curMacEntity->Suspend ();
354  // second unattached current MAC entity from single PHY device
355  curMacEntity->ResetWifiPhy ();
356  // third switch PHY device from current channel to next channel;
357  m_phy->SetChannelNumber (nextChannelNumber);
358  // Here channel switch time is required to notify next MAC entity
359  // that channel access cannot be enabled in channel switch time.
360  Time switchTime = m_phy->GetChannelSwitchDelay ();
361  nextMacEntity->MakeVirtualBusy (switchTime);
362  // four attach next MAC entity to single PHY device
363  nextMacEntity->SetWifiPhy (m_phy);
364  // finally resume next MAC entity from sleep mode
365  nextMacEntity->Resume ();
366 }
367 
368 bool
370 {
371  NS_LOG_FUNCTION (this << channelNumber);
372  NS_ASSERT (m_channelNumber != 0);
373  if (m_channelNumber != channelNumber)
374  {
375  return false;
376  }
377  // cancel current SCH MAC activity and assigned default CCH access.
382  if (!m_waitEvent.IsExpired ())
383  {
384  m_waitEvent.Cancel ();
385  }
386  if (!m_extendEvent.IsExpired ())
387  {
389  }
391  m_waitExtend = 0;
392  return true;
393 }
394 
395 void
397 {
398  NS_LOG_FUNCTION (this << duration);
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION (this << duration);
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION (this << duration << cchi);
411  // only alternating access requires channel coordination events
413  {
414  return;
415  }
416 
417  if (cchi)
418  {
421  // see chapter 6.2.5 Sync tolerance
422  // a medium busy shall be declared during the guard interval.
423  mac->MakeVirtualBusy (duration);
424  }
425  else
426  {
429  // see chapter 6.2.5 Sync tolerance
430  // a medium busy shall be declared during the guard interval.
431  mac->MakeVirtualBusy (duration);
432  }
433 }
434 } // namespace ns3
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:232
Ptr< WifiPhy > GetPhy(uint32_t index) const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:95
CoordinationListener(DefaultChannelScheduler *scheduler)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual void DoDispose(void)
Destructor implementation.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:867
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:338
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
#define CCH
bool IsSchInterval(Time duration=Seconds(0.0)) const
virtual void DoInitialize(void)
Initialize() implementation.
virtual void NotifyGuardSlotStart(Time duration, bool cchi)
virtual void SetWaveNetDevice(Ptr< WaveNetDevice > device)
Ptr< ChannelCoordinator > GetChannelCoordinator(void) const
DefaultChannelScheduler * m_scheduler
virtual void SetWifiPhy(Ptr< WifiPhy > phy)
void RegisterListener(Ptr< ChannelCoordinationListener > listener)
Time NeedTimeToCchInterval(Time duration=Seconds(0.0)) const
void Suspend(void)
To support MAC extension for multiple channel operation, Suspend the activity in current MAC entity...
virtual void SetWaveNetDevice(Ptr< WaveNetDevice > device)
void MakeVirtualBusy(Time duration)
#define EXTENDED_CONTINUOUS
virtual void ResetWifiPhy(void)
removes attached WifiPhy device from this MAC.
virtual void DoInitialize(void)
Initialize() implementation.
virtual void NotifySchSlotStart(Time duration)
virtual bool AssignDefaultCchAccess(void)
This method will assign default CCH access for CCH.
virtual Time GetChannelSwitchDelay(void) const =0
This class uses a simple mechanism to assign channel access with following features: (1) only in the ...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< ChannelCoordinator > m_coordinator
void NotifyGuardSlotStart(Time duration, bool cchi)
Ptr< OcbWifiMac > GetMac(uint32_t channelNumber) const
virtual bool AssignAlternatingAccess(uint32_t channelNumber, bool immediate)
virtual uint16_t GetChannelNumber(void) const =0
Return current channel number.
Time NeedTimeToSchInterval(Time duration=Seconds(0.0)) const
virtual enum ChannelAccess GetAssignedAccessType(uint32_t channelNumber) const
virtual bool ReleaseAccess(uint32_t channelNumber)
virtual void SetChannelNumber(uint16_t id)=0
Set channel number.
Ptr< WaveNetDevice > m_device
virtual void NotifyCchSlotStart(Time duration)
std::vector< Ptr< WifiPhy > > GetPhys(void) const
Ptr< ChannelCoordinationListener > m_coordinationListener
uint32_t m_channelNumber
when m_channelAccess is ContinuousAccess, m_channelNumber is continuous channel number; when m_channe...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
receive notifications about channel coordination events.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Time GetSyncInterval(void) const
virtual bool AssignContinuousAccess(uint32_t channelNumber, bool immediate)
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
virtual bool AssignExtendedAccess(uint32_t channelNumber, uint32_t extends, bool immediate)
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
a unique identifier for an interface.
Definition: type-id.h:51
void Resume(void)
To support MAC extension for multiple channel operation, Resume the activity of suspended MAC entity...
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:331
TypeId SetParent(TypeId tid)
Definition: type-id.cc:631
This class will assign channel access for requests from higher layers.
void SwitchToNextChannel(uint32_t curChannelNumber, uint32_t nextChannelNumber)