A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
31namespace ns3
32{
33
34NS_LOG_COMPONENT_DEFINE("OlsrHeader");
35
36namespace olsr
37{
38
40#define OLSR_C 0.0625
41
48uint8_t
49SecondsToEmf(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
91double
92EmfToSeconds(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
102NS_OBJECT_ENSURE_REGISTERED(PacketHeader);
103
105{
106}
107
109{
110}
111
112TypeId
114{
115 static TypeId tid = TypeId("ns3::olsr::PacketHeader")
116 .SetParent<Header>()
117 .SetGroupName("Olsr")
118 .AddConstructor<PacketHeader>();
119 return tid;
120}
121
122TypeId
124{
125 return GetTypeId();
126}
127
130{
132}
133
134void
135PacketHeader::Print(std::ostream& os) const
136{
137 os << "len: " << m_packetLength << " seqNo: " << m_packetSequenceNumber;
138}
139
140void
142{
143 Buffer::Iterator i = start;
146}
147
150{
151 Buffer::Iterator i = start;
154 return GetSerializedSize();
155}
156
157// ---------------- OLSR Message -------------------------------
158
160
162 : m_messageType(MessageHeader::MessageType(0))
163{
164}
165
167{
168}
169
170TypeId
172{
173 static TypeId tid = TypeId("ns3::olsr::MessageHeader")
174 .SetParent<Header>()
175 .SetGroupName("Olsr")
176 .AddConstructor<MessageHeader>();
177 return tid;
178}
179
180TypeId
182{
183 return GetTypeId();
184}
185
188{
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
212void
213MessageHeader::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
257void
259{
260 Buffer::Iterator i = start;
262 i.WriteU8(m_vTime);
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
290{
291 uint32_t size;
292 Buffer::Iterator i = start;
295 m_vTime = i.ReadU8();
298 m_timeToLive = i.ReadU8();
299 m_hopCount = i.ReadU8();
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
326{
327 return this->interfaceAddresses.size() * IPV4_ADDRESS_SIZE;
328}
329
330void
331MessageHeader::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
350void
352{
353 Buffer::Iterator i = start;
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
365{
366 Buffer::Iterator i = start;
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
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;
394 }
395 return size;
396}
397
398void
399MessageHeader::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
426void
428{
429 Buffer::Iterator i = start;
430
431 i.WriteU16(0); // Reserved
432 i.WriteU8(this->hTime);
433 i.WriteU8(static_cast<uint8_t>(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 =
452 neigh_iter != lm.neighborInterfaceAddresses.end();
453 neigh_iter++)
454 {
455 i.WriteHtonU32(neigh_iter->Get());
456 }
457 }
458}
459
462{
463 Buffer::Iterator i = start;
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 = 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
500{
501 return 4 + this->neighborAddresses.size() * IPV4_ADDRESS_SIZE;
502}
503
504void
505MessageHeader::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
525void
527{
528 Buffer::Iterator i = start;
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
543{
544 Buffer::Iterator i = start;
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
567{
568 return 2 * this->associations.size() * IPV4_ADDRESS_SIZE;
569}
570
571void
572MessageHeader::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
591void
593{
594 Buffer::Iterator i = start;
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
605{
606 Buffer::Iterator i = start;
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 {
613 Ipv4Address address(i.ReadNtohU32());
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:865
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
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:936
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
struct ns3::olsr::MessageHeader::@66 m_message
Structure holding the message content.
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
uint32_t Deserialize(Buffer::Iterator start) override
Definition: olsr-header.cc: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: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 Deserialize(Buffer::Iterator start) override
Definition: olsr-header.cc:149
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
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: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: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