A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
network-controller-components.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 University of Padova
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Davide Magrin <magrinda@dei.unipd.it>
7 */
8
10
11namespace ns3
12{
13namespace lorawan
14{
15
16NS_LOG_COMPONENT_DEFINE("NetworkControllerComponent");
17
19
20TypeId
22{
23 static TypeId tid =
24 TypeId("ns3::NetworkControllerComponent").SetParent<Object>().SetGroupName("lorawan");
25 return tid;
26}
27
31
35
36////////////////////////////////
37// ConfirmedMessagesComponent //
38////////////////////////////////
41{
42 static TypeId tid = TypeId("ns3::ConfirmedMessagesComponent")
44 .AddConstructor<ConfirmedMessagesComponent>()
45 .SetGroupName("lorawan");
46 return tid;
47}
48
52
56
57void
60 Ptr<NetworkStatus> networkStatus)
61{
62 NS_LOG_FUNCTION(this->GetTypeId() << packet << networkStatus);
63
64 // Check whether the received packet requires an acknowledgment.
66 LoraFrameHeader fHdr;
67 fHdr.SetAsUplink();
68 Ptr<Packet> myPacket = packet->Copy();
69 myPacket->RemoveHeader(mHdr);
70 myPacket->RemoveHeader(fHdr);
71
72 NS_LOG_INFO("Received packet Mac Header: " << mHdr);
73 NS_LOG_INFO("Received packet Frame Header: " << fHdr);
74
76 {
77 NS_LOG_INFO("Packet requires confirmation");
78
79 // Set up the ACK bit on the reply
80 status->m_reply.frameHeader.SetAsDownlink();
81 status->m_reply.frameHeader.SetAck(true);
82 status->m_reply.frameHeader.SetAddress(fHdr.GetAddress());
83 status->m_reply.macHeader.SetMType(LorawanMacHeader::UNCONFIRMED_DATA_DOWN);
84 status->m_reply.needsReply = true;
85
86 // Note that the acknowledgment procedure dies here: "Acknowledgments
87 // are only snt in response to the latest message received and are never
88 // retransmitted". We interpret this to mean that only the current
89 // reception window can be used, and that the Ack field should be
90 // emptied in case transmission cannot be performed in the current
91 // window. Because of this, in this component's OnFailedReply method we
92 // void the ack bits.
93 }
94 else if (fHdr.GetAdrAckReq())
95 {
96 NS_LOG_INFO("Packet has ADRACKReq bit set");
97
98 // Configure reply
99 status->m_reply.frameHeader.SetAsDownlink();
100 status->m_reply.frameHeader.SetAck(false);
101 status->m_reply.frameHeader.SetAddress(fHdr.GetAddress());
102 status->m_reply.macHeader.SetMType(LorawanMacHeader::UNCONFIRMED_DATA_DOWN);
103 status->m_reply.needsReply = true;
104 }
105}
106
107void
109 Ptr<NetworkStatus> networkStatus)
110{
111 NS_LOG_FUNCTION(this << status << networkStatus);
112 // Nothing to do in this case
113}
114
115void
117 Ptr<NetworkStatus> networkStatus)
118{
119 NS_LOG_FUNCTION(this << networkStatus);
120
121 // Empty the Ack bit.
122 status->m_reply.frameHeader.SetAck(false);
123}
124
125////////////////////////
126// LinkCheckComponent //
127////////////////////////
128TypeId
130{
131 static TypeId tid = TypeId("ns3::LinkCheckComponent")
133 .AddConstructor<LinkCheckComponent>()
134 .SetGroupName("lorawan");
135 return tid;
136}
137
141
145
146void
149 Ptr<NetworkStatus> networkStatus)
150{
151 NS_LOG_FUNCTION(this->GetTypeId() << packet << networkStatus);
152
153 // We will only act just before reply, when all Gateways will have received
154 // the packet.
155}
156
157void
159 Ptr<NetworkStatus> networkStatus)
160{
161 NS_LOG_FUNCTION(this << status << networkStatus);
162
163 Ptr<Packet> myPacket = status->GetLastPacketReceivedFromDevice()->Copy();
164 LorawanMacHeader mHdr;
165 LoraFrameHeader fHdr;
166 fHdr.SetAsUplink();
167 myPacket->RemoveHeader(mHdr);
168 myPacket->RemoveHeader(fHdr);
169
171
172 // GetMacCommand returns 0 if no command is found
173 if (command)
174 {
175 status->m_reply.needsReply = true;
176
177 auto info = status->GetLastReceivedPacketInfo();
178
179 // Adapted from: github.com/chirpstack/chirpstack v4.9.0
180
181 // Get the best demodulation margin of the most recent LinkCheckReq command
182 double maxRssi = -1e3;
183 for (const auto& [_, gwRxData] : info.gwList)
184 {
185 if (gwRxData.rxPower > maxRssi)
186 {
187 maxRssi = gwRxData.rxPower;
188 }
189 }
190 /// @see ns3::lorawan::AdrComponent::RxPowerToSNR
191 double maxSnr = maxRssi + 174 - 10 * log10(125000) - 6;
192 /// @todo make this a global PHY constant, manage unknown sf values
193 double requiredSnr[] = {-20.0, -17.5, -15.0, -12.5, -10.0, -7.5, -5};
194 double diff = maxSnr - requiredSnr[12 - info.sf];
195 uint8_t margin = (diff < 0) ? 0 : (diff > 254) ? 254 : diff;
196
197 // Get the number of gateways that received the most recent LinkCheckReq command
198 uint8_t gwCount = info.gwList.size();
199
200 auto replyCommand = Create<LinkCheckAns>(margin, gwCount);
201 status->m_reply.frameHeader.SetAsDownlink();
202 status->m_reply.frameHeader.AddCommand(replyCommand);
203 status->m_reply.macHeader.SetMType(LorawanMacHeader::UNCONFIRMED_DATA_DOWN);
204 }
205 else
206 {
207 // Do nothing
208 }
209}
210
211void
213{
214 NS_LOG_FUNCTION(this->GetTypeId() << networkStatus);
215}
216} // namespace lorawan
217} // namespace ns3
Object()
Constructor.
Definition object.cc:96
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
void BeforeSendingReply(Ptr< EndDeviceStatus > status, Ptr< NetworkStatus > networkStatus) override
Function called as a downlink reply is about to leave the NetworkServer application.
void OnFailedReply(Ptr< EndDeviceStatus > status, Ptr< NetworkStatus > networkStatus) override
Method that is called when a packet cannot be sent in the downlink.
void OnReceivedPacket(Ptr< const Packet > packet, Ptr< EndDeviceStatus > status, Ptr< NetworkStatus > networkStatus) override
This method checks whether the received packet requires an acknowledgment and sets up the appropriate...
This class represents the Frame header (FHDR) used in a LoraWAN network.
Ptr< T > GetMacCommand()
Return a pointer to the first MacCommand of type T, or 0 if no such MacCommand exists in this header.
bool GetAdrAckReq() const
Get the value of the ADRACKReq bit field.
void SetAsUplink()
State that this is an uplink message.
LoraDeviceAddress GetAddress() const
Get this header's device address value.
This class represents the Mac header of a LoRaWAN packet.
uint8_t GetMType() const
Get the message type from the header.
Generic class describing a component of the NetworkController.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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: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:439
Every class exported by the ns3 library is enclosed in the ns3 namespace.