A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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"
24#include "cid.h"
25#include "connection-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
39namespace ns3
40{
41
42NS_LOG_COMPONENT_DEFINE("BSSchedulerSimple");
43
44NS_OBJECT_ENSURE_REGISTERED(BSSchedulerSimple);
45
46TypeId
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
85std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>*
87{
88 return m_downlinkBursts;
89}
90
91void
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->emplace_back(dlMapIe, burst);
113}
114
115void
117{
118 Ptr<WimaxConnection> connection;
121 uint32_t nrSymbolsRequired = 0;
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())
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 {
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
241bool
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;
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
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
STL namespace.
#define list