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  .SetGroupName ("Wave")
60  .AddConstructor<DefaultChannelScheduler> ()
61  ;
62  return tid;
63 }
64 
66  : m_channelNumber (0),
67  m_extend (EXTENDED_CONTINUOUS),
68  m_channelAccess (NoAccess),
69  m_waitChannelNumber (0),
70  m_waitExtend (0),
71  m_coordinationListener (0)
72 {
73  NS_LOG_FUNCTION (this);
74 }
76 {
77  NS_LOG_FUNCTION (this);
78 }
79 
80 void
82 {
83  NS_LOG_FUNCTION (this);
85 }
86 
87 void
89 {
90  NS_LOG_FUNCTION (this);
91  m_coordinator = 0;
92  if (m_coordinationListener != 0)
93  {
95  }
96  if (!m_waitEvent.IsExpired ())
97  {
99  }
100  if (!m_extendEvent.IsExpired ())
101  {
102  m_waitEvent.Cancel ();
103  }
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION (this << device);
112  std::vector<Ptr<WifiPhy> > phys = device->GetPhys ();
113  if (phys.size () > 1)
114  {
115  NS_LOG_WARN ("The class is only in the context of single-PHY device, while there are more than one PHY devices");
116  }
117  // since default channel scheduler is in the context of single-PHY, we only use one phy object.
118  m_phy = device->GetPhy (0);
120  m_coordinationListener = Create<CoordinationListener> (this);
122 }
123 
124 enum ChannelAccess
126 {
127  NS_LOG_FUNCTION (this << channelNumber);
128  if (m_channelAccess == AlternatingAccess && channelNumber == CCH)
129  {
130  return AlternatingAccess;
131  }
132  return (m_channelNumber == channelNumber) ? m_channelAccess : NoAccess;
133 }
134 
135 
136 bool
137 DefaultChannelScheduler::AssignAlternatingAccess (uint32_t channelNumber, bool immediate)
138 {
139  NS_LOG_FUNCTION (this << channelNumber << immediate);
141  uint32_t sch = channelNumber;
142 
144  {
145  return false;
146  }
147 
149  {
150  if (m_channelNumber != sch)
151  {
152  return false;
153  }
154  else
155  {
156  return true;
157  }
158  }
159 
160  // if we need immediately switch to AlternatingAccess,
161  // we switch to specific SCH.
162  if ((immediate && m_coordinator->IsSchInterval ()))
163  {
165  SwitchToNextChannel (CCH, sch);
166  }
167 
168  m_channelNumber = sch;
170  return true;
171 }
172 
173 bool
174 DefaultChannelScheduler::AssignContinuousAccess (uint32_t channelNumber, bool immediate)
175 {
176  NS_LOG_FUNCTION (this << channelNumber << immediate);
178  uint32_t sch = channelNumber;
180  {
181  return false;
182  }
183 
185  {
186  if (m_channelNumber != sch)
187  {
188  return false;
189  }
190  else
191  {
192  return true;
193  }
194  }
195 
196  // if there is already an wait event for previous non-immediate request
197  if (!m_waitEvent.IsExpired ())
198  {
199  if (m_waitChannelNumber != sch)
200  {
201  // then the coming new request will be rejected because of FCFS
202  return false;
203  }
204  else
205  {
206  if (!immediate)
207  {
208  return true;
209  }
210  // then cancel this wait event and assign access for request immediately
211  m_waitEvent.Cancel ();
212  }
213  }
214 
215  if (immediate || m_coordinator->IsSchInterval ())
216  {
218  m_channelNumber = sch;
220  }
221  else
222  {
225  m_waitChannelNumber = sch;
226  }
227 
228  return true;
229 }
230 
231 bool
232 DefaultChannelScheduler::AssignExtendedAccess (uint32_t channelNumber, uint32_t extends, bool immediate)
233 {
234  NS_LOG_FUNCTION (this << channelNumber << extends << immediate);
236  uint32_t sch = channelNumber;
238  {
239  return false;
240  }
241 
243  {
244  if (m_channelNumber != sch)
245  {
246  return false;
247  }
248  else
249  {
250  // if current remain extends cannot fulfill the requirement for extends
252  uint32_t remainExtends = remainTime / m_coordinator->GetSyncInterval ();
253  if (remainExtends > extends)
254  {
255  return true;
256  }
257  else
258  {
259  return false;
260  }
261  }
262  }
263 
264  // if there is already an wait event for previous non-immediate request
265  if (!m_waitEvent.IsExpired ())
266  {
268  if (m_waitChannelNumber != sch)
269  {
270  // then the coming new request will be rejected because of FCFS
271  return false;
272  }
273  else
274  {
275  if (m_waitExtend < extends)
276  {
277  return false;
278  }
279 
280  if (immediate)
281  {
282  // then cancel previous wait event and
283  // go to below code to assign access for request immediately
284  m_waitEvent.Cancel ();
285  }
286  else
287  {
288  return true;
289  }
290  }
291  }
292 
293  if (immediate || m_coordinator->IsSchInterval ())
294  {
296  m_channelNumber = sch;
298  m_extend = extends;
299 
301  // the wait time to proper interval will not be calculated as extended time.
302  Time extendedDuration = m_coordinator->NeedTimeToCchInterval () + MilliSeconds (extends * sync.GetMilliSeconds ());
303  // after end_duration time, DefaultChannelScheduler will release channel access automatically
305  }
306  else
307  {
310  m_waitChannelNumber = sch;
311  m_waitExtend = extends;
312  }
313  return true;
314 }
315 
316 bool
318 {
319  NS_LOG_FUNCTION (this);
321  {
322  return true;
323  }
324  if (m_channelNumber != 0)
325  {
326  // This class does not support preemptive scheduling
327  NS_LOG_DEBUG ("channel access is already assigned for other SCHs, thus cannot assign default CCH access.");
328  return false;
329  }
330  // CCH MAC is to attach single-PHY device and wake up for transmission.
331  Ptr<OcbWifiMac> cchMacEntity = m_device->GetMac (CCH);
332  if (Now ().GetMilliSeconds() != 0)
333  {
335  Time switchTime = m_phy->GetChannelSwitchDelay ();
336  cchMacEntity->MakeVirtualBusy (switchTime);
337  }
338  cchMacEntity->SetWifiPhy (m_phy);
339  cchMacEntity->Resume ();
340 
344  return true;
345 }
346 
347 void
348 DefaultChannelScheduler::SwitchToNextChannel (uint32_t curChannelNumber, uint32_t nextChannelNumber)
349 {
350  NS_LOG_FUNCTION (this << curChannelNumber << curChannelNumber);
351  if (m_phy->GetChannelNumber () == nextChannelNumber)
352  {
353  return;
354  }
355  Ptr<OcbWifiMac> curMacEntity = m_device->GetMac (curChannelNumber);
356  Ptr<OcbWifiMac> nextMacEntity = m_device->GetMac (nextChannelNumber);
357  // Perfect channel switch operation among multiple MAC entities in the context of single PHY device.
358  // first make current MAC entity in sleep mode.
359  curMacEntity->Suspend ();
360  // second unattached current MAC entity from single PHY device
361  curMacEntity->ResetWifiPhy ();
362  // third switch PHY device from current channel to next channel;
363  m_phy->SetChannelNumber (nextChannelNumber);
364  // Here channel switch time is required to notify next MAC entity
365  // that channel access cannot be enabled in channel switch time.
366  Time switchTime = m_phy->GetChannelSwitchDelay ();
367  nextMacEntity->MakeVirtualBusy (switchTime);
368  // four attach next MAC entity to single PHY device
369  nextMacEntity->SetWifiPhy (m_phy);
370  // finally resume next MAC entity from sleep mode
371  nextMacEntity->Resume ();
372 }
373 
374 bool
376 {
377  NS_LOG_FUNCTION (this << channelNumber);
378  NS_ASSERT (m_channelNumber != 0);
379  if (m_channelNumber != channelNumber)
380  {
381  return false;
382  }
383  // cancel current SCH MAC activity and assigned default CCH access.
388  if (!m_waitEvent.IsExpired ())
389  {
390  m_waitEvent.Cancel ();
391  }
392  if (!m_extendEvent.IsExpired ())
393  {
395  }
397  m_waitExtend = 0;
398  return true;
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION (this << duration);
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION (this << duration);
411 }
412 
413 void
415 {
416  NS_LOG_FUNCTION (this << duration << cchi);
417  // only alternating access requires channel coordination events
419  {
420  return;
421  }
422 
423  if (cchi)
424  {
427  // see chapter 6.2.5 Sync tolerance
428  // a medium busy shall be declared during the guard interval.
429  mac->MakeVirtualBusy (duration);
430  }
431  else
432  {
435  // see chapter 6.2.5 Sync tolerance
436  // a medium busy shall be declared during the guard interval.
437  mac->MakeVirtualBusy (duration);
438  }
439 }
440 } // namespace ns3
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:233
Ptr< WifiPhy > GetPhy(uint32_t index) const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
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:67
#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:903
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
#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 uint16_t GetChannelNumber(void) const
Return current channel number.
Definition: wifi-phy.cc:1329
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1238
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.
tuple mac
Definition: third.py:92
virtual void SetChannelNumber(uint16_t id)
Set channel number.
Definition: wifi-phy.cc:1275
virtual void DoInitialize(void)
Initialize() implementation.
virtual void NotifySchSlotStart(Time duration)
virtual bool AssignDefaultCchAccess(void)
This method will assign default CCH access for CCH.
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)
Time NeedTimeToSchInterval(Time duration=Seconds(0.0)) const
virtual enum ChannelAccess GetAssignedAccessType(uint32_t channelNumber) const
virtual bool ReleaseAccess(uint32_t channelNumber)
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 Time GetChannelSwitchDelay(void) const
Definition: wifi-phy.cc:659
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)
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:340
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:58
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:345
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
This class will assign channel access for requests from higher layers.
void SwitchToNextChannel(uint32_t curChannelNumber, uint32_t nextChannelNumber)