A Discrete-Event Network Simulator
API
bs-scheduler-simple.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007,2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
18  */
19 
20 #include "bs-scheduler-simple.h"
21 
22 #include "bs-net-device.h"
23 #include "burst-profile-manager.h"
24 #include "cid.h"
25 #include "connection-manager.h"
26 #include "service-flow-manager.h"
27 #include "service-flow-record.h"
28 #include "service-flow.h"
29 #include "ss-manager.h"
30 #include "ss-record.h"
31 #include "wimax-connection.h"
32 #include "wimax-mac-header.h"
33 #include "wimax-mac-queue.h"
34 
35 #include "ns3/log.h"
36 #include "ns3/packet-burst.h"
37 #include "ns3/simulator.h"
38 
39 namespace ns3
40 {
41 
42 NS_LOG_COMPONENT_DEFINE("BSSchedulerSimple");
43 
44 NS_OBJECT_ENSURE_REGISTERED(BSSchedulerSimple);
45 
46 TypeId
48 {
49  static TypeId tid = TypeId("ns3::BSSchedulerSimple")
51  .SetGroupName("Wimax")
52  .AddConstructor<BSSchedulerSimple>();
53  return tid;
54 }
55 
57  : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
58 {
59  SetBs(nullptr);
60 }
61 
63  : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
64 {
65  // m_downlinkBursts is filled by AddDownlinkBurst and emptied by
66  // wimax-bs-net-device::sendBurst and wimax-ss-net-device::sendBurst
67  SetBs(bs);
68 }
69 
71 {
72  std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts = m_downlinkBursts;
73  std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
74  while (!downlinkBursts->empty())
75  {
76  pair = downlinkBursts->front();
77  pair.second = nullptr;
78  delete pair.first;
79  }
80  SetBs(nullptr);
81  delete m_downlinkBursts;
82  m_downlinkBursts = nullptr;
83 }
84 
85 std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>*
87 {
88  return m_downlinkBursts;
89 }
90 
91 void
93  uint8_t diuc,
94  WimaxPhy::ModulationType modulationType,
95  Ptr<PacketBurst> burst)
96 {
97  OfdmDlMapIe* dlMapIe = new OfdmDlMapIe();
98  dlMapIe->SetCid(connection->GetCid());
99  dlMapIe->SetDiuc(diuc);
100 
101  NS_LOG_INFO("BS scheduler, burst size: " << burst->GetSize() << " bytes"
102  << ", pkts: " << burst->GetNPackets()
103  << ", connection: " << connection->GetTypeStr()
104  << ", CID: " << connection->GetCid());
105  if (connection->GetType() == Cid::TRANSPORT)
106  {
107  NS_LOG_INFO(", SFID: " << connection->GetServiceFlow()->GetSfid() << ", service: "
108  << connection->GetServiceFlow()->GetSchedulingTypeStr());
109  }
110  NS_LOG_INFO(", modulation: " << modulationType << ", DIUC: " << (uint32_t)diuc);
111 
112  m_downlinkBursts->push_back(std::make_pair(dlMapIe, burst));
113 }
114 
115 void
117 {
118  Ptr<WimaxConnection> connection;
121  uint32_t nrSymbolsRequired = 0;
122  GenericMacHeader hdr;
123  Ptr<Packet> packet;
124  Ptr<PacketBurst> burst;
126  uint32_t availableSymbols = GetBs()->GetNrDlSymbols();
127 
128  while (SelectConnection(connection))
129  {
130  if (connection != GetBs()->GetInitialRangingConnection() &&
131  connection != GetBs()->GetBroadcastConnection())
132  {
133  /* determines modulation/DIUC only once per burst as it is always same for a particular
134  * CID */
135  if (connection->GetType() == Cid::MULTICAST)
136  {
137  modulationType = connection->GetServiceFlow()->GetModulation();
138  }
139  else
140  {
141  modulationType =
142  GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
143  }
144  diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
145  modulationType,
147  }
148  else if (connection == GetBs()->GetInitialRangingConnection() ||
149  connection == GetBs()->GetBroadcastConnection())
150  {
151  modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
153  }
154 
155  if (connection->GetType() == Cid::TRANSPORT || connection->GetType() == Cid::MULTICAST)
156  {
157  schedulingType = (ServiceFlow::SchedulingType)connection->GetSchedulingType();
158  }
159 
160  if (schedulingType == ServiceFlow::SF_TYPE_UGS)
161  {
162  nrSymbolsRequired = connection->GetServiceFlow()->GetRecord()->GetGrantSize();
163  if (nrSymbolsRequired < availableSymbols)
164  {
165  burst =
166  CreateUgsBurst(connection->GetServiceFlow(), modulationType, nrSymbolsRequired);
167  }
168  else
169  {
170  burst =
171  CreateUgsBurst(connection->GetServiceFlow(), modulationType, availableSymbols);
172  }
173  if (burst->GetNPackets() != 0)
174  {
175  uint32_t BurstSizeSymbols =
176  GetBs()->GetPhy()->GetNrSymbols(burst->GetSize(), modulationType);
177  AddDownlinkBurst(connection, diuc, modulationType, burst);
178 
179  if (availableSymbols <= BurstSizeSymbols)
180  {
181  availableSymbols -=
182  BurstSizeSymbols;
183  break;
184  }
185  }
186  }
187  else
188  {
189  burst = Create<PacketBurst>();
190  while (connection->HasPackets() == true)
191  {
192  uint32_t FirstPacketSize = connection->GetQueue()->GetFirstPacketRequiredByte(
194  nrSymbolsRequired =
195  GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
196  if (availableSymbols < nrSymbolsRequired &&
197  CheckForFragmentation(connection, availableSymbols, modulationType))
198  {
199  uint32_t availableByte =
200  GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
201  packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
202  availableSymbols = 0;
203  }
204  else if (availableSymbols >= nrSymbolsRequired)
205  {
206  packet = connection->Dequeue();
207  availableSymbols -= nrSymbolsRequired;
208  }
209  else
210  {
211  break;
212  }
213  burst->AddPacket(packet);
214  }
215  AddDownlinkBurst(connection, diuc, modulationType, burst);
216  }
217  if (availableSymbols == 0)
218  {
219  break;
220  }
221  }
222 
223  if (!m_downlinkBursts->empty())
224  {
225  NS_LOG_DEBUG(
226  "BS scheduler, number of bursts: "
227  << m_downlinkBursts->size() << ", symbols left: " << availableSymbols << std::endl
228  << "BS scheduler, queues:"
229  << " IR " << GetBs()->GetInitialRangingConnection()->GetQueue()->GetSize()
230  << " broadcast " << GetBs()->GetBroadcastConnection()->GetQueue()->GetSize()
231  << " basic "
232  << GetBs()->GetConnectionManager()->GetNPackets(Cid::BASIC, ServiceFlow::SF_TYPE_NONE)
233  << " primary "
234  << GetBs()->GetConnectionManager()->GetNPackets(Cid::PRIMARY, ServiceFlow::SF_TYPE_NONE)
235  << " transport "
236  << GetBs()->GetConnectionManager()->GetNPackets(Cid::TRANSPORT,
238  }
239 }
240 
241 bool
243 {
244  connection = nullptr;
245  Time currentTime = Simulator::Now();
246  std::vector<Ptr<WimaxConnection>>::const_iterator iter1;
247  std::vector<ServiceFlow*>::iterator iter2;
248  ServiceFlowRecord* serviceFlowRecord;
249  NS_LOG_INFO("BS Scheduler: Selecting connection...");
250  if (GetBs()->GetBroadcastConnection()->HasPackets())
251  {
252  NS_LOG_INFO("Return GetBroadcastConnection");
253  connection = GetBs()->GetBroadcastConnection();
254  return true;
255  }
256  else if (GetBs()->GetInitialRangingConnection()->HasPackets())
257  {
258  NS_LOG_INFO("Return GetInitialRangingConnection");
259  connection = GetBs()->GetInitialRangingConnection();
260  return true;
261  }
262  else
263  {
264  std::vector<Ptr<WimaxConnection>> connections;
265  std::vector<ServiceFlow*> serviceFlows;
266 
267  connections = GetBs()->GetConnectionManager()->GetConnections(Cid::BASIC);
268  for (iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
269  {
270  if ((*iter1)->HasPackets())
271  {
272  NS_LOG_INFO("Return Basic");
273  connection = *iter1;
274  return true;
275  }
276  }
277 
278  connections = GetBs()->GetConnectionManager()->GetConnections(Cid::PRIMARY);
279  for (iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
280  {
281  if ((*iter1)->HasPackets())
282  {
283  NS_LOG_INFO("Return Primary");
284  connection = *iter1;
285  return true;
286  }
287  }
288 
289  serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_UGS);
290  for (iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
291  {
292  serviceFlowRecord = (*iter2)->GetRecord();
293  NS_LOG_INFO("processing UGS: HAS PACKET="
294  << (*iter2)->HasPackets() << "max Latency = "
295  << MilliSeconds((*iter2)->GetMaximumLatency()) << "Delay = "
296  << ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
297  GetBs()->GetPhy()->GetFrameDuration()));
298  // if latency would exceed in case grant is allocated in next frame then allocate in
299  // current frame
300  if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
301  GetBs()->GetPhy()->GetFrameDuration()) >
302  MilliSeconds((*iter2)->GetMaximumLatency()))
303  {
304  serviceFlowRecord->SetDlTimeStamp(currentTime);
305  connection = (*iter2)->GetConnection();
306  NS_LOG_INFO("Return UGS SF: CID = " << (*iter2)->GetCid()
307  << "SFID = " << (*iter2)->GetSfid());
308  return true;
309  }
310  }
311 
312  serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
313  for (iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
314  {
315  serviceFlowRecord = (*iter2)->GetRecord();
316  // if latency would exceed in case poll is allocated in next frame then allocate in
317  // current frame
318  if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
319  GetBs()->GetPhy()->GetFrameDuration()) >
320  MilliSeconds((*iter2)->GetMaximumLatency()))
321  {
322  serviceFlowRecord->SetDlTimeStamp(currentTime);
323  connection = (*iter2)->GetConnection();
324  NS_LOG_INFO("Return RTPS SF: CID = " << (*iter2)->GetCid()
325  << "SFID = " << (*iter2)->GetSfid());
326  return true;
327  }
328  }
329 
330  serviceFlows =
331  GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_NRTPS);
332  for (iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
333  {
334  // unused: serviceFlowRecord = (*iter2)->GetRecord ();
335  if ((*iter2)->HasPackets())
336  {
337  NS_LOG_INFO("Return NRTPS SF: CID = " << (*iter2)->GetCid()
338  << "SFID = " << (*iter2)->GetSfid());
339  connection = (*iter2)->GetConnection();
340  return true;
341  }
342  }
343 
344  serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_BE);
345  for (iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
346  {
347  // unused: serviceFlowRecord = (*iter2)->GetRecord ();
348  if ((*iter2)->HasPackets())
349  {
350  NS_LOG_INFO("Return BE SF: CID = " << (*iter2)->GetCid()
351  << "SFID = " << (*iter2)->GetSfid());
352  connection = (*iter2)->GetConnection();
353  return true;
354  }
355  }
356  }
357  NS_LOG_INFO("NO connection is selected!");
358  return false;
359 }
360 
363  WimaxPhy::ModulationType modulationType,
364  uint32_t availableSymbols)
365 {
366  Time timeStamp;
367  GenericMacHeader hdr;
368  Ptr<Packet> packet;
369  Ptr<PacketBurst> burst = Create<PacketBurst>();
370  uint32_t nrSymbolsRequired = 0;
371 
372  // serviceFlow->CleanUpQueue ();
373  Ptr<WimaxConnection> connection = serviceFlow->GetConnection();
374  while (serviceFlow->HasPackets())
375  {
376  uint32_t FirstPacketSize =
377  connection->GetQueue()->GetFirstPacketRequiredByte(MacHeaderType::HEADER_TYPE_GENERIC);
378  nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
379  if (availableSymbols < nrSymbolsRequired &&
380  CheckForFragmentation(connection, availableSymbols, modulationType))
381  {
382  uint32_t availableByte =
383  GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
384  packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
385  availableSymbols = 0;
386  }
387  else
388  {
389  packet = connection->Dequeue();
390  availableSymbols -= nrSymbolsRequired;
391  }
392  burst->AddPacket(packet);
393  if (availableSymbols <= 0)
394  {
395  break;
396  }
397  }
398  return burst;
399 }
400 
401 } // namespace ns3
BaseStation Scheduler.
Definition: bs-scheduler.h:48
virtual Ptr< BaseStationNetDevice > GetBs()
Get the base station.
Definition: bs-scheduler.cc:89
virtual void SetBs(Ptr< BaseStationNetDevice > bs)
Set the base station.
Definition: bs-scheduler.cc:83
bool CheckForFragmentation(Ptr< WimaxConnection > connection, int availableSymbols, WimaxPhy::ModulationType modulationType)
Check if the packet fragmentation is possible for transport connection.
Definition: bs-scheduler.cc:95
BaseStation Scheduler - simplified.
std::list< std::pair< OfdmDlMapIe *, Ptr< PacketBurst > > > * GetDownlinkBursts() const override
This function returns all the downlink bursts scheduled for the next downlink sub-frame.
void AddDownlinkBurst(Ptr< const WimaxConnection > connection, uint8_t diuc, WimaxPhy::ModulationType modulationType, Ptr< PacketBurst > burst) override
This function adds a downlink burst to the list of downlink bursts scheduled for the next downlink su...
std::list< std::pair< OfdmDlMapIe *, Ptr< PacketBurst > > > * m_downlinkBursts
down link bursts
static TypeId GetTypeId()
Get the type ID.
void Schedule() override
the scheduling function for the downlink subframe.
Ptr< PacketBurst > CreateUgsBurst(ServiceFlow *serviceFlow, WimaxPhy::ModulationType modulationType, uint32_t availableSymbols) override
Creates a downlink UGS burst.
bool SelectConnection(Ptr< WimaxConnection > &connection) override
Selects a connection from the list of connections having packets to be sent .
@ PRIMARY
Definition: cid.h:45
@ TRANSPORT
Definition: cid.h:46
@ MULTICAST
Definition: cid.h:47
@ BASIC
Definition: cid.h:44
This class implements the Generic mac Header as described by IEEE Standard for Local and metropolitan...
This class implements the OFDM DL-MAP information element as described by "IEEE Standard for Local an...
void SetCid(Cid cid)
Set CID function.
void SetDiuc(uint8_t diuc)
Set DIUC field.
this class implement a burst as a list of packets
Definition: packet-burst.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
This class implements service flows as described by the IEEE-802.16 standard.
Definition: service-flow.h:43
SchedulingType
section 11.13.11 Service flow scheduling type, page 701
Definition: service-flow.h:62
bool HasPackets() const
Check if packets are present.
Ptr< WimaxConnection > GetConnection() const
Can return a null connection is this service flow has not been associated yet to a connection.
this class implements a structure to manage some parameters and statistics related to a service flow
void SetDlTimeStamp(Time dlTimeStamp)
Set the DlTimeStamp.
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
ModulationType
ModulationType enumeration.
Definition: wimax-phy.h:54
@ MODULATION_TYPE_BPSK_12
Definition: wimax-phy.h:55
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added.
Definition: wifi-utils.cc:132
#define list