A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lora-packet-tracker.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 University of Padova
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: Davide Magrin <magrinda@dei.unipd.it>
18 */
19
20#include "lora-packet-tracker.h"
21
22#include "ns3/log.h"
23#include "ns3/lorawan-mac-header.h"
24#include "ns3/simulator.h"
25
26#include <fstream>
27#include <iostream>
28
29namespace ns3
30{
31namespace lorawan
32{
33NS_LOG_COMPONENT_DEFINE("LoraPacketTracker");
34
36{
37 NS_LOG_FUNCTION(this);
38}
39
41{
42 NS_LOG_FUNCTION(this);
43}
44
45/////////////////
46// MAC metrics //
47/////////////////
48
49void
51{
52 if (IsUplink(packet))
53 {
54 NS_LOG_INFO("A new packet was sent by the MAC layer");
55
56 MacPacketStatus status;
57 status.packet = packet;
58 status.sendTime = Simulator::Now();
60 status.receivedTime = Time::Max();
61
62 m_macPacketTracker.insert(std::pair<Ptr<const Packet>, MacPacketStatus>(packet, status));
63 }
64}
65
66void
68 bool success,
69 Time firstAttempt,
70 Ptr<Packet> packet)
71{
72 NS_LOG_INFO("Finished retransmission attempts for a packet");
73 NS_LOG_DEBUG("Packet: " << packet << "ReqTx " << unsigned(reqTx) << ", succ: " << success
74 << ", firstAttempt: " << firstAttempt.GetSeconds());
75
77 entry.firstAttempt = firstAttempt;
78 entry.finishTime = Simulator::Now();
79 entry.reTxAttempts = reqTx;
80 entry.successful = success;
81
82 m_reTransmissionTracker.insert(std::pair<Ptr<Packet>, RetransmissionStatus>(packet, entry));
83}
84
85void
87{
88 if (IsUplink(packet))
89 {
90 NS_LOG_INFO("A packet was successfully received"
91 << " at the MAC layer of gateway " << Simulator::GetContext());
92
93 // Find the received packet in the m_macPacketTracker
94 auto it = m_macPacketTracker.find(packet);
95 if (it != m_macPacketTracker.end())
96 {
97 (*it).second.receptionTimes.insert(
98 std::pair<int, Time>(Simulator::GetContext(), Simulator::Now()));
99 }
100 else
101 {
102 NS_ABORT_MSG("Packet not found in tracker");
103 }
104 }
105}
106
107/////////////////
108// PHY metrics //
109/////////////////
110
111void
113{
114 if (IsUplink(packet))
115 {
116 NS_LOG_INFO("PHY packet " << packet << " was transmitted by device " << edId);
117 // Create a packetStatus
118 PacketStatus status;
119 status.packet = packet;
120 status.sendTime = Simulator::Now();
121 status.senderId = edId;
122
123 m_packetTracker.insert(std::pair<Ptr<const Packet>, PacketStatus>(packet, status));
124 }
125}
126
127void
129{
130 if (IsUplink(packet))
131 {
132 // Remove the successfully received packet from the list of sent ones
133 NS_LOG_INFO("PHY packet " << packet << " was successfully received at gateway " << gwId);
134
135 auto it = m_packetTracker.find(packet);
136 (*it).second.outcomes.insert(std::pair<int, enum PhyPacketOutcome>(gwId, RECEIVED));
137 }
138}
139
140void
142{
143 if (IsUplink(packet))
144 {
145 NS_LOG_INFO("PHY packet " << packet << " was interfered at gateway " << gwId);
146
147 auto it = m_packetTracker.find(packet);
148 (*it).second.outcomes.insert(std::pair<int, enum PhyPacketOutcome>(gwId, INTERFERED));
149 }
150}
151
152void
154{
155 if (IsUplink(packet))
156 {
157 NS_LOG_INFO("PHY packet " << packet << " was lost because no more receivers at gateway "
158 << gwId);
159 auto it = m_packetTracker.find(packet);
160 (*it).second.outcomes.insert(
161 std::pair<int, enum PhyPacketOutcome>(gwId, NO_MORE_RECEIVERS));
162 }
163}
164
165void
167{
168 if (IsUplink(packet))
169 {
170 NS_LOG_INFO("PHY packet " << packet << " was lost because under sensitivity at gateway "
171 << gwId);
172
173 auto it = m_packetTracker.find(packet);
174 (*it).second.outcomes.insert(
175 std::pair<int, enum PhyPacketOutcome>(gwId, UNDER_SENSITIVITY));
176 }
177}
178
179void
181{
182 if (IsUplink(packet))
183 {
185 "PHY packet " << packet
186 << " was lost because of concurrent downlink transmission at gateway "
187 << gwId);
188
189 auto it = m_packetTracker.find(packet);
190 (*it).second.outcomes.insert(std::pair<int, enum PhyPacketOutcome>(gwId, LOST_BECAUSE_TX));
191 }
192}
193
194bool
196{
197 NS_LOG_FUNCTION(this);
198
199 LorawanMacHeader mHdr;
200 Ptr<Packet> copy = packet->Copy();
201 copy->RemoveHeader(mHdr);
202 return mHdr.IsUplink();
203}
204
205////////////////////////
206// Counting Functions //
207////////////////////////
208
209std::vector<int>
211{
212 // Vector packetCounts will contain - for the interval given in the input of
213 // the function, the following fields: totPacketsSent receivedPackets
214 // interferedPackets noMoreGwPackets underSensitivityPackets lostBecauseTxPackets
215
216 std::vector<int> packetCounts(6, 0);
217
218 for (auto itPhy = m_packetTracker.begin(); itPhy != m_packetTracker.end(); ++itPhy)
219 {
220 if ((*itPhy).second.sendTime >= startTime && (*itPhy).second.sendTime <= stopTime)
221 {
222 packetCounts.at(0)++;
223
224 NS_LOG_DEBUG("Dealing with packet " << (*itPhy).second.packet);
225 NS_LOG_DEBUG("This packet was received by " << (*itPhy).second.outcomes.size()
226 << " gateways");
227
228 if ((*itPhy).second.outcomes.count(gwId) > 0)
229 {
230 switch ((*itPhy).second.outcomes.at(gwId))
231 {
232 case RECEIVED: {
233 packetCounts.at(1)++;
234 break;
235 }
236 case INTERFERED: {
237 packetCounts.at(2)++;
238 break;
239 }
240 case NO_MORE_RECEIVERS: {
241 packetCounts.at(3)++;
242 break;
243 }
244 case UNDER_SENSITIVITY: {
245 packetCounts.at(4)++;
246 break;
247 }
248 case LOST_BECAUSE_TX: {
249 packetCounts.at(5)++;
250 break;
251 }
252 case UNSET: {
253 break;
254 }
255 }
256 }
257 }
258 }
259
260 return packetCounts;
261}
262
263std::string
265{
266 // Vector packetCounts will contain - for the interval given in the input of
267 // the function, the following fields: totPacketsSent receivedPackets
268 // interferedPackets noMoreGwPackets underSensitivityPackets lostBecauseTxPackets
269
270 std::vector<int> packetCounts(6, 0);
271
272 for (auto itPhy = m_packetTracker.begin(); itPhy != m_packetTracker.end(); ++itPhy)
273 {
274 if ((*itPhy).second.sendTime >= startTime && (*itPhy).second.sendTime <= stopTime)
275 {
276 packetCounts.at(0)++;
277
278 NS_LOG_DEBUG("Dealing with packet " << (*itPhy).second.packet);
279 NS_LOG_DEBUG("This packet was received by " << (*itPhy).second.outcomes.size()
280 << " gateways");
281
282 if ((*itPhy).second.outcomes.count(gwId) > 0)
283 {
284 switch ((*itPhy).second.outcomes.at(gwId))
285 {
286 case RECEIVED: {
287 packetCounts.at(1)++;
288 break;
289 }
290 case INTERFERED: {
291 packetCounts.at(2)++;
292 break;
293 }
294 case NO_MORE_RECEIVERS: {
295 packetCounts.at(3)++;
296 break;
297 }
298 case UNDER_SENSITIVITY: {
299 packetCounts.at(4)++;
300 break;
301 }
302 case LOST_BECAUSE_TX: {
303 packetCounts.at(5)++;
304 break;
305 }
306 case UNSET: {
307 break;
308 }
309 }
310 }
311 }
312 }
313
314 std::string output("");
315 for (int i = 0; i < 6; ++i)
316 {
317 output += std::to_string(packetCounts.at(i)) + " ";
318 }
319
320 return output;
321}
322
323std::string
325{
326 NS_LOG_FUNCTION(this << startTime << stopTime);
327
328 double sent = 0;
329 double received = 0;
330 for (auto it = m_macPacketTracker.begin(); it != m_macPacketTracker.end(); ++it)
331 {
332 if ((*it).second.sendTime >= startTime && (*it).second.sendTime <= stopTime)
333 {
334 sent++;
335 if (!(*it).second.receptionTimes.empty())
336 {
337 received++;
338 }
339 }
340 }
341
342 return std::to_string(sent) + " " + std::to_string(received);
343}
344
345std::string
347{
348 NS_LOG_FUNCTION(this << startTime << stopTime);
349
350 double sent = 0;
351 double received = 0;
352 for (auto it = m_reTransmissionTracker.begin(); it != m_reTransmissionTracker.end(); ++it)
353 {
354 if ((*it).second.firstAttempt >= startTime && (*it).second.firstAttempt <= stopTime)
355 {
356 sent++;
357 NS_LOG_DEBUG("Found a packet");
358 NS_LOG_DEBUG("Number of attempts: " << unsigned(it->second.reTxAttempts)
359 << ", successful: " << it->second.successful);
360 if (it->second.successful)
361 {
362 received++;
363 }
364 }
365 }
366
367 return std::to_string(sent) + " " + std::to_string(received);
368}
369
370} // namespace lorawan
371} // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static uint32_t GetContext()
Get the current simulation context.
Definition: simulator.cc:318
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:297
void NoMoreReceiversCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a gateway packet loss caused by lack of free reception paths.
void MacTransmissionCallback(Ptr< const Packet > packet)
Trace a packet leaving a node's MAC layer to go down the stack and be sent by the PHY layer.
PhyPacketData m_packetTracker
Packet map of PHY layer metrics.
void RequiredTransmissionsCallback(uint8_t reqTx, bool success, Time firstAttempt, Ptr< Packet > packet)
Trace the exit status of a MAC layer packet retransmission process of an end device.
void UnderSensitivityCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a gateway packet loss caused by signal strength under sensitivity.
void LostBecauseTxCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a gateway packet loss caused by concurrent downlink transmission.
std::vector< int > CountPhyPacketsPerGw(Time startTime, Time stopTime, int systemId)
Count packets in a time interval to evaluate the performance at PHY level of a specific gateway.
std::string PrintPhyPacketsPerGw(Time startTime, Time stopTime, int systemId)
Count packets in a time interval to evaluate the performance at PHY level of a specific gateway.
void MacGwReceptionCallback(Ptr< const Packet > packet)
Trace a packet leaving a gateway's MAC layer to go up the stack and be delivered to the node's applic...
LoraPacketTracker()
Default constructor.
void PacketReceptionCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a correct packet RX by the PHY layer of a gateway.
MacPacketData m_macPacketTracker
Packet map of MAC layer metrics.
std::string CountMacPacketsGlobally(Time startTime, Time stopTime)
In a time interval, count packets to evaluate the global performance at MAC level of the whole networ...
bool IsUplink(Ptr< const Packet > packet)
Check whether a packet is uplink.
void InterferenceCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a gateway packet loss caused by interference.
void TransmissionCallback(Ptr< const Packet > packet, uint32_t systemId)
Trace a packet TX start by the PHY layer of an end device.
RetransmissionData m_reTransmissionTracker
Packet map of retransmission process metrics.
std::string CountMacPacketsGloballyCpsr(Time startTime, Time stopTime)
In a time interval, count packets to evaluate the performance at MAC level of the whole network.
This class represents the Mac header of a LoRaWAN packet.
bool IsUplink() const
Check whether this header is for an uplink message.
Time stopTime
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#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_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Stores MAC-layer packet metrics of sender/receivers.
Ptr< const Packet > packet
Packet being tracked.
Time receivedTime
Time of first reception (placeholder field)
Time sendTime
Timestamp of the pkt leaving MAC layer to go down the stack of sender.
uint32_t senderId
Node id of the packet sender.
Stores PHY-layer uplink packet metrics of sender/receivers.
uint32_t senderId
Node id of the packet sender.
Time sendTime
Timestamp of pkt radio tx start.
Ptr< const Packet > packet
Packet being tracked.
Stores (optionally enabled) MAC layer packet retransmission process metrics of end devices.
Time finishTime
Timestamp of the conclusion of the retransmission process.
Time firstAttempt
Timestamp of the first transmission attempt.
bool successful
Whether the retransmission procedure was successful.
uint8_t reTxAttempts
Number of transmissions attempted during the process.