A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
olsr-header.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 INESC Porto
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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
18  */
19 
20 #include "olsr-header.h"
21 
22 #include "ns3/assert.h"
23 #include "ns3/log.h"
24 
25 #include <cmath>
26 
27 #define IPV4_ADDRESS_SIZE 4
28 #define OLSR_MSG_HEADER_SIZE 12
29 #define OLSR_PKT_HEADER_SIZE 4
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("OlsrHeader");
35 
36 namespace olsr
37 {
38 
40 #define OLSR_C 0.0625
41 
48 uint8_t
49 SecondsToEmf(double seconds)
50 {
51  int a;
52  int b = 0;
53 
54  NS_ASSERT_MSG(seconds >= OLSR_C, "SecondsToEmf - Can not convert a value less than OLSR_C");
55 
56  // find the largest integer 'b' such that: T/C >= 2^b
57  for (b = 1; (seconds / OLSR_C) >= (1 << b); ++b)
58  {
59  }
60  NS_ASSERT((seconds / OLSR_C) < (1 << b));
61  b--;
62  NS_ASSERT((seconds / OLSR_C) >= (1 << b));
63 
64  // compute the expression 16*(T/(C*(2^b))-1), which may not be a integer
65  double tmp = 16 * (seconds / (OLSR_C * (1 << b)) - 1);
66 
67  // round it up. This results in the value for 'a'
68  a = (int)std::ceil(tmp - 0.5);
69 
70  // if 'a' is equal to 16: increment 'b' by one, and set 'a' to 0
71  if (a == 16)
72  {
73  b += 1;
74  a = 0;
75  }
76 
77  // now, 'a' and 'b' should be integers between 0 and 15,
78  NS_ASSERT(a >= 0 && a < 16);
79  NS_ASSERT(b >= 0 && b < 16);
80 
81  // the field will be a byte holding the value a*16+b
82  return (uint8_t)((a << 4) | b);
83 }
84 
91 double
92 EmfToSeconds(uint8_t olsrFormat)
93 {
94  int a = (olsrFormat >> 4);
95  int b = (olsrFormat & 0xf);
96  // value = C*(1+a/16)*2^b [in seconds]
97  return OLSR_C * (1 + a / 16.0) * (1 << b);
98 }
99 
100 // ---------------- OLSR Packet -------------------------------
101 
102 NS_OBJECT_ENSURE_REGISTERED(PacketHeader);
103 
105 {
106 }
107 
109 {
110 }
111 
112 TypeId
114 {
115  static TypeId tid = TypeId("ns3::olsr::PacketHeader")
116  .SetParent<Header>()
117  .SetGroupName("Olsr")
118  .AddConstructor<PacketHeader>();
119  return tid;
120 }
121 
122 TypeId
124 {
125  return GetTypeId();
126 }
127 
128 uint32_t
130 {
131  return OLSR_PKT_HEADER_SIZE;
132 }
133 
134 void
135 PacketHeader::Print(std::ostream& os) const
136 {
137  os << "len: " << m_packetLength << " seqNo: " << m_packetSequenceNumber;
138 }
139 
140 void
142 {
146 }
147 
148 uint32_t
150 {
154  return GetSerializedSize();
155 }
156 
157 // ---------------- OLSR Message -------------------------------
158 
160 
162  : m_messageType(MessageHeader::MessageType(0))
163 {
164 }
165 
167 {
168 }
169 
170 TypeId
172 {
173  static TypeId tid = TypeId("ns3::olsr::MessageHeader")
174  .SetParent<Header>()
175  .SetGroupName("Olsr")
176  .AddConstructor<MessageHeader>();
177  return tid;
178 }
179 
180 TypeId
182 {
183  return GetTypeId();
184 }
185 
186 uint32_t
188 {
189  uint32_t size = OLSR_MSG_HEADER_SIZE;
190  switch (m_messageType)
191  {
192  case MID_MESSAGE:
193  size += m_message.mid.GetSerializedSize();
194  break;
195  case HELLO_MESSAGE:
196  NS_LOG_DEBUG("Hello Message Size: " << size << " + "
197  << m_message.hello.GetSerializedSize());
198  size += m_message.hello.GetSerializedSize();
199  break;
200  case TC_MESSAGE:
201  size += m_message.tc.GetSerializedSize();
202  break;
203  case HNA_MESSAGE:
204  size += m_message.hna.GetSerializedSize();
205  break;
206  default:
207  NS_ASSERT(false);
208  }
209  return size;
210 }
211 
212 void
213 MessageHeader::Print(std::ostream& os) const
214 {
215  switch (m_messageType)
216  {
217  case HELLO_MESSAGE:
218  os << "type: HELLO";
219  break;
220  case TC_MESSAGE:
221  os << "type: TC";
222  break;
223  case MID_MESSAGE:
224  os << "type: MID";
225  break;
226  case HNA_MESSAGE:
227  os << "type: HNA";
228  break;
229  }
230 
231  os << " TTL: " << +m_timeToLive;
232  os << " Orig: " << m_originatorAddress;
233  os << " SeqNo: " << m_messageSequenceNumber;
234  os << " Validity: " << +m_vTime;
235  os << " Hop count: " << +m_hopCount;
236  os << " Size: " << m_messageSize;
237 
238  switch (m_messageType)
239  {
240  case MID_MESSAGE:
241  m_message.mid.Print(os);
242  break;
243  case HELLO_MESSAGE:
244  m_message.hello.Print(os);
245  break;
246  case TC_MESSAGE:
247  m_message.tc.Print(os);
248  break;
249  case HNA_MESSAGE:
250  m_message.hna.Print(os);
251  break;
252  default:
253  NS_ASSERT(false);
254  }
255 }
256 
257 void
259 {
262  i.WriteU8(m_vTime);
266  i.WriteU8(m_hopCount);
268 
269  switch (m_messageType)
270  {
271  case MID_MESSAGE:
272  m_message.mid.Serialize(i);
273  break;
274  case HELLO_MESSAGE:
275  m_message.hello.Serialize(i);
276  break;
277  case TC_MESSAGE:
278  m_message.tc.Serialize(i);
279  break;
280  case HNA_MESSAGE:
281  m_message.hna.Serialize(i);
282  break;
283  default:
284  NS_ASSERT(false);
285  }
286 }
287 
288 uint32_t
290 {
291  uint32_t size;
295  m_vTime = i.ReadU8();
298  m_timeToLive = i.ReadU8();
299  m_hopCount = i.ReadU8();
301  size = OLSR_MSG_HEADER_SIZE;
302  switch (m_messageType)
303  {
304  case MID_MESSAGE:
305  size += m_message.mid.Deserialize(i, m_messageSize - OLSR_MSG_HEADER_SIZE);
306  break;
307  case HELLO_MESSAGE:
308  size += m_message.hello.Deserialize(i, m_messageSize - OLSR_MSG_HEADER_SIZE);
309  break;
310  case TC_MESSAGE:
311  size += m_message.tc.Deserialize(i, m_messageSize - OLSR_MSG_HEADER_SIZE);
312  break;
313  case HNA_MESSAGE:
314  size += m_message.hna.Deserialize(i, m_messageSize - OLSR_MSG_HEADER_SIZE);
315  break;
316  default:
317  NS_ASSERT(false);
318  }
319  return size;
320 }
321 
322 // ---------------- OLSR MID Message -------------------------------
323 
324 uint32_t
326 {
327  return this->interfaceAddresses.size() * IPV4_ADDRESS_SIZE;
328 }
329 
330 void
331 MessageHeader::Mid::Print(std::ostream& os) const
332 {
333  bool first = true;
334  os << " [";
335  for (const auto& iAddr : interfaceAddresses)
336  {
337  if (first)
338  {
339  first = false;
340  }
341  else
342  {
343  os << ", ";
344  }
345  os << iAddr;
346  }
347  os << "]";
348 }
349 
350 void
352 {
354 
355  for (auto iter = this->interfaceAddresses.begin(); iter != this->interfaceAddresses.end();
356  iter++)
357  {
358  i.WriteHtonU32(iter->Get());
359  }
360 }
361 
362 uint32_t
364 {
366 
367  this->interfaceAddresses.clear();
368  NS_ASSERT(messageSize % IPV4_ADDRESS_SIZE == 0);
369 
370  int numAddresses = messageSize / IPV4_ADDRESS_SIZE;
371  this->interfaceAddresses.erase(this->interfaceAddresses.begin(),
372  this->interfaceAddresses.end());
373  for (int n = 0; n < numAddresses; ++n)
374  {
375  this->interfaceAddresses.emplace_back(i.ReadNtohU32());
376  }
377  return GetSerializedSize();
378 }
379 
380 // ---------------- OLSR HELLO Message -------------------------------
381 
382 uint32_t
384 {
385  uint32_t size = 4;
386  for (auto iter = this->linkMessages.begin(); iter != this->linkMessages.end(); iter++)
387  {
388  const LinkMessage& lm = *iter;
389  size += 4;
390  size += IPV4_ADDRESS_SIZE * lm.neighborInterfaceAddresses.size();
391  }
392  return size;
393 }
394 
395 void
396 MessageHeader::Hello::Print(std::ostream& os) const
397 {
398  os << " Interval: " << +hTime << " (" << EmfToSeconds(hTime) << "s)";
399  os << " Willingness: " << willingness;
400 
401  for (const auto& ilinkMessage : linkMessages)
402  {
403  const LinkMessage& lm = ilinkMessage;
404  os << " Link code: " << +(lm.linkCode);
405  os << " [";
406  bool first = true;
407  for (const auto& neigh_iter : lm.neighborInterfaceAddresses)
408  {
409  if (first)
410  {
411  first = false;
412  }
413  else
414  {
415  os << ", ";
416  }
417  os << neigh_iter;
418  }
419  os << "]";
420  }
421 }
422 
423 void
425 {
427 
428  i.WriteU16(0); // Reserved
429  i.WriteU8(this->hTime);
430  i.WriteU8(static_cast<uint8_t>(this->willingness));
431 
432  for (auto iter = this->linkMessages.begin(); iter != this->linkMessages.end(); iter++)
433  {
434  const LinkMessage& lm = *iter;
435 
436  i.WriteU8(lm.linkCode);
437  i.WriteU8(0); // Reserved
438 
439  // The size of the link message, counted in bytes and measured
440  // from the beginning of the "Link Code" field and until the
441  // next "Link Code" field (or - if there are no more link types
442  // - the end of the message).
444 
445  for (auto neigh_iter = lm.neighborInterfaceAddresses.begin();
446  neigh_iter != lm.neighborInterfaceAddresses.end();
447  neigh_iter++)
448  {
449  i.WriteHtonU32(neigh_iter->Get());
450  }
451  }
452 }
453 
454 uint32_t
456 {
458 
459  NS_ASSERT(messageSize >= 4);
460 
461  this->linkMessages.clear();
462 
463  uint16_t helloSizeLeft = messageSize;
464 
465  i.ReadNtohU16(); // Reserved
466  this->hTime = i.ReadU8();
467  this->willingness = Willingness(i.ReadU8());
468 
469  helloSizeLeft -= 4;
470 
471  while (helloSizeLeft)
472  {
473  LinkMessage lm;
474  NS_ASSERT(helloSizeLeft >= 4);
475  lm.linkCode = i.ReadU8();
476  i.ReadU8(); // Reserved
477  uint16_t lmSize = i.ReadNtohU16();
478  NS_ASSERT((lmSize - 4) % IPV4_ADDRESS_SIZE == 0);
479  for (int n = (lmSize - 4) / IPV4_ADDRESS_SIZE; n; --n)
480  {
481  lm.neighborInterfaceAddresses.emplace_back(i.ReadNtohU32());
482  }
483  helloSizeLeft -= lmSize;
484  this->linkMessages.push_back(lm);
485  }
486 
487  return messageSize;
488 }
489 
490 // ---------------- OLSR TC Message -------------------------------
491 
492 uint32_t
494 {
495  return 4 + this->neighborAddresses.size() * IPV4_ADDRESS_SIZE;
496 }
497 
498 void
499 MessageHeader::Tc::Print(std::ostream& os) const
500 {
501  os << " Adv. SeqNo: " << ansn;
502  os << " [";
503  bool first = true;
504  for (const auto& iAddr : neighborAddresses)
505  {
506  if (first)
507  {
508  first = false;
509  }
510  else
511  {
512  os << ", ";
513  }
514  os << iAddr;
515  }
516  os << "]";
517 }
518 
519 void
521 {
523 
524  i.WriteHtonU16(this->ansn);
525  i.WriteHtonU16(0); // Reserved
526 
527  for (auto iter = this->neighborAddresses.begin(); iter != this->neighborAddresses.end(); iter++)
528  {
529  i.WriteHtonU32(iter->Get());
530  }
531 }
532 
533 uint32_t
535 {
537 
538  this->neighborAddresses.clear();
539  NS_ASSERT(messageSize >= 4);
540 
541  this->ansn = i.ReadNtohU16();
542  i.ReadNtohU16(); // Reserved
543 
544  NS_ASSERT((messageSize - 4) % IPV4_ADDRESS_SIZE == 0);
545  int numAddresses = (messageSize - 4) / IPV4_ADDRESS_SIZE;
546  this->neighborAddresses.clear();
547  for (int n = 0; n < numAddresses; ++n)
548  {
549  this->neighborAddresses.emplace_back(i.ReadNtohU32());
550  }
551 
552  return messageSize;
553 }
554 
555 // ---------------- OLSR HNA Message -------------------------------
556 
557 uint32_t
559 {
560  return 2 * this->associations.size() * IPV4_ADDRESS_SIZE;
561 }
562 
563 void
564 MessageHeader::Hna::Print(std::ostream& os) const
565 {
566  os << " [";
567  bool first = true;
568  for (const auto& iAssoc : associations)
569  {
570  if (first)
571  {
572  first = false;
573  }
574  else
575  {
576  os << ", ";
577  }
578  os << iAssoc.address << "/" << iAssoc.mask.GetPrefixLength();
579  }
580  os << "]";
581 }
582 
583 void
585 {
587 
588  for (size_t n = 0; n < this->associations.size(); ++n)
589  {
590  i.WriteHtonU32(this->associations[n].address.Get());
591  i.WriteHtonU32(this->associations[n].mask.Get());
592  }
593 }
594 
595 uint32_t
597 {
599 
600  NS_ASSERT(messageSize % (IPV4_ADDRESS_SIZE * 2) == 0);
601  int numAddresses = messageSize / IPV4_ADDRESS_SIZE / 2;
602  this->associations.clear();
603  for (int n = 0; n < numAddresses; ++n)
604  {
606  Ipv4Mask mask(i.ReadNtohU32());
607  this->associations.push_back((Association){address, mask});
608  }
609  return messageSize;
610 }
611 
612 } // namespace olsr
613 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteU16(uint16_t data)
Definition: buffer.cc:859
void WriteHtonU16(uint16_t data)
Definition: buffer.h:915
uint32_t ReadNtohU32()
Definition: buffer.h:978
void WriteHtonU32(uint32_t data)
Definition: buffer.h:933
uint16_t ReadNtohU16()
Definition: buffer.h:954
Protocol header serialization and deserialization.
Definition: header.h:44
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
uint32_t Get() const
Get the host-order 32-bit IP address.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
This header can store HELP, TC, MID and HNA messages.
Definition: olsr-header.h:161
void Print(std::ostream &os) const override
Definition: olsr-header.cc:213
MessageType m_messageType
The message type.
Definition: olsr-header.h:286
uint8_t m_hopCount
The hop count.
Definition: olsr-header.h:290
Ipv4Address m_originatorAddress
The originator address.
Definition: olsr-header.h:288
uint8_t m_vTime
The validity time.
Definition: olsr-header.h:287
uint8_t m_timeToLive
The time to live.
Definition: olsr-header.h:289
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: olsr-header.cc:181
uint16_t m_messageSize
The message size.
Definition: olsr-header.h:292
uint32_t GetSerializedSize() const override
Definition: olsr-header.cc:187
uint16_t m_messageSequenceNumber
The message sequence number.
Definition: olsr-header.h:291
void Serialize(Buffer::Iterator start) const override
Definition: olsr-header.cc:258
static TypeId GetTypeId()
Get the type ID.
Definition: olsr-header.cc:171
struct ns3::olsr::MessageHeader::@68 m_message
Structure holding the message content.
MessageType
Message type.
Definition: olsr-header.h:167
The basic layout of any packet in OLSR is as follows (omitting IP and UDP headers):
Definition: olsr-header.h:79
static TypeId GetTypeId()
Get the type ID.
Definition: olsr-header.cc:113
uint32_t GetSerializedSize() const override
Definition: olsr-header.cc:129
uint16_t m_packetLength
The packet length.
Definition: olsr-header.h:121
void Print(std::ostream &os) const override
Definition: olsr-header.cc:135
uint16_t m_packetSequenceNumber
The packet sequence number.
Definition: olsr-header.h:122
void Serialize(Buffer::Iterator start) const override
Definition: olsr-header.cc:141
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: olsr-header.cc:123
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Willingness
Willingness for forwarding packets from other nodes.
Definition: first.py:1
address
Definition: first.py:47
double EmfToSeconds(uint8_t olsrFormat)
Converts a number of seconds in the mantissa/exponent format to a decimal number.
Definition: olsr-header.cc:92
uint8_t SecondsToEmf(double seconds)
Converts a decimal number of seconds to the mantissa/exponent format.
Definition: olsr-header.cc:49
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Definition: olsr.py:1
#define OLSR_MSG_HEADER_SIZE
Definition: olsr-header.cc:28
#define IPV4_ADDRESS_SIZE
Definition: olsr-header.cc:27
#define OLSR_PKT_HEADER_SIZE
Definition: olsr-header.cc:29
#define OLSR_C
Scaling factor used in RFC 3626.
Definition: olsr-header.cc:40
uint32_t Deserialize(Buffer::Iterator start, uint32_t messageSize)
This method is used by Packet::RemoveHeader to re-create a header from the byte buffer of a packet.
Definition: olsr-header.cc:455
void Print(std::ostream &os) const
This method is used to print the content of a Hello message.
Definition: olsr-header.cc:396
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:383
void Serialize(Buffer::Iterator start) const
This method is used by Packet::AddHeader to store a header into the byte buffer of a packet.
Definition: olsr-header.cc:424
void Serialize(Buffer::Iterator start) const
This method is used by Packet::AddHeader to store a header into the byte buffer of a packet.
Definition: olsr-header.cc:584
uint32_t Deserialize(Buffer::Iterator start, uint32_t messageSize)
This method is used by Packet::RemoveHeader to re-create a header from the byte buffer of a packet.
Definition: olsr-header.cc:596
void Print(std::ostream &os) const
This method is used to print the content of a Hna message.
Definition: olsr-header.cc:564
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:558
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:325
std::vector< Ipv4Address > interfaceAddresses
Interface Address container.
Definition: olsr-header.h:324
void Serialize(Buffer::Iterator start) const
This method is used by Packet::AddHeader to store a header into the byte buffer of a packet.
Definition: olsr-header.cc:351
void Print(std::ostream &os) const
This method is used to print the content of a MID message.
Definition: olsr-header.cc:331
uint32_t Deserialize(Buffer::Iterator start, uint32_t messageSize)
This method is used by Packet::RemoveHeader to re-create a header from the byte buffer of a packet.
Definition: olsr-header.cc:363
void Serialize(Buffer::Iterator start) const
This method is used by Packet::AddHeader to store a header into the byte buffer of a packet.
Definition: olsr-header.cc:520
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:493
void Print(std::ostream &os) const
This method is used to print the content of a Tc message.
Definition: olsr-header.cc:499
uint32_t Deserialize(Buffer::Iterator start, uint32_t messageSize)
This method is used by Packet::RemoveHeader to re-create a header from the byte buffer of a packet.
Definition: olsr-header.cc:534