Loading...
Searching...
No Matches
lora-frame-header.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
21#include "lora-frame-header.h"
22
23#include "ns3/log.h"
24
25#include <bitset>
26#include <iostream>
27#include <list>
28#include <ostream>
29
30namespace ns3
31{
32
33NS_LOG_COMPONENT_DEFINE("LoraFrameHeader");
34
35// Initialization list
37 : m_fPort(0),
39 m_adr(0),
40 m_adrAckReq(0),
41 m_ack(0),
42 m_fPending(0),
43 m_fOptsLen(0),
44 m_fCnt(0)
45{
46}
47
51
52TypeId
54{
55 static TypeId tid =
56 TypeId("LoraFrameHeader").SetParent<Header>().AddConstructor<LoraFrameHeader>();
57 return tid;
58}
59
60TypeId
62{
63 return GetTypeId();
64}
65
66uint32_t
68{
69 NS_LOG_FUNCTION_NOARGS();
70
71 // Sizes in bytes:
72 // 4 for DevAddr + 1 for FCtrl + 2 for FCnt + 1 for FPort + 0-15 for FOpts
73 uint32_t size = 8 + m_fOptsLen;
74
75 NS_LOG_INFO("LoraFrameHeader serialized size: " << size);
76
77 return size;
78}
79
80void
81LoraFrameHeader::Serialize(Buffer::Iterator start) const
82{
83 NS_LOG_FUNCTION_NOARGS();
84
85 // Device Address field
86 start.WriteU32(m_address.Get());
87
88 // fCtrl field
89 uint8_t fCtrl = 0;
90 fCtrl |= uint8_t(m_adr << 6 & 0b1000000);
91 fCtrl |= uint8_t(m_adrAckReq << 5 & 0b100000);
92 fCtrl |= uint8_t(m_ack << 4 & 0b10000);
93 fCtrl |= uint8_t(m_fPending << 3 & 0b1000);
94 fCtrl |= m_fOptsLen & 0b111;
95 start.WriteU8(fCtrl);
96
97 // FCnt field
98 start.WriteU16(m_fCnt);
99
100 // FOpts field
101 for (auto it = m_macCommands.begin(); it != m_macCommands.end(); it++)
102 {
103 NS_LOG_DEBUG("Serializing a MAC command");
104 (*it)->Serialize(start);
105 }
106
107 // FPort
108 start.WriteU8(m_fPort);
109}
110
111uint32_t
112LoraFrameHeader::Deserialize(Buffer::Iterator start)
113{
114 NS_LOG_FUNCTION_NOARGS();
115
116 // Empty the list of MAC commands
117 m_macCommands.clear();
118
119 // Read from buffer and save into local variables
120 m_address.Set(start.ReadU32());
121 uint8_t fCtl = start.ReadU8();
122 m_adr = (fCtl >> 6) & 0b1;
123 m_adrAckReq = (fCtl >> 5) & 0b1;
124 m_ack = (fCtl >> 4) & 0b1;
125 m_fPending = (fCtl >> 3) & 0b1;
126 m_fOptsLen = fCtl & 0b111;
127 m_fCnt = start.ReadU16();
128
129 NS_LOG_DEBUG("Deserialized data: ");
130 NS_LOG_DEBUG("Address: " << m_address.Print());
131 NS_LOG_DEBUG("ADR: " << unsigned(m_adr));
132 NS_LOG_DEBUG("ADRAckReq: " << unsigned(m_adrAckReq));
133 NS_LOG_DEBUG("Ack: " << unsigned(m_ack));
134 NS_LOG_DEBUG("fPending: " << unsigned(m_fPending));
135 NS_LOG_DEBUG("fOptsLen: " << unsigned(m_fOptsLen));
136 NS_LOG_DEBUG("fCnt: " << unsigned(m_fCnt));
137
138 // Deserialize MAC commands
139 NS_LOG_DEBUG("Starting deserialization of MAC commands");
140 for (uint8_t byteNumber = 0; byteNumber < m_fOptsLen;)
141 {
142 uint8_t cid = start.PeekU8();
143 NS_LOG_DEBUG("CID: " << unsigned(cid));
144
145 // Divide Uplink and Downlink messages
146 // This needs to be done because they have the same CID, and the context
147 // about where this message will be Serialized/Deserialized (i.e., at the
148 // ED or at the NS) is umportant.
149 if (m_isUplink)
150 {
151 switch (cid)
152 {
153 // In the case of Uplink messages, the NS will deserialize the
154 // request for a link check
155 case (0x02): {
156 NS_LOG_DEBUG("Creating a LinkCheckReq command");
157 Ptr<LinkCheckReq> command = CreateObject<LinkCheckReq>();
158 byteNumber += command->Deserialize(start);
159 m_macCommands.push_back(command);
160 break;
161 }
162 case (0x03): {
163 NS_LOG_DEBUG("Creating a LinkAdrAns command");
164 Ptr<LinkAdrAns> command = CreateObject<LinkAdrAns>();
165 byteNumber += command->Deserialize(start);
166 m_macCommands.push_back(command);
167 break;
168 }
169 case (0x04): {
170 NS_LOG_DEBUG("Creating a DutyCycleAns command");
171 Ptr<DutyCycleAns> command = CreateObject<DutyCycleAns>();
172 byteNumber += command->Deserialize(start);
173 m_macCommands.push_back(command);
174 break;
175 }
176 case (0x05): {
177 NS_LOG_DEBUG("Creating a RxParamSetupAns command");
178 Ptr<RxParamSetupAns> command = CreateObject<RxParamSetupAns>();
179 byteNumber += command->Deserialize(start);
180 m_macCommands.push_back(command);
181 break;
182 }
183 case (0x06): {
184 NS_LOG_DEBUG("Creating a DevStatusAns command");
185 Ptr<DevStatusAns> command = CreateObject<DevStatusAns>();
186 byteNumber += command->Deserialize(start);
187 m_macCommands.push_back(command);
188 break;
189 }
190 case (0x07): {
191 NS_LOG_DEBUG("Creating a NewChannelAns command");
192 Ptr<NewChannelAns> command = CreateObject<NewChannelAns>();
193 byteNumber += command->Deserialize(start);
194 m_macCommands.push_back(command);
195 break;
196 }
197 case (0x08): {
198 NS_LOG_DEBUG("Creating a RxTimingSetupAns command");
199 Ptr<RxTimingSetupAns> command = CreateObject<RxTimingSetupAns>();
200 byteNumber += command->Deserialize(start);
201 m_macCommands.push_back(command);
202 break;
203 }
204 case (0x09): {
205 NS_LOG_DEBUG("Creating a TxParamSetupAns command");
206 Ptr<TxParamSetupAns> command = CreateObject<TxParamSetupAns>();
207 byteNumber += command->Deserialize(start);
208 m_macCommands.push_back(command);
209 break;
210 }
211 case (0x0A): {
212 NS_LOG_DEBUG("Creating a DlChannelAns command");
213 Ptr<DlChannelAns> command = CreateObject<DlChannelAns>();
214 byteNumber += command->Deserialize(start);
215 m_macCommands.push_back(command);
216 break;
217 }
218 default: {
219 NS_LOG_ERROR("CID not recognized during deserialization");
220 }
221 }
222 }
223 else
224 {
225 switch (cid)
226 {
227 // In the case of Downlink messages, the ED will deserialize the
228 // answer to a link check
229 case (0x02): {
230 NS_LOG_DEBUG("Creating a LinkCheckAns command");
231 Ptr<LinkCheckAns> command = CreateObject<LinkCheckAns>();
232 byteNumber += command->Deserialize(start);
233 m_macCommands.push_back(command);
234 break;
235 }
236 case (0x03): {
237 NS_LOG_DEBUG("Creating a LinkAdrReq command");
238 Ptr<LinkAdrReq> command = CreateObject<LinkAdrReq>();
239 byteNumber += command->Deserialize(start);
240 m_macCommands.push_back(command);
241 break;
242 }
243 case (0x04): {
244 NS_LOG_DEBUG("Creating a DutyCycleReq command");
245 Ptr<DutyCycleReq> command = CreateObject<DutyCycleReq>();
246 byteNumber += command->Deserialize(start);
247 m_macCommands.push_back(command);
248 break;
249 }
250 case (0x05): {
251 NS_LOG_DEBUG("Creating a RxParamSetupReq command");
252 Ptr<RxParamSetupReq> command = CreateObject<RxParamSetupReq>();
253 byteNumber += command->Deserialize(start);
254 m_macCommands.push_back(command);
255 break;
256 }
257 case (0x06): {
258 NS_LOG_DEBUG("Creating a DevStatusReq command");
259 Ptr<DevStatusReq> command = CreateObject<DevStatusReq>();
260 byteNumber += command->Deserialize(start);
261 m_macCommands.push_back(command);
262 break;
263 }
264 case (0x07): {
265 NS_LOG_DEBUG("Creating a NewChannelReq command");
266 Ptr<NewChannelReq> command = CreateObject<NewChannelReq>();
267 byteNumber += command->Deserialize(start);
268 m_macCommands.push_back(command);
269 break;
270 }
271 case (0x08): {
272 NS_LOG_DEBUG("Creating a RxTimingSetupReq command");
273 Ptr<RxTimingSetupReq> command = CreateObject<RxTimingSetupReq>();
274 byteNumber += command->Deserialize(start);
275 m_macCommands.push_back(command);
276 break;
277 }
278 case (0x09): {
279 NS_LOG_DEBUG("Creating a TxParamSetupReq command");
280 Ptr<TxParamSetupReq> command = CreateObject<TxParamSetupReq>();
281 byteNumber += command->Deserialize(start);
282 m_macCommands.push_back(command);
283 break;
284 }
285 default: {
286 NS_LOG_ERROR("CID not recognized during deserialization");
287 }
288 }
289 }
290 }
291
292 m_fPort = uint8_t(start.ReadU8());
293
294 return 8 + m_fOptsLen; // the number of bytes consumed.
295}
296
297void
298LoraFrameHeader::Print(std::ostream& os) const
299{
300 NS_LOG_FUNCTION_NOARGS();
301
302 os << "Address=" << m_address.Print() << std::endl;
303 os << "ADR=" << m_adr << std::endl;
304 os << "ADRAckReq=" << m_adrAckReq << std::endl;
305 os << "ACK=" << m_ack << std::endl;
306 os << "FPending=" << m_fPending << std::endl;
307 os << "FOptsLen=" << unsigned(m_fOptsLen) << std::endl;
308 os << "FCnt=" << unsigned(m_fCnt) << std::endl;
309
310 for (auto it = m_macCommands.begin(); it != m_macCommands.end(); it++)
311 {
312 (*it)->Print(os);
313 }
314
315 os << "FPort=" << unsigned(m_fPort) << std::endl;
316}
317
318void
320{
321 NS_LOG_FUNCTION_NOARGS();
322
323 m_isUplink = true;
324}
325
326void
328{
329 NS_LOG_FUNCTION_NOARGS();
330
331 m_isUplink = false;
332}
333
334void
336{
337 m_fPort = fPort;
338}
339
340uint8_t
342{
343 return m_fPort;
344}
345
346void
351
354{
355 return m_address;
356}
357
358void
360{
361 NS_LOG_FUNCTION(this << adr);
362 m_adr = adr;
363}
364
365bool
367{
368 return m_adr;
369}
370
371void
373{
374 m_adrAckReq = adrAckReq;
375}
376
377bool
379{
380 return m_adrAckReq;
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << ack);
387 m_ack = ack;
388}
389
390bool
392{
393 return m_ack;
394}
395
396void
398{
399 m_fPending = fPending;
400}
401
402bool
404{
405 return m_fPending;
406}
407
408uint8_t
410{
411 // Sum the serialized lenght of all commands in the list
412 uint8_t fOptsLen = 0;
413 std::list<Ptr<LorawanMacCommand>>::const_iterator it;
414 for (it = m_macCommands.begin(); it != m_macCommands.end(); it++)
415 {
416 fOptsLen = fOptsLen + (*it)->GetSerializedSize();
417 }
418 return fOptsLen;
419}
420
421void
423{
424 m_fCnt = fCnt;
425}
426
427uint16_t
429{
430 return m_fCnt;
431}
432
433void
435{
436 NS_LOG_FUNCTION_NOARGS();
437
438 Ptr<LinkCheckReq> command = CreateObject<LinkCheckReq>();
439 m_macCommands.push_back(command);
440
441 NS_LOG_DEBUG("Command SerializedSize: " << unsigned(command->GetSerializedSize()));
442 m_fOptsLen += command->GetSerializedSize();
443}
444
445void
446LoraFrameHeader::AddLinkCheckAns(uint8_t margin, uint8_t gwCnt)
447{
448 NS_LOG_FUNCTION(this << unsigned(margin) << unsigned(gwCnt));
449
450 Ptr<LinkCheckAns> command = CreateObject<LinkCheckAns>(margin, gwCnt);
451 m_macCommands.push_back(command);
452
453 m_fOptsLen += command->GetSerializedSize();
454}
455
456void
458 uint8_t txPower,
459 std::list<int> enabledChannels,
460 int repetitions)
461{
462 NS_LOG_FUNCTION(this << unsigned(dataRate) << txPower << repetitions);
463
464 uint16_t channelMask = 0;
465 for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++)
466 {
467 NS_ASSERT((*it) < 16 && (*it) > -1);
468
469 channelMask |= 0b1 << (*it);
470 }
471
472 // TODO Implement chMaskCntl field
473
474 NS_LOG_DEBUG("Creating LinkAdrReq with: DR = " << unsigned(dataRate)
475 << " and txPower = " << unsigned(txPower));
476
477 Ptr<LinkAdrReq> command =
478 CreateObject<LinkAdrReq>(dataRate, txPower, channelMask, 0, repetitions);
479 m_macCommands.push_back(command);
480
481 m_fOptsLen += command->GetSerializedSize();
482}
483
484void
485LoraFrameHeader::AddLinkAdrAns(bool powerAck, bool dataRateAck, bool channelMaskAck)
486{
487 NS_LOG_FUNCTION(this << powerAck << dataRateAck << channelMaskAck);
488
489 Ptr<LinkAdrAns> command = CreateObject<LinkAdrAns>(powerAck, dataRateAck, channelMaskAck);
490 m_macCommands.push_back(command);
491
492 m_fOptsLen += command->GetSerializedSize();
493}
494
495void
497{
498 NS_LOG_FUNCTION(this << unsigned(dutyCycle));
499
500 Ptr<DutyCycleReq> command = CreateObject<DutyCycleReq>(dutyCycle);
501
502 m_macCommands.push_back(command);
503
504 m_fOptsLen += command->GetSerializedSize();
505}
506
507void
509{
510 NS_LOG_FUNCTION(this);
511
512 Ptr<DutyCycleAns> command = CreateObject<DutyCycleAns>();
513
514 m_macCommands.push_back(command);
515
516 m_fOptsLen += command->GetSerializedSize();
517}
518
519void
520LoraFrameHeader::AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency)
521{
522 NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency);
523
524 // Evaluate whether to eliminate this assert in case new offsets can be defined.
525 NS_ASSERT(0 <= rx1DrOffset && rx1DrOffset <= 5);
526
527 Ptr<RxParamSetupReq> command =
528 CreateObject<RxParamSetupReq>(rx1DrOffset, rx2DataRate, frequency);
529
530 m_macCommands.push_back(command);
531
532 m_fOptsLen += command->GetSerializedSize();
533}
534
535void
537{
538 NS_LOG_FUNCTION(this);
539
540 Ptr<RxParamSetupAns> command = CreateObject<RxParamSetupAns>();
541
542 m_macCommands.push_back(command);
543
544 m_fOptsLen += command->GetSerializedSize();
545}
546
547void
549{
550 NS_LOG_FUNCTION(this);
551
552 Ptr<DevStatusReq> command = CreateObject<DevStatusReq>();
553
554 m_macCommands.push_back(command);
555
556 m_fOptsLen += command->GetSerializedSize();
557}
558
559void
561 double frequency,
562 uint8_t minDataRate,
563 uint8_t maxDataRate)
564{
565 NS_LOG_FUNCTION(this);
566
567 Ptr<NewChannelReq> command =
568 CreateObject<NewChannelReq>(chIndex, frequency, minDataRate, maxDataRate);
569
570 m_macCommands.push_back(command);
571
572 m_fOptsLen += command->GetSerializedSize();
573}
574
575std::list<Ptr<LorawanMacCommand>>
577{
578 NS_LOG_FUNCTION_NOARGS();
579
580 return m_macCommands;
581}
582
583void
584LoraFrameHeader::AddCommand(Ptr<LorawanMacCommand> macCommand)
585{
586 NS_LOG_FUNCTION(this << macCommand);
587
588 m_macCommands.push_back(macCommand);
589 m_fOptsLen += macCommand->GetSerializedSize();
590}
591
592} // namespace ns3
This class represents the device address of a LoraWAN End Device.
void SetAddress(LoraDeviceAddress address)
Set the address.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the contents of the buffer into a LoraFrameHeader object.
void AddDevStatusReq()
Add a DevStatusReq command.
virtual TypeId GetInstanceTypeId(void) const
void AddLinkAdrReq(uint8_t dataRate, uint8_t txPower, std::list< int > enabledChannels, int repetitions)
Add a LinkAdrReq command.
void SetAsUplink(void)
State that this is an uplink message.
void SetAck(bool ack)
Set the Ack bit.
bool GetFPending(void) const
Get the FPending value.
uint8_t GetFOptsLen(void) const
Get the FOptsLen value.
void AddCommand(Ptr< LorawanMacCommand > macCommand)
Add a predefined command to the list.
bool GetAdr(void) const
Get the Adr value.
void SetFCnt(uint16_t fCnt)
Set the FCnt value.
void SetAdrAckReq(bool adrAckReq)
Set the AdrAckReq value.
virtual void Serialize(Buffer::Iterator start) const
Serialize the header.
bool GetAck(void) const
Get the Ack bit value.
bool GetAdrAckReq(void) const
Get the AdrAckReq value.
void AddLinkAdrAns(bool powerAck, bool dataRateAck, bool channelMaskAck)
Add a LinkAdrAns command.
virtual void Print(std::ostream &os) const
Print the header in a human-readable format.
void SetFPending(bool fPending)
Set the FPending value.
static TypeId GetTypeId(void)
LoraDeviceAddress m_address
std::list< Ptr< LorawanMacCommand > > GetCommands(void)
Return a list of pointers to all the MAC commands saved in this header.
void AddLinkCheckReq(void)
Add a LinkCheckReq command.
uint8_t GetFPort(void) const
Get the FPort value.
void AddDutyCycleAns(void)
Add a DutyCycleAns command.
std::list< Ptr< LorawanMacCommand > > m_macCommands
List containing all the LorawanMacCommand instances that are contained in this LoraFrameHeader.
virtual uint32_t GetSerializedSize(void) const
Return the size required for serialization of this header.
void AddRxParamSetupAns()
Add a RxParamSetupAns command.
void SetAdr(bool adr)
Set the Adr value.
uint16_t GetFCnt(void) const
Get the FCnt value.
void AddNewChannelReq(uint8_t chIndex, double frequency, uint8_t minDataRate, uint8_t maxDataRate)
Add a NewChannelReq command.
void AddDutyCycleReq(uint8_t dutyCycle)
Add a DutyCycleReq command.
void SetFPort(uint8_t fPort)
Set the FPort value.
void SetAsDownlink(void)
State that this is a downlink message.
LoraDeviceAddress GetAddress(void) const
Get this header's device address value.
void AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency)
Add a RxParamSetupReq command.
void AddLinkCheckAns(uint8_t margin, uint8_t gwCnt)
Add a LinkCheckAns command.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.