A Discrete-Event Network Simulator
API
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 (std::vector<Ipv4Address>::const_iterator iter = this->interfaceAddresses.begin();
356  iter != this->interfaceAddresses.end();
357  iter++)
358  {
359  i.WriteHtonU32(iter->Get());
360  }
361 }
362 
363 uint32_t
365 {
367 
368  this->interfaceAddresses.clear();
369  NS_ASSERT(messageSize % IPV4_ADDRESS_SIZE == 0);
370 
371  int numAddresses = messageSize / IPV4_ADDRESS_SIZE;
372  this->interfaceAddresses.erase(this->interfaceAddresses.begin(),
373  this->interfaceAddresses.end());
374  for (int n = 0; n < numAddresses; ++n)
375  {
376  this->interfaceAddresses.emplace_back(i.ReadNtohU32());
377  }
378  return GetSerializedSize();
379 }
380 
381 // ---------------- OLSR HELLO Message -------------------------------
382 
383 uint32_t
385 {
386  uint32_t size = 4;
387  for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin();
388  iter != this->linkMessages.end();
389  iter++)
390  {
391  const LinkMessage& lm = *iter;
392  size += 4;
393  size += IPV4_ADDRESS_SIZE * lm.neighborInterfaceAddresses.size();
394  }
395  return size;
396 }
397 
398 void
399 MessageHeader::Hello::Print(std::ostream& os) const
400 {
401  os << " Interval: " << +hTime << " (" << EmfToSeconds(hTime) << "s)";
402  os << " Willingness: " << +willingness;
403 
404  for (const auto& ilinkMessage : linkMessages)
405  {
406  const LinkMessage& lm = ilinkMessage;
407  os << " Link code: " << +(lm.linkCode);
408  os << " [";
409  bool first = true;
410  for (const auto& neigh_iter : lm.neighborInterfaceAddresses)
411  {
412  if (first)
413  {
414  first = false;
415  }
416  else
417  {
418  os << ", ";
419  }
420  os << neigh_iter;
421  }
422  os << "]";
423  }
424 }
425 
426 void
428 {
430 
431  i.WriteU16(0); // Reserved
432  i.WriteU8(this->hTime);
433  i.WriteU8(this->willingness);
434 
435  for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin();
436  iter != this->linkMessages.end();
437  iter++)
438  {
439  const LinkMessage& lm = *iter;
440 
441  i.WriteU8(lm.linkCode);
442  i.WriteU8(0); // Reserved
443 
444  // The size of the link message, counted in bytes and measured
445  // from the beginning of the "Link Code" field and until the
446  // next "Link Code" field (or - if there are no more link types
447  // - the end of the message).
449 
450  for (std::vector<Ipv4Address>::const_iterator neigh_iter =
451  lm.neighborInterfaceAddresses.begin();
452  neigh_iter != lm.neighborInterfaceAddresses.end();
453  neigh_iter++)
454  {
455  i.WriteHtonU32(neigh_iter->Get());
456  }
457  }
458 }
459 
460 uint32_t
462 {
464 
465  NS_ASSERT(messageSize >= 4);
466 
467  this->linkMessages.clear();
468 
469  uint16_t helloSizeLeft = messageSize;
470 
471  i.ReadNtohU16(); // Reserved
472  this->hTime = i.ReadU8();
473  this->willingness = i.ReadU8();
474 
475  helloSizeLeft -= 4;
476 
477  while (helloSizeLeft)
478  {
479  LinkMessage lm;
480  NS_ASSERT(helloSizeLeft >= 4);
481  lm.linkCode = i.ReadU8();
482  i.ReadU8(); // Reserved
483  uint16_t lmSize = i.ReadNtohU16();
484  NS_ASSERT((lmSize - 4) % IPV4_ADDRESS_SIZE == 0);
485  for (int n = (lmSize - 4) / IPV4_ADDRESS_SIZE; n; --n)
486  {
487  lm.neighborInterfaceAddresses.emplace_back(i.ReadNtohU32());
488  }
489  helloSizeLeft -= lmSize;
490  this->linkMessages.push_back(lm);
491  }
492 
493  return messageSize;
494 }
495 
496 // ---------------- OLSR TC Message -------------------------------
497 
498 uint32_t
500 {
501  return 4 + this->neighborAddresses.size() * IPV4_ADDRESS_SIZE;
502 }
503 
504 void
505 MessageHeader::Tc::Print(std::ostream& os) const
506 {
507  os << " Adv. SeqNo: " << ansn;
508  os << " [";
509  bool first = true;
510  for (const auto& iAddr : neighborAddresses)
511  {
512  if (first)
513  {
514  first = false;
515  }
516  else
517  {
518  os << ", ";
519  }
520  os << iAddr;
521  }
522  os << "]";
523 }
524 
525 void
527 {
529 
530  i.WriteHtonU16(this->ansn);
531  i.WriteHtonU16(0); // Reserved
532 
533  for (std::vector<Ipv4Address>::const_iterator iter = this->neighborAddresses.begin();
534  iter != this->neighborAddresses.end();
535  iter++)
536  {
537  i.WriteHtonU32(iter->Get());
538  }
539 }
540 
541 uint32_t
543 {
545 
546  this->neighborAddresses.clear();
547  NS_ASSERT(messageSize >= 4);
548 
549  this->ansn = i.ReadNtohU16();
550  i.ReadNtohU16(); // Reserved
551 
552  NS_ASSERT((messageSize - 4) % IPV4_ADDRESS_SIZE == 0);
553  int numAddresses = (messageSize - 4) / IPV4_ADDRESS_SIZE;
554  this->neighborAddresses.clear();
555  for (int n = 0; n < numAddresses; ++n)
556  {
557  this->neighborAddresses.emplace_back(i.ReadNtohU32());
558  }
559 
560  return messageSize;
561 }
562 
563 // ---------------- OLSR HNA Message -------------------------------
564 
565 uint32_t
567 {
568  return 2 * this->associations.size() * IPV4_ADDRESS_SIZE;
569 }
570 
571 void
572 MessageHeader::Hna::Print(std::ostream& os) const
573 {
574  os << " [";
575  bool first = true;
576  for (const auto& iAssoc : associations)
577  {
578  if (first)
579  {
580  first = false;
581  }
582  else
583  {
584  os << ", ";
585  }
586  os << iAssoc.address << "/" << iAssoc.mask.GetPrefixLength();
587  }
588  os << "]";
589 }
590 
591 void
593 {
595 
596  for (size_t n = 0; n < this->associations.size(); ++n)
597  {
598  i.WriteHtonU32(this->associations[n].address.Get());
599  i.WriteHtonU32(this->associations[n].mask.Get());
600  }
601 }
602 
603 uint32_t
605 {
607 
608  NS_ASSERT(messageSize % (IPV4_ADDRESS_SIZE * 2) == 0);
609  int numAddresses = messageSize / IPV4_ADDRESS_SIZE / 2;
610  this->associations.clear();
611  for (int n = 0; n < numAddresses; ++n)
612  {
614  Ipv4Mask mask(i.ReadNtohU32());
615  this->associations.push_back((Association){address, mask});
616  }
617  return messageSize;
618 }
619 
620 } // namespace olsr
621 } // 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:862
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:43
uint32_t Get() const
Get the host-order 32-bit IP address.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:258
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
This header can store HELP, TC, MID and HNA messages.
Definition: olsr-header.h:159
void Print(std::ostream &os) const override
Definition: olsr-header.cc:213
MessageType m_messageType
The message type.
Definition: olsr-header.h:284
uint8_t m_hopCount
The hop count.
Definition: olsr-header.h:288
Ipv4Address m_originatorAddress
The originator address.
Definition: olsr-header.h:286
uint8_t m_vTime
The validity time.
Definition: olsr-header.h:285
uint8_t m_timeToLive
The time to live.
Definition: olsr-header.h:287
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: olsr-header.cc:181
struct ns3::olsr::MessageHeader::@69 m_message
Structure holding the message content.
uint16_t m_messageSize
The message size.
Definition: olsr-header.h:290
uint32_t GetSerializedSize() const override
Definition: olsr-header.cc:187
uint16_t m_messageSequenceNumber
The message sequence number.
Definition: olsr-header.h:289
void Serialize(Buffer::Iterator start) const override
Definition: olsr-header.cc:258
static TypeId GetTypeId()
Get the type ID.
Definition: olsr-header.cc:171
MessageType
Message type.
Definition: olsr-header.h:165
The basic layout of any packet in OLSR is as follows (omitting IP and UDP headers):
Definition: olsr-header.h:77
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:119
void Print(std::ostream &os) const override
Definition: olsr-header.cc:135
uint16_t m_packetSequenceNumber
The packet sequence number.
Definition: olsr-header.h:120
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
Definition: first.py:1
address
Definition: first.py:40
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:461
void Print(std::ostream &os) const
This method is used to print the content of a Hello message.
Definition: olsr-header.cc:399
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:384
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:427
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:592
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:604
void Print(std::ostream &os) const
This method is used to print the content of a Hna message.
Definition: olsr-header.cc:572
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:566
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:322
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:364
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:526
uint32_t GetSerializedSize() const
Returns the expected size of the header.
Definition: olsr-header.cc:499
void Print(std::ostream &os) const
This method is used to print the content of a Tc message.
Definition: olsr-header.cc:505
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:542