lora-network-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 University of Padova
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Davide Magrin <magrinda@dei.unipd.it>
19  *
20  * Modified by: Bastien Tauran <bastien.tauran@viveris.fr>
21  */
22 
23 #include "lora-network-scheduler.h"
24 
25 #include <stdint.h>
26 
27 NS_LOG_COMPONENT_DEFINE("LoraNetworkScheduler");
28 
29 namespace ns3
30 {
31 
32 NS_OBJECT_ENSURE_REGISTERED(LoraNetworkScheduler);
33 
34 TypeId
36 {
37  static TypeId tid =
38  TypeId("ns3::LoraNetworkScheduler")
39  .SetParent<Object>()
40  .AddAttribute("FirstWindowAnswerDelay",
41  "Delay to wait between end of reception of paquet and sending of anwser, "
42  "to be in first window opportunity",
43  TimeValue(Seconds(1)),
45  MakeTimeChecker())
46  .AddAttribute("SecondWindowAnswerDelay",
47  "Delay to wait between end of reception of paquet and sending of anwser, "
48  "to be in second window opportunity",
49  TimeValue(Seconds(2)),
51  MakeTimeChecker())
52  .AddTraceSource("ReceiveWindowOpened",
53  "Trace source that is fired when a receive window opportunity happens.",
54  MakeTraceSourceAccessor(&LoraNetworkScheduler::m_receiveWindowOpened),
55  "ns3::Packet::TracedCallback")
56  .AddConstructor<LoraNetworkScheduler>();
57  return tid;
58 }
59 
60 TypeId
62 {
63  return GetTypeId();
64 }
65 
67 {
68 }
69 
70 LoraNetworkScheduler::LoraNetworkScheduler(Ptr<LoraNetworkStatus> status,
71  Ptr<LoraNetworkController> controller)
72  : m_status(status),
73  m_controller(controller),
74  m_firstWindowAnswerDelay(Seconds(1)),
75  m_secondWindowAnswerDelay(Seconds(2))
76 {
77  ObjectBase::ConstructSelf(AttributeConstructionList());
78 
80  "First window answer delay must be lower than second window answer delay");
81 }
82 
84 {
85 }
86 
87 void
88 LoraNetworkScheduler::OnReceivedPacket(Ptr<const Packet> packet)
89 {
90  NS_LOG_FUNCTION(packet);
91 
92  // Get the current packet's frame counter
93  Ptr<Packet> packetCopy = packet->Copy();
94  LorawanMacHeader receivedMacHdr;
95  packetCopy->RemoveHeader(receivedMacHdr);
96  LoraFrameHeader receivedFrameHdr;
97  receivedFrameHdr.SetAsUplink();
98  packetCopy->RemoveHeader(receivedFrameHdr);
99 
100  // Need to decide whether to schedule a receive window
101  if (!m_status->GetEndDeviceStatus(packet)->HasReceiveWindowOpportunityScheduled())
102  {
103  // Extract the address
104  LoraDeviceAddress deviceAddress = receivedFrameHdr.GetAddress();
105 
106  // Schedule OnReceiveWindowOpportunity event
107  m_status->GetEndDeviceStatus(packet)->SetReceiveWindowOpportunity(
108  Simulator::Schedule(m_firstWindowAnswerDelay,
110  this,
111  deviceAddress,
112  1));
113  }
114 }
115 
116 void
118 {
119  NS_LOG_FUNCTION(deviceAddress);
120 
121  NS_LOG_DEBUG("Opening receive window number " << window << " for device " << deviceAddress);
122 
123  // Check whether we can send a reply to the device, again by using
124  // NetworkStatus
125  Address gwAddress = m_status->GetBestGatewayForDevice(deviceAddress, window);
126 
127  if (gwAddress == Address() && window == 1)
128  {
129  NS_LOG_DEBUG("No suitable gateway found for first window.");
130 
131  // No suitable GW was found, but there's still hope to find one for the
132  // second window.
133  // Schedule another OnReceiveWindowOpportunity event
134  m_status->GetEndDeviceStatus(deviceAddress)
135  ->SetReceiveWindowOpportunity(
136  Simulator::Schedule(m_secondWindowAnswerDelay,
138  this,
139  deviceAddress,
140  2));
141  }
142  else if (gwAddress == Address() && window == 2)
143  {
144  // No suitable GW was found and this was our last opportunity
145  // Simply give up.
146  NS_LOG_DEBUG("Giving up on reply: no suitable gateway was found "
147  << "on the second receive window");
148 
149  // Reset the reply
150  // XXX Should we reset it here or keep it for the next opportunity?
151  m_status->GetEndDeviceStatus(deviceAddress)->RemoveReceiveWindowOpportunity();
152  m_status->GetEndDeviceStatus(deviceAddress)->InitializeReply();
153  }
154  else
155  {
156  // A gateway was found
157 
158  NS_LOG_DEBUG("Found available gateway with address: " << gwAddress);
159 
160  m_controller->BeforeSendingReply(m_status->GetEndDeviceStatus(deviceAddress));
161 
162  // Check whether this device needs a response by querying m_status
163  bool needsReply = m_status->NeedsReply(deviceAddress);
164 
165  if (needsReply)
166  {
167  NS_LOG_INFO("A reply is needed");
168 
169  // Send the reply through that gateway
170  m_status->SendThroughGateway(m_status->GetReplyForDevice(deviceAddress, window),
171  gwAddress);
172 
173  // Reset the reply
174  m_status->GetEndDeviceStatus(deviceAddress)->RemoveReceiveWindowOpportunity();
175  m_status->GetEndDeviceStatus(deviceAddress)->InitializeReply();
176  }
177  }
178 }
179 } // namespace ns3
This class represents the device address of a LoraWAN End Device.
This class represents the Frame header (FHDR) used in a LoraWAN network.
void SetAsUplink(void)
State that this is an uplink message.
LoraDeviceAddress GetAddress(void) const
Get this header's device address value.
Time m_secondWindowAnswerDelay
Delay to wait between end of reception of paquet and sending of anwser, to be in second window opport...
Ptr< LoraNetworkStatus > m_status
void OnReceivedPacket(Ptr< const Packet > packet)
Method called by NetworkServer to inform the Scheduler of a newly arrived uplink packet.
Time m_firstWindowAnswerDelay
Delay to wait between end of reception of paquet and sending of anwser, to be in first window opportu...
TypeId GetInstanceTypeId(void) const
void OnReceiveWindowOpportunity(LoraDeviceAddress deviceAddress, int window)
Method that is scheduled after packet arrivals in order to act on receive windows 1 and 2 seconds lat...
Ptr< LoraNetworkController > m_controller
TracedCallback< Ptr< const Packet > > m_receiveWindowOpened
This class represents the Mac header of a LoRaWAN packet.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.