A Discrete-Event Network Simulator
API
ipv4-header.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/assert.h"
22 #include "ns3/abort.h"
23 #include "ns3/log.h"
24 #include "ns3/header.h"
25 #include "ipv4-header.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("Ipv4Header");
30 
31 NS_OBJECT_ENSURE_REGISTERED (Ipv4Header);
32 
34  : m_calcChecksum (false),
35  m_payloadSize (0),
36  m_identification (0),
37  m_tos (0),
38  m_ttl (0),
39  m_protocol (0),
40  m_flags (0),
41  m_fragmentOffset (0),
42  m_checksum (0),
43  m_goodChecksum (true),
44  m_headerSize(5*4)
45 {
46 }
47 
48 void
50 {
51  NS_LOG_FUNCTION (this);
52  m_calcChecksum = true;
53 }
54 
55 void
57 {
58  NS_LOG_FUNCTION (this << size);
59  m_payloadSize = size;
60 }
61 uint16_t
63 {
64  NS_LOG_FUNCTION (this);
65  return m_payloadSize;
66 }
67 
68 uint16_t
70 {
71  NS_LOG_FUNCTION (this);
72  return m_identification;
73 }
74 void
75 Ipv4Header::SetIdentification (uint16_t identification)
76 {
77  NS_LOG_FUNCTION (this << identification);
78  m_identification = identification;
79 }
80 
81 void
82 Ipv4Header::SetTos (uint8_t tos)
83 {
84  NS_LOG_FUNCTION (this << static_cast<uint32_t> (tos));
85  m_tos = tos;
86 }
87 
88 void
90 {
91  NS_LOG_FUNCTION (this << dscp);
92  m_tos &= 0x3; // Clear out the DSCP part, retain 2 bits of ECN
93  m_tos |= (dscp << 2);
94 }
95 
96 void
98 {
99  NS_LOG_FUNCTION (this << ecn);
100  m_tos &= 0xFC; // Clear out the ECN part, retain 6 bits of DSCP
101  m_tos |= ecn;
102 }
103 
106 {
107  NS_LOG_FUNCTION (this);
108  // Extract only first 6 bits of TOS byte, i.e 0xFC
109  return DscpType ((m_tos & 0xFC) >> 2);
110 }
111 
112 std::string
114 {
115  NS_LOG_FUNCTION (this << dscp);
116  switch (dscp)
117  {
118  case DscpDefault:
119  return "Default";
120  case DSCP_CS1:
121  return "CS1";
122  case DSCP_AF11:
123  return "AF11";
124  case DSCP_AF12:
125  return "AF12";
126  case DSCP_AF13:
127  return "AF13";
128  case DSCP_CS2:
129  return "CS2";
130  case DSCP_AF21:
131  return "AF21";
132  case DSCP_AF22:
133  return "AF22";
134  case DSCP_AF23:
135  return "AF23";
136  case DSCP_CS3:
137  return "CS3";
138  case DSCP_AF31:
139  return "AF31";
140  case DSCP_AF32:
141  return "AF32";
142  case DSCP_AF33:
143  return "AF33";
144  case DSCP_CS4:
145  return "CS4";
146  case DSCP_AF41:
147  return "AF41";
148  case DSCP_AF42:
149  return "AF42";
150  case DSCP_AF43:
151  return "AF43";
152  case DSCP_CS5:
153  return "CS5";
154  case DSCP_EF:
155  return "EF";
156  case DSCP_CS6:
157  return "CS6";
158  case DSCP_CS7:
159  return "CS7";
160  default:
161  return "Unrecognized DSCP";
162  };
163 }
164 
165 
167 Ipv4Header::GetEcn (void) const
168 {
169  NS_LOG_FUNCTION (this);
170  // Extract only last 2 bits of TOS byte, i.e 0x3
171  return EcnType (m_tos & 0x3);
172 }
173 
174 std::string
176 {
177  NS_LOG_FUNCTION (this << ecn);
178  switch (ecn)
179  {
180  case ECN_NotECT:
181  return "Not-ECT";
182  case ECN_ECT1:
183  return "ECT (1)";
184  case ECN_ECT0:
185  return "ECT (0)";
186  case ECN_CE:
187  return "CE";
188  default:
189  return "Unknown ECN";
190  };
191 }
192 
193 uint8_t
194 Ipv4Header::GetTos (void) const
195 {
196  NS_LOG_FUNCTION (this);
197  return m_tos;
198 }
199 void
201 {
202  NS_LOG_FUNCTION (this);
204 }
205 void
207 {
208  NS_LOG_FUNCTION (this);
210 }
211 bool
213 {
214  NS_LOG_FUNCTION (this);
215  return !(m_flags & MORE_FRAGMENTS);
216 }
217 
218 void
220 {
221  NS_LOG_FUNCTION (this);
223 }
224 void
226 {
227  NS_LOG_FUNCTION (this);
229 }
230 bool
232 {
233  NS_LOG_FUNCTION (this);
234  return (m_flags & DONT_FRAGMENT);
235 }
236 
237 void
238 Ipv4Header::SetFragmentOffset (uint16_t offsetBytes)
239 {
240  NS_LOG_FUNCTION (this << offsetBytes);
241  // check if the user is trying to set an invalid offset
242  NS_ABORT_MSG_IF ((offsetBytes & 0x7), "offsetBytes must be multiple of 8 bytes");
243  m_fragmentOffset = offsetBytes;
244 }
245 uint16_t
247 {
248  NS_LOG_FUNCTION (this);
249  // -fstrict-overflow sensitive, see bug 1868
250  if ( m_fragmentOffset + m_payloadSize > 65535 - 5*4 )
251  {
252  NS_LOG_WARN("Fragment will exceed the maximum packet size once reassembled");
253  }
254 
255  return m_fragmentOffset;
256 }
257 
258 void
259 Ipv4Header::SetTtl (uint8_t ttl)
260 {
261  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
262  m_ttl = ttl;
263 }
264 uint8_t
265 Ipv4Header::GetTtl (void) const
266 {
267  NS_LOG_FUNCTION (this);
268  return m_ttl;
269 }
270 
271 uint8_t
273 {
274  NS_LOG_FUNCTION (this);
275  return m_protocol;
276 }
277 void
278 Ipv4Header::SetProtocol (uint8_t protocol)
279 {
280  NS_LOG_FUNCTION (this << static_cast<uint32_t> (protocol));
281  m_protocol = protocol;
282 }
283 
284 void
286 {
287  NS_LOG_FUNCTION (this << source);
288  m_source = source;
289 }
292 {
293  NS_LOG_FUNCTION (this);
294  return m_source;
295 }
296 
297 void
299 {
300  NS_LOG_FUNCTION (this << dst);
301  m_destination = dst;
302 }
305 {
306  NS_LOG_FUNCTION (this);
307  return m_destination;
308 }
309 
310 
311 bool
313 {
314  NS_LOG_FUNCTION (this);
315  return m_goodChecksum;
316 }
317 
318 TypeId
320 {
321  static TypeId tid = TypeId ("ns3::Ipv4Header")
322  .SetParent<Header> ()
323  .SetGroupName ("Internet")
324  .AddConstructor<Ipv4Header> ()
325  ;
326  return tid;
327 }
328 TypeId
330 {
331  NS_LOG_FUNCTION (this);
332  return GetTypeId ();
333 }
334 void
335 Ipv4Header::Print (std::ostream &os) const
336 {
337  NS_LOG_FUNCTION (this << &os);
338  // ipv4, right ?
339  std::string flags;
340  if (m_flags == 0)
341  {
342  flags = "none";
343  }
344  else if ((m_flags & MORE_FRAGMENTS) &&
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)
370  << " "
371  << m_source << " > " << m_destination
372  ;
373 }
374 uint32_t
376 {
377  NS_LOG_FUNCTION (this);
378  //return 5 * 4;
379  return m_headerSize;
380 }
381 
382 void
384 {
385  NS_LOG_FUNCTION (this << &start);
387 
388  uint8_t verIhl = (4 << 4) | (5);
389  i.WriteU8 (verIhl);
390  i.WriteU8 (m_tos);
391  i.WriteHtonU16 (m_payloadSize + 5*4);
393  uint32_t fragmentOffset = m_fragmentOffset / 8;
394  uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
395  if (m_flags & DONT_FRAGMENT)
396  {
397  flagsFrag |= (1<<6);
398  }
399  if (m_flags & MORE_FRAGMENTS)
400  {
401  flagsFrag |= (1<<5);
402  }
403  i.WriteU8 (flagsFrag);
404  uint8_t frag = fragmentOffset & 0xff;
405  i.WriteU8 (frag);
406  i.WriteU8 (m_ttl);
407  i.WriteU8 (m_protocol);
408  i.WriteHtonU16 (0);
409  i.WriteHtonU32 (m_source.Get ());
411 
412  if (m_calcChecksum)
413  {
414  i = start;
415  uint16_t checksum = i.CalculateIpChecksum (20);
416  NS_LOG_LOGIC ("checksum=" <<checksum);
417  i = start;
418  i.Next (10);
419  i.WriteU16 (checksum);
420  }
421 }
422 uint32_t
424 {
425  NS_LOG_FUNCTION (this << &start);
427 
428  uint8_t verIhl = i.ReadU8 ();
429  uint8_t ihl = verIhl & 0x0f;
430  uint16_t headerSize = ihl * 4;
431 
432  if ((verIhl >> 4) != 4)
433  {
434  NS_LOG_WARN ("Trying to decode a non-IPv4 header, refusing to do it.");
435  return 0;
436  }
437 
438  m_tos = i.ReadU8 ();
439  uint16_t size = i.ReadNtohU16 ();
440  m_payloadSize = size - headerSize;
442  uint8_t flags = i.ReadU8 ();
443  m_flags = 0;
444  if (flags & (1<<6))
445  {
447  }
448  if (flags & (1<<5))
449  {
451  }
452  i.Prev ();
453  m_fragmentOffset = i.ReadU8 () & 0x1f;
454  m_fragmentOffset <<= 8;
455  m_fragmentOffset |= i.ReadU8 ();
456  m_fragmentOffset <<= 3;
457  m_ttl = i.ReadU8 ();
458  m_protocol = i.ReadU8 ();
459  m_checksum = i.ReadU16 ();
460  /* i.Next (2); // checksum */
461  m_source.Set (i.ReadNtohU32 ());
463  m_headerSize = headerSize;
464 
465  if (m_calcChecksum)
466  {
467  i = start;
468  uint16_t checksum = i.CalculateIpChecksum (headerSize);
469  NS_LOG_LOGIC ("checksum=" <<checksum);
470 
471  m_goodChecksum = (checksum == 0);
472  }
473  return GetSerializedSize ();
474 }
475 
476 } // namespace ns3
uint16_t ReadU16(void)
Definition: buffer.h:1029
Protocol header serialization and deserialization.
Definition: header.h:42
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1133
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:285
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
std::string DscpTypeToString(DscpType dscp) const
Definition: ipv4-header.cc:113
uint32_t m_ttl
TTL.
Definition: ipv4-header.h:254
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t m_flags
flags
Definition: ipv4-header.h:256
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint16_t m_identification
identification
Definition: ipv4-header.h:252
DscpType
DiffServ codepoints.
Definition: ipv4-header.h:70
Ipv4Address m_destination
destination address
Definition: ipv4-header.h:259
def start()
Definition: core.py:1855
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: ipv4-header.cc:329
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
virtual void Serialize(Buffer::Iterator start) const
Definition: ipv4-header.cc:383
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:204
uint16_t m_headerSize
IP header size.
Definition: ipv4-header.h:262
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
Definition: ipv4-header.cc:238
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
uint32_t m_tos
TOS, also used as DSCP + ECN value.
Definition: ipv4-header.h:253
void SetDontFragment(void)
Don&#39;t fragment this packet: if you need to anyway, drop it.
Definition: ipv4-header.cc:219
uint32_t ReadNtohU32(void)
Definition: buffer.h:970
iterator in a Buffer instance
Definition: buffer.h:98
static TypeId GetTypeId(void)
Get the type ID.
Definition: ipv4-header.cc:319
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetLastFragment(void)
This packet is the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:206
bool m_goodChecksum
true if checksum is correct
Definition: ipv4-header.h:261
void Prev(void)
go backward by one byte
Definition: buffer.h:851
std::string EcnTypeToString(EcnType ecn) const
Definition: ipv4-header.cc:175
Ipv4Header()
Construct a null IPv4 header.
Definition: ipv4-header.cc:33
void WriteU16(uint16_t data)
Definition: buffer.cc:870
void EnableChecksum(void)
Enable checksum calculation for this header.
Definition: ipv4-header.cc:49
void SetDscp(DscpType dscp)
Set DSCP Field.
Definition: ipv4-header.cc:89
void WriteHtonU16(uint16_t data)
Definition: buffer.h:905
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
void Next(void)
go forward by one byte
Definition: buffer.h:845
void SetIdentification(uint16_t identification)
Definition: ipv4-header.cc:75
void SetMayFragment(void)
If you need to fragment this packet, you can do it.
Definition: ipv4-header.cc:225
DscpType GetDscp(void) const
Definition: ipv4-header.cc:105
uint16_t m_fragmentOffset
Fragment offset.
Definition: ipv4-header.h:257
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
bool IsDontFragment(void) const
Definition: ipv4-header.cc:231
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t m_checksum
checksum
Definition: ipv4-header.h:260
void SetMoreFragments(void)
This packet is not the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:200
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
Ipv4Address m_source
source address
Definition: ipv4-header.h:258
void WriteHtonU32(uint32_t data)
Definition: buffer.h:924
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
void Set(uint32_t address)
input address is in host order.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
void WriteU8(uint8_t data)
Definition: buffer.h:869
#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_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:264
uint32_t m_protocol
Protocol.
Definition: ipv4-header.h:255
void SetEcn(EcnType ecn)
Set ECN Field.
Definition: ipv4-header.cc:97
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:259
uint8_t ReadU8(void)
Definition: buffer.h:1021
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:312
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
bool m_calcChecksum
true if the checksum must be calculated
Definition: ipv4-header.h:249
uint16_t m_payloadSize
payload size
Definition: ipv4-header.h:251
uint32_t Get(void) const
Get the host-order 32-bit IP address.
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint16_t ReadNtohU16(void)
Definition: buffer.h:946
a unique identifier for an interface.
Definition: type-id.h:58
EcnType GetEcn(void) const
Definition: ipv4-header.cc:167
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
EcnType
ECN Type defined in RFC 3168
Definition: ipv4-header.h:112
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: ipv4-header.cc:423
virtual void Print(std::ostream &os) const
Definition: ipv4-header.cc:335