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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
7 */
8
10
11#include "bs-net-device.h"
13#include "cid.h"
14#include "connection-manager.h"
16#include "service-flow-record.h"
17#include "service-flow.h"
18#include "ss-manager.h"
19#include "ss-record.h"
20#include "wimax-connection.h"
21#include "wimax-mac-header.h"
22#include "wimax-mac-queue.h"
23
24#include "ns3/log.h"
25#include "ns3/packet-burst.h"
26#include "ns3/simulator.h"
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("BSSchedulerSimple");
32
33NS_OBJECT_ENSURE_REGISTERED(BSSchedulerSimple);
34
35TypeId
37{
38 static TypeId tid = TypeId("ns3::BSSchedulerSimple")
40 .SetGroupName("Wimax")
41 .AddConstructor<BSSchedulerSimple>();
42 return tid;
43}
44
46 : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
47{
48 SetBs(nullptr);
49}
50
52 : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
53{
54 // m_downlinkBursts is filled by AddDownlinkBurst and emptied by
55 // wimax-bs-net-device::sendBurst and wimax-ss-net-device::sendBurst
56 SetBs(bs);
57}
58
60{
61 std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts = m_downlinkBursts;
62 std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
63 while (!downlinkBursts->empty())
64 {
65 pair = downlinkBursts->front();
66 pair.second = nullptr;
67 delete pair.first;
68 }
69 SetBs(nullptr);
70 delete m_downlinkBursts;
71 m_downlinkBursts = nullptr;
72}
73
74std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>*
79
80void
82 uint8_t diuc,
83 WimaxPhy::ModulationType modulationType,
84 Ptr<PacketBurst> burst)
85{
86 auto dlMapIe = new OfdmDlMapIe();
87 dlMapIe->SetCid(connection->GetCid());
88 dlMapIe->SetDiuc(diuc);
89
90 NS_LOG_INFO("BS scheduler, burst size: " << burst->GetSize() << " bytes"
91 << ", pkts: " << burst->GetNPackets()
92 << ", connection: " << connection->GetTypeStr()
93 << ", CID: " << connection->GetCid());
94 if (connection->GetType() == Cid::TRANSPORT)
95 {
96 NS_LOG_INFO(", SFID: " << connection->GetServiceFlow()->GetSfid() << ", service: "
97 << connection->GetServiceFlow()->GetSchedulingTypeStr());
98 }
99 NS_LOG_INFO(", modulation: " << modulationType << ", DIUC: " << (uint32_t)diuc);
100
101 m_downlinkBursts->emplace_back(dlMapIe, burst);
102}
103
104void
106{
107 Ptr<WimaxConnection> connection;
110 uint32_t nrSymbolsRequired = 0;
112 Ptr<Packet> packet;
113 Ptr<PacketBurst> burst;
115 uint32_t availableSymbols = GetBs()->GetNrDlSymbols();
116
117 while (SelectConnection(connection))
118 {
119 if (connection != GetBs()->GetInitialRangingConnection() &&
120 connection != GetBs()->GetBroadcastConnection())
121 {
122 /* determines modulation/DIUC only once per burst as it is always same for a particular
123 * CID */
124 if (connection->GetType() == Cid::MULTICAST)
125 {
126 modulationType = connection->GetServiceFlow()->GetModulation();
127 }
128 else
129 {
130 modulationType =
131 GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
132 }
133 diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
134 modulationType,
136 }
137 else if (connection == GetBs()->GetInitialRangingConnection() ||
138 connection == GetBs()->GetBroadcastConnection())
139 {
140 modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
142 }
143
144 if (connection->GetType() == Cid::TRANSPORT || connection->GetType() == Cid::MULTICAST)
145 {
146 schedulingType = (ServiceFlow::SchedulingType)connection->GetSchedulingType();
147 }
148
149 if (schedulingType == ServiceFlow::SF_TYPE_UGS)
150 {
151 nrSymbolsRequired = connection->GetServiceFlow()->GetRecord()->GetGrantSize();
152 if (nrSymbolsRequired < availableSymbols)
153 {
154 burst =
155 CreateUgsBurst(connection->GetServiceFlow(), modulationType, nrSymbolsRequired);
156 }
157 else
158 {
159 burst =
160 CreateUgsBurst(connection->GetServiceFlow(), modulationType, availableSymbols);
161 }
162 if (burst->GetNPackets() != 0)
163 {
164 uint32_t BurstSizeSymbols =
165 GetBs()->GetPhy()->GetNrSymbols(burst->GetSize(), modulationType);
166 AddDownlinkBurst(connection, diuc, modulationType, burst);
167
168 if (availableSymbols <= BurstSizeSymbols)
169 {
170 availableSymbols -=
171 BurstSizeSymbols; /// \todo Overflows but don't know how to fix
172 break;
173 }
174 }
175 }
176 else
177 {
178 burst = Create<PacketBurst>();
179 while (connection->HasPackets())
180 {
181 uint32_t FirstPacketSize = connection->GetQueue()->GetFirstPacketRequiredByte(
183 nrSymbolsRequired =
184 GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
185 if (availableSymbols < nrSymbolsRequired &&
186 CheckForFragmentation(connection, availableSymbols, modulationType))
187 {
188 uint32_t availableByte =
189 GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
190 packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
191 availableSymbols = 0;
192 }
193 else if (availableSymbols >= nrSymbolsRequired)
194 {
195 packet = connection->Dequeue();
196 availableSymbols -= nrSymbolsRequired;
197 }
198 else
199 {
200 break;
201 }
202 burst->AddPacket(packet);
203 }
204 AddDownlinkBurst(connection, diuc, modulationType, burst);
205 }
206 if (availableSymbols == 0)
207 {
208 break;
209 }
210 }
211
212 if (!m_downlinkBursts->empty())
213 {
215 "BS scheduler, number of bursts: "
216 << m_downlinkBursts->size() << ", symbols left: " << availableSymbols << std::endl
217 << "BS scheduler, queues:"
218 << " IR " << GetBs()->GetInitialRangingConnection()->GetQueue()->GetSize()
219 << " broadcast " << GetBs()->GetBroadcastConnection()->GetQueue()->GetSize()
220 << " basic "
221 << GetBs()->GetConnectionManager()->GetNPackets(Cid::BASIC, ServiceFlow::SF_TYPE_NONE)
222 << " primary "
223 << GetBs()->GetConnectionManager()->GetNPackets(Cid::PRIMARY, ServiceFlow::SF_TYPE_NONE)
224 << " transport "
225 << GetBs()->GetConnectionManager()->GetNPackets(Cid::TRANSPORT,
227 }
228}
229
230bool
232{
233 connection = nullptr;
234 Time currentTime = Simulator::Now();
235 ServiceFlowRecord* serviceFlowRecord;
236 NS_LOG_INFO("BS Scheduler: Selecting connection...");
237 if (GetBs()->GetBroadcastConnection()->HasPackets())
238 {
239 NS_LOG_INFO("Return GetBroadcastConnection");
240 connection = GetBs()->GetBroadcastConnection();
241 return true;
242 }
243 else if (GetBs()->GetInitialRangingConnection()->HasPackets())
244 {
245 NS_LOG_INFO("Return GetInitialRangingConnection");
246 connection = GetBs()->GetInitialRangingConnection();
247 return true;
248 }
249 else
250 {
251 std::vector<Ptr<WimaxConnection>> connections;
252 std::vector<ServiceFlow*> serviceFlows;
253
254 connections = GetBs()->GetConnectionManager()->GetConnections(Cid::BASIC);
255 for (auto iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
256 {
257 if ((*iter1)->HasPackets())
258 {
259 NS_LOG_INFO("Return Basic");
260 connection = *iter1;
261 return true;
262 }
263 }
264
265 connections = GetBs()->GetConnectionManager()->GetConnections(Cid::PRIMARY);
266 for (auto iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
267 {
268 if ((*iter1)->HasPackets())
269 {
270 NS_LOG_INFO("Return Primary");
271 connection = *iter1;
272 return true;
273 }
274 }
275
276 serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_UGS);
277 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
278 {
279 serviceFlowRecord = (*iter2)->GetRecord();
280 NS_LOG_INFO("processing UGS: HAS PACKET="
281 << (*iter2)->HasPackets() << "max Latency = "
282 << MilliSeconds((*iter2)->GetMaximumLatency()) << "Delay = "
283 << ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
284 GetBs()->GetPhy()->GetFrameDuration()));
285 // if latency would exceed in case grant is allocated in next frame then allocate in
286 // current frame
287 if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
288 GetBs()->GetPhy()->GetFrameDuration()) >
289 MilliSeconds((*iter2)->GetMaximumLatency()))
290 {
291 serviceFlowRecord->SetDlTimeStamp(currentTime);
292 connection = (*iter2)->GetConnection();
293 NS_LOG_INFO("Return UGS SF: CID = " << (*iter2)->GetCid()
294 << "SFID = " << (*iter2)->GetSfid());
295 return true;
296 }
297 }
298
299 serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
300 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
301 {
302 serviceFlowRecord = (*iter2)->GetRecord();
303 // if latency would exceed in case poll is allocated in next frame then allocate in
304 // current frame
305 if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
306 GetBs()->GetPhy()->GetFrameDuration()) >
307 MilliSeconds((*iter2)->GetMaximumLatency()))
308 {
309 serviceFlowRecord->SetDlTimeStamp(currentTime);
310 connection = (*iter2)->GetConnection();
311 NS_LOG_INFO("Return RTPS SF: CID = " << (*iter2)->GetCid()
312 << "SFID = " << (*iter2)->GetSfid());
313 return true;
314 }
315 }
316
317 serviceFlows =
318 GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_NRTPS);
319 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
320 {
321 // unused: serviceFlowRecord = (*iter2)->GetRecord ();
322 if ((*iter2)->HasPackets())
323 {
324 NS_LOG_INFO("Return NRTPS SF: CID = " << (*iter2)->GetCid()
325 << "SFID = " << (*iter2)->GetSfid());
326 connection = (*iter2)->GetConnection();
327 return true;
328 }
329 }
330
331 serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_BE);
332 for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
333 {
334 // unused: serviceFlowRecord = (*iter2)->GetRecord ();
335 if ((*iter2)->HasPackets())
336 {
337 NS_LOG_INFO("Return BE SF: CID = " << (*iter2)->GetCid()
338 << "SFID = " << (*iter2)->GetSfid());
339 connection = (*iter2)->GetConnection();
340 return true;
341 }
342 }
343 }
344 NS_LOG_INFO("NO connection is selected!");
345 return false;
346}
347
350 WimaxPhy::ModulationType modulationType,
351 uint32_t availableSymbols)
352{
353 Time timeStamp;
355 Ptr<Packet> packet;
357 uint32_t nrSymbolsRequired = 0;
358
359 // serviceFlow->CleanUpQueue ();
360 Ptr<WimaxConnection> connection = serviceFlow->GetConnection();
361 while (serviceFlow->HasPackets())
362 {
363 uint32_t FirstPacketSize =
364 connection->GetQueue()->GetFirstPacketRequiredByte(MacHeaderType::HEADER_TYPE_GENERIC);
365 nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
366 if (availableSymbols < nrSymbolsRequired &&
367 CheckForFragmentation(connection, availableSymbols, modulationType))
368 {
369 uint32_t availableByte =
370 GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
371 packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
372 availableSymbols = 0;
373 }
374 else
375 {
376 packet = connection->Dequeue();
377 availableSymbols -= nrSymbolsRequired;
378 }
379 burst->AddPacket(packet);
380 if (availableSymbols <= 0)
381 {
382 break;
383 }
384 }
385 return burst;
386}
387
388} // namespace ns3
BaseStation Scheduler.
virtual Ptr< BaseStationNetDevice > GetBs()
Get the base station.
virtual void SetBs(Ptr< BaseStationNetDevice > bs)
Set the base station.
bool CheckForFragmentation(Ptr< WimaxConnection > connection, int availableSymbols, WimaxPhy::ModulationType modulationType)
Check if the packet fragmentation is possible for transport connection.
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:34
@ TRANSPORT
Definition cid.h:35
@ MULTICAST
Definition cid.h:36
@ BASIC
Definition cid.h:33
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 forLocal and...
this class implement a burst as a list of packets
Smart pointer class similar to boost::intrusive_ptr.
This class implements service flows as described by the IEEE-802.16 standard.
SchedulingType
section 11.13.11 Service flow scheduling type, page 701
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:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
ModulationType
ModulationType enumeration.
Definition wimax-phy.h:43
@ MODULATION_TYPE_BPSK_12
Definition wimax-phy.h:44
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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.
STL namespace.