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