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 NS_LOG_COMPONENT_DEFINE("LoraNetworkScheduler");
26 
27 namespace ns3
28 {
29 
30 NS_OBJECT_ENSURE_REGISTERED(LoraNetworkScheduler);
31 
32 TypeId
34 {
35  static TypeId tid =
36  TypeId("ns3::LoraNetworkScheduler")
37  .SetParent<Object>()
38  .AddAttribute("FirstWindowAnswerDelay",
39  "Delay to wait between end of reception of paquet and sending of anwser, "
40  "to be in first window opportunity",
41  TimeValue(Seconds(1)),
43  MakeTimeChecker())
44  .AddAttribute("SecondWindowAnswerDelay",
45  "Delay to wait between end of reception of paquet and sending of anwser, "
46  "to be in second window opportunity",
47  TimeValue(Seconds(2)),
49  MakeTimeChecker())
50  .AddTraceSource("ReceiveWindowOpened",
51  "Trace source that is fired when a receive window opportunity happens.",
52  MakeTraceSourceAccessor(&LoraNetworkScheduler::m_receiveWindowOpened),
53  "ns3::Packet::TracedCallback")
54  .AddConstructor<LoraNetworkScheduler>();
55  return tid;
56 }
57 
58 TypeId
60 {
61  return GetTypeId();
62 }
63 
65 {
66 }
67 
68 LoraNetworkScheduler::LoraNetworkScheduler(Ptr<LoraNetworkStatus> status,
69  Ptr<LoraNetworkController> controller)
70  : m_status(status),
71  m_controller(controller),
72  m_firstWindowAnswerDelay(Seconds(1)),
73  m_secondWindowAnswerDelay(Seconds(2))
74 {
75  ObjectBase::ConstructSelf(AttributeConstructionList());
76 }
77 
79 {
80 }
81 
82 void
83 LoraNetworkScheduler::OnReceivedPacket(Ptr<const Packet> packet)
84 {
85  NS_LOG_FUNCTION(packet);
86 
87  // Get the current packet's frame counter
88  Ptr<Packet> packetCopy = packet->Copy();
89  LorawanMacHeader receivedMacHdr;
90  packetCopy->RemoveHeader(receivedMacHdr);
91  LoraFrameHeader receivedFrameHdr;
92  receivedFrameHdr.SetAsUplink();
93  packetCopy->RemoveHeader(receivedFrameHdr);
94 
95  // Need to decide whether to schedule a receive window
96  if (!m_status->GetEndDeviceStatus(packet)->HasReceiveWindowOpportunityScheduled())
97  {
98  // Extract the address
99  LoraDeviceAddress deviceAddress = receivedFrameHdr.GetAddress();
100 
101  // Schedule OnReceiveWindowOpportunity event
102  m_status->GetEndDeviceStatus(packet)->SetReceiveWindowOpportunity(
103  Simulator::Schedule(m_firstWindowAnswerDelay,
105  this,
106  deviceAddress,
107  1));
108  }
109 }
110 
111 void
113 {
114  NS_LOG_FUNCTION(deviceAddress);
115 
116  NS_LOG_DEBUG("Opening receive window number " << window << " for device " << deviceAddress);
117 
118  // Check whether we can send a reply to the device, again by using
119  // NetworkStatus
120  Address gwAddress = m_status->GetBestGatewayForDevice(deviceAddress, window);
121 
122  if (gwAddress == Address() && window == 1)
123  {
124  NS_LOG_DEBUG("No suitable gateway found for first window.");
125 
126  // No suitable GW was found, but there's still hope to find one for the
127  // second window.
128  // Schedule another OnReceiveWindowOpportunity event
129  m_status->GetEndDeviceStatus(deviceAddress)
130  ->SetReceiveWindowOpportunity(
131  Simulator::Schedule(m_secondWindowAnswerDelay,
133  this,
134  deviceAddress,
135  2));
136  }
137  else if (gwAddress == Address() && window == 2)
138  {
139  // No suitable GW was found and this was our last opportunity
140  // Simply give up.
141  NS_LOG_DEBUG("Giving up on reply: no suitable gateway was found "
142  << "on the second receive window");
143 
144  // Reset the reply
145  // XXX Should we reset it here or keep it for the next opportunity?
146  m_status->GetEndDeviceStatus(deviceAddress)->RemoveReceiveWindowOpportunity();
147  m_status->GetEndDeviceStatus(deviceAddress)->InitializeReply();
148  }
149  else
150  {
151  // A gateway was found
152 
153  NS_LOG_DEBUG("Found available gateway with address: " << gwAddress);
154 
155  m_controller->BeforeSendingReply(m_status->GetEndDeviceStatus(deviceAddress));
156 
157  // Check whether this device needs a response by querying m_status
158  bool needsReply = m_status->NeedsReply(deviceAddress);
159 
160  if (needsReply)
161  {
162  NS_LOG_INFO("A reply is needed");
163 
164  // Send the reply through that gateway
165  m_status->SendThroughGateway(m_status->GetReplyForDevice(deviceAddress, window),
166  gwAddress);
167 
168  // Reset the reply
169  m_status->GetEndDeviceStatus(deviceAddress)->RemoveReceiveWindowOpportunity();
170  m_status->GetEndDeviceStatus(deviceAddress)->InitializeReply();
171  }
172  }
173 }
174 } // 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.