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