A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv4-header.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9#include "ipv4-header.h"
10
11#include "ns3/abort.h"
12#include "ns3/assert.h"
13#include "ns3/header.h"
14#include "ns3/log.h"
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("Ipv4Header");
20
22
24 : m_calcChecksum(false),
25 m_payloadSize(0),
26 m_identification(0),
27 m_tos(0),
28 m_ttl(0),
29 m_protocol(0),
30 m_flags(0),
31 m_fragmentOffset(0),
32 m_checksum(0),
33 m_goodChecksum(true),
34 m_headerSize(5 * 4)
35{
36}
37
38void
44
45void
47{
48 NS_LOG_FUNCTION(this << size);
49 m_payloadSize = size;
50}
51
52uint16_t
54{
55 NS_LOG_FUNCTION(this);
56 return m_payloadSize;
57}
58
59uint16_t
65
66void
67Ipv4Header::SetIdentification(uint16_t identification)
68{
69 NS_LOG_FUNCTION(this << identification);
70 m_identification = identification;
71}
72
73void
75{
76 NS_LOG_FUNCTION(this << static_cast<uint32_t>(tos));
77 m_tos = tos;
78}
79
80void
82{
83 NS_LOG_FUNCTION(this << dscp);
84 m_tos &= 0x3; // Clear out the DSCP part, retain 2 bits of ECN
85 m_tos |= (dscp << 2);
86}
87
88void
90{
91 NS_LOG_FUNCTION(this << ecn);
92 m_tos &= 0xFC; // Clear out the ECN part, retain 6 bits of DSCP
93 m_tos |= ecn;
94}
95
98{
99 NS_LOG_FUNCTION(this);
100 // Extract only first 6 bits of TOS byte, i.e 0xFC
101 return DscpType((m_tos & 0xFC) >> 2);
102}
103
104std::string
106{
107 NS_LOG_FUNCTION(this << dscp);
108 switch (dscp)
109 {
110 case DscpDefault:
111 return "Default";
112 case DSCP_CS1:
113 return "CS1";
114 case DSCP_AF11:
115 return "AF11";
116 case DSCP_AF12:
117 return "AF12";
118 case DSCP_AF13:
119 return "AF13";
120 case DSCP_CS2:
121 return "CS2";
122 case DSCP_AF21:
123 return "AF21";
124 case DSCP_AF22:
125 return "AF22";
126 case DSCP_AF23:
127 return "AF23";
128 case DSCP_CS3:
129 return "CS3";
130 case DSCP_AF31:
131 return "AF31";
132 case DSCP_AF32:
133 return "AF32";
134 case DSCP_AF33:
135 return "AF33";
136 case DSCP_CS4:
137 return "CS4";
138 case DSCP_AF41:
139 return "AF41";
140 case DSCP_AF42:
141 return "AF42";
142 case DSCP_AF43:
143 return "AF43";
144 case DSCP_CS5:
145 return "CS5";
146 case DSCP_EF:
147 return "EF";
148 case DSCP_CS6:
149 return "CS6";
150 case DSCP_CS7:
151 return "CS7";
152 default:
153 return "Unrecognized DSCP";
154 };
155}
156
159{
160 NS_LOG_FUNCTION(this);
161 // Extract only last 2 bits of TOS byte, i.e 0x3
162 return EcnType(m_tos & 0x3);
163}
164
165std::string
167{
168 NS_LOG_FUNCTION(this << ecn);
169 switch (ecn)
170 {
171 case ECN_NotECT:
172 return "Not-ECT";
173 case ECN_ECT1:
174 return "ECT (1)";
175 case ECN_ECT0:
176 return "ECT (0)";
177 case ECN_CE:
178 return "CE";
179 default:
180 return "Unknown ECN";
181 };
182}
183
184uint8_t
186{
187 NS_LOG_FUNCTION(this);
188 return m_tos;
189}
190
191void
197
198void
200{
201 NS_LOG_FUNCTION(this);
202 m_flags &= ~MORE_FRAGMENTS;
203}
204
205bool
207{
208 NS_LOG_FUNCTION(this);
209 return !(m_flags & MORE_FRAGMENTS);
210}
211
212void
218
219void
221{
222 NS_LOG_FUNCTION(this);
223 m_flags &= ~DONT_FRAGMENT;
224}
225
226bool
228{
229 NS_LOG_FUNCTION(this);
230 return (m_flags & DONT_FRAGMENT);
231}
232
233void
234Ipv4Header::SetFragmentOffset(uint16_t offsetBytes)
235{
236 NS_LOG_FUNCTION(this << offsetBytes);
237 // check if the user is trying to set an invalid offset
238 NS_ABORT_MSG_IF((offsetBytes & 0x7), "offsetBytes must be multiple of 8 bytes");
239 m_fragmentOffset = offsetBytes;
240}
241
242uint16_t
244{
245 NS_LOG_FUNCTION(this);
246 // -fstrict-overflow sensitive, see bug 1868
247 if (m_fragmentOffset + m_payloadSize > 65535 - 5 * 4)
248 {
249 NS_LOG_WARN("Fragment will exceed the maximum packet size once reassembled");
250 }
251
252 return m_fragmentOffset;
253}
254
255void
257{
258 NS_LOG_FUNCTION(this << static_cast<uint32_t>(ttl));
259 m_ttl = ttl;
260}
261
262uint8_t
264{
265 NS_LOG_FUNCTION(this);
266 return m_ttl;
267}
268
269uint8_t
271{
272 NS_LOG_FUNCTION(this);
273 return m_protocol;
274}
275
276void
277Ipv4Header::SetProtocol(uint8_t protocol)
278{
279 NS_LOG_FUNCTION(this << static_cast<uint32_t>(protocol));
280 m_protocol = protocol;
281}
282
283void
285{
286 NS_LOG_FUNCTION(this << source);
287 m_source = source;
288}
289
292{
293 NS_LOG_FUNCTION(this);
294 return m_source;
295}
296
297void
299{
300 NS_LOG_FUNCTION(this << dst);
301 m_destination = dst;
302}
303
306{
307 NS_LOG_FUNCTION(this);
308 return m_destination;
309}
310
311bool
313{
314 NS_LOG_FUNCTION(this);
315 return m_goodChecksum;
316}
317
318TypeId
320{
321 static TypeId tid = TypeId("ns3::Ipv4Header")
322 .SetParent<Header>()
323 .SetGroupName("Internet")
324 .AddConstructor<Ipv4Header>();
325 return tid;
326}
327
328TypeId
330{
331 NS_LOG_FUNCTION(this);
332 return GetTypeId();
333}
334
335void
336Ipv4Header::Print(std::ostream& os) const
337{
338 NS_LOG_FUNCTION(this << &os);
339 // ipv4, right ?
340 std::string flags;
341 if (m_flags == 0)
342 {
343 flags = "none";
344 }
345 else if ((m_flags & MORE_FRAGMENTS) && (m_flags & DONT_FRAGMENT))
346 {
347 flags = "MF|DF";
348 }
349 else if (m_flags & DONT_FRAGMENT)
350 {
351 flags = "DF";
352 }
353 else if (m_flags & MORE_FRAGMENTS)
354 {
355 flags = "MF";
356 }
357 else
358 {
359 flags = "XX";
360 }
361 os << "tos 0x" << std::hex << m_tos << std::dec << " "
362 << "DSCP " << DscpTypeToString(GetDscp()) << " "
363 << "ECN " << EcnTypeToString(GetEcn()) << " "
364 << "ttl " << m_ttl << " "
365 << "id " << m_identification << " "
366 << "protocol " << m_protocol << " "
367 << "offset (bytes) " << m_fragmentOffset << " "
368 << "flags [" << flags << "] "
369 << "length: " << (m_payloadSize + 5 * 4) << " " << m_source << " > " << m_destination;
370}
371
374{
375 NS_LOG_FUNCTION(this);
376 // return 5 * 4;
377 return m_headerSize;
378}
379
380void
382{
383 NS_LOG_FUNCTION(this << &start);
384 Buffer::Iterator i = start;
385
386 uint8_t verIhl = (4 << 4) | (5);
387 i.WriteU8(verIhl);
388 i.WriteU8(m_tos);
389 i.WriteHtonU16(m_payloadSize + 5 * 4);
391 uint32_t fragmentOffset = m_fragmentOffset / 8;
392 uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
394 {
395 flagsFrag |= (1 << 6);
396 }
398 {
399 flagsFrag |= (1 << 5);
400 }
401 i.WriteU8(flagsFrag);
402 uint8_t frag = fragmentOffset & 0xff;
403 i.WriteU8(frag);
404 i.WriteU8(m_ttl);
406 i.WriteHtonU16(0);
409
410 if (m_calcChecksum)
411 {
412 i = start;
413 uint16_t checksum = i.CalculateIpChecksum(20);
414 NS_LOG_LOGIC("checksum=" << checksum);
415 i = start;
416 i.Next(10);
417 i.WriteU16(checksum);
418 }
419}
420
423{
424 NS_LOG_FUNCTION(this << &start);
425 Buffer::Iterator i = start;
426
427 uint8_t verIhl = i.ReadU8();
428 uint8_t ihl = verIhl & 0x0f;
429 uint16_t headerSize = ihl * 4;
430
431 if ((verIhl >> 4) != 4)
432 {
433 NS_LOG_WARN("Trying to decode a non-IPv4 header, refusing to do it.");
434 return 0;
435 }
436
437 m_tos = i.ReadU8();
438 uint16_t size = i.ReadNtohU16();
439 m_payloadSize = size - headerSize;
441 uint8_t flags = i.ReadU8();
442 m_flags = 0;
443 if (flags & (1 << 6))
444 {
446 }
447 if (flags & (1 << 5))
448 {
450 }
451 i.Prev();
452 m_fragmentOffset = i.ReadU8() & 0x1f;
453 m_fragmentOffset <<= 8;
455 m_fragmentOffset <<= 3;
456 m_ttl = i.ReadU8();
457 m_protocol = i.ReadU8();
458 m_checksum = i.ReadU16();
459 /* i.Next (2); // checksum */
462 m_headerSize = headerSize;
463
464 if (m_calcChecksum)
465 {
466 i = start;
467 uint16_t checksum = i.CalculateIpChecksum(headerSize);
468 NS_LOG_LOGIC("checksum=" << checksum);
469
470 m_goodChecksum = (checksum == 0);
471 }
472 return GetSerializedSize();
473}
474
475} // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition buffer.cc:1124
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
void Prev()
go backward by one byte
Definition buffer.h:849
uint16_t ReadU16()
Definition buffer.h:1024
void Next()
go forward by one byte
Definition buffer.h:842
Protocol header serialization and deserialization.
Definition header.h:33
Ipv4 addresses are stored in host order in this class.
void Set(uint32_t address)
input address is in host order.
uint32_t Get() const
Get the host-order 32-bit IP address.
Packet header for IPv4.
Definition ipv4-header.h:23
Ipv4Address m_source
source address
bool IsChecksumOk() const
void Print(std::ostream &os) const override
void SetDestination(Ipv4Address destination)
Ipv4Address GetSource() const
uint16_t m_fragmentOffset
Fragment offset.
void SetDontFragment()
Don't fragment this packet: if you need to anyway, drop it.
std::string EcnTypeToString(EcnType ecn) const
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint8_t GetTos() const
void SetLastFragment()
This packet is the last packet of a fragmented ipv4 packet.
uint32_t m_ttl
TTL.
uint32_t m_protocol
Protocol.
void SetPayloadSize(uint16_t size)
EcnType GetEcn() const
uint16_t m_identification
identification
uint16_t GetIdentification() const
bool IsDontFragment() const
uint8_t GetProtocol() const
uint16_t m_payloadSize
payload size
void SetTtl(uint8_t ttl)
bool IsLastFragment() const
uint32_t m_tos
TOS, also used as DSCP + ECN value.
bool m_goodChecksum
true if checksum is correct
void SetMoreFragments()
This packet is not the last packet of a fragmented ipv4 packet.
Ipv4Address GetDestination() const
void Serialize(Buffer::Iterator start) const override
void SetDscp(DscpType dscp)
Set DSCP Field.
Ipv4Address m_destination
destination address
void SetMayFragment()
If you need to fragment this packet, you can do it.
EcnType
ECN Type defined in RFC 3168
uint16_t m_checksum
checksum
uint16_t m_headerSize
IP header size.
DscpType GetDscp() const
uint16_t GetPayloadSize() const
void SetEcn(EcnType ecn)
Set ECN Field.
DscpType
DiffServ codepoints.
Definition ipv4-header.h:61
std::string DscpTypeToString(DscpType dscp) const
uint32_t m_flags
flags
uint32_t GetSerializedSize() const override
uint16_t GetFragmentOffset() const
void SetProtocol(uint8_t num)
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
void SetIdentification(uint16_t identification)
static TypeId GetTypeId()
Get the type ID.
uint8_t GetTtl() const
void EnableChecksum()
Enable checksum calculation for this header.
void SetTos(uint8_t tos)
uint32_t Deserialize(Buffer::Iterator start) override
void SetSource(Ipv4Address source)
Ipv4Header()
Construct a null IPv4 header.
bool m_calcChecksum
true if the checksum must be calculated
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Every class exported by the ns3 library is enclosed in the ns3 namespace.