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
39/// Scaling factor used in RFC 3626.
40#define OLSR_C 0.0625
41
42///
43/// \brief Converts a decimal number of seconds to the mantissa/exponent format.
44///
45/// \param seconds decimal number of seconds we want to convert.
46/// \return the number of seconds in mantissa/exponent format.
47///
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
85///
86/// \brief Converts a number of seconds in the mantissa/exponent format to a decimal number.
87///
88/// \param olsrFormat number of seconds in mantissa/exponent format.
89/// \return the decimal number of seconds.
90///
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 (auto iter = this->interfaceAddresses.begin(); iter != this->interfaceAddresses.end();
356 iter++)
357 {
358 i.WriteHtonU32(iter->Get());
359 }
360}
361
364{
365 Buffer::Iterator i = start;
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
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;
391 }
392 return size;
393}
394
395void
396MessageHeader::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
423void
425{
426 Buffer::Iterator i = start;
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
456{
457 Buffer::Iterator i = start;
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
494{
495 return 4 + this->neighborAddresses.size() * IPV4_ADDRESS_SIZE;
496}
497
498void
499MessageHeader::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
519void
521{
522 Buffer::Iterator i = start;
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
535{
536 Buffer::Iterator i = start;
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
559{
560 return 2 * this->associations.size() * IPV4_ADDRESS_SIZE;
561}
562
563void
564MessageHeader::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
583void
585{
586 Buffer::Iterator i = start;
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
597{
598 Buffer::Iterator i = start;
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 {
605 Ipv4Address address(i.ReadNtohU32());
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
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:932
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: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