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