A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-header.cc
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 NS_LOG_COMPONENT_DEFINE ("Ipv4Header");
28 
29 namespace ns3 {
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;
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);
110 }
111 
112 std::string
114 {
115  NS_LOG_FUNCTION (this << dscp);
116  switch (dscp)
117  {
118  case DscpDefault:
119  return "Default";
120  case CS1:
121  return "CS1";
122  case AF11:
123  return "AF11";
124  case AF12:
125  return "AF12";
126  case AF13:
127  return "AF13";
128  case CS2:
129  return "CS2";
130  case AF21:
131  return "AF21";
132  case AF22:
133  return "AF22";
134  case AF23:
135  return "AF23";
136  case CS3:
137  return "CS3";
138  case AF31:
139  return "AF31";
140  case AF32:
141  return "AF32";
142  case AF33:
143  return "AF33";
144  case CS4:
145  return "CS4";
146  case AF41:
147  return "AF41";
148  case AF42:
149  return "AF42";
150  case AF43:
151  return "AF43";
152  case CS5:
153  return "CS5";
154  case EF:
155  return "EF";
156  case CS6:
157  return "CS6";
158  case 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 NotECT:
181  return "Not-ECT";
182  case ECT1:
183  return "ECT (1)";
184  case ECT0:
185  return "ECT (0)";
186  case 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);
203  m_flags |= MORE_FRAGMENTS;
204 }
205 void
207 {
208  NS_LOG_FUNCTION (this);
209  m_flags &= ~MORE_FRAGMENTS;
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);
222  m_flags |= DONT_FRAGMENT;
223 }
224 void
226 {
227  NS_LOG_FUNCTION (this);
228  m_flags &= ~DONT_FRAGMENT;
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  if ((m_fragmentOffset+m_payloadSize+5*4) > 65535)
250  {
251  NS_LOG_WARN("Fragment will exceed the maximum packet size once reassembled");
252  }
253 
254  return m_fragmentOffset;
255 }
256 
257 void
258 Ipv4Header::SetTtl (uint8_t ttl)
259 {
260  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
261  m_ttl = ttl;
262 }
263 uint8_t
264 Ipv4Header::GetTtl (void) const
265 {
266  NS_LOG_FUNCTION (this);
267  return m_ttl;
268 }
269 
270 uint8_t
272 {
273  NS_LOG_FUNCTION (this);
274  return m_protocol;
275 }
276 void
277 Ipv4Header::SetProtocol (uint8_t protocol)
278 {
279  NS_LOG_FUNCTION (this << static_cast<uint32_t> (protocol));
280  m_protocol = protocol;
281 }
282 
283 void
285 {
286  NS_LOG_FUNCTION (this << source);
287  m_source = source;
288 }
291 {
292  NS_LOG_FUNCTION (this);
293  return m_source;
294 }
295 
296 void
298 {
299  NS_LOG_FUNCTION (this << dst);
300  m_destination = dst;
301 }
304 {
305  NS_LOG_FUNCTION (this);
306  return m_destination;
307 }
308 
309 
310 bool
312 {
313  NS_LOG_FUNCTION (this);
314  return m_goodChecksum;
315 }
316 
317 TypeId
318 Ipv4Header::GetTypeId (void)
319 {
320  static TypeId tid = TypeId ("ns3::Ipv4Header")
321  .SetParent<Header> ()
322  .AddConstructor<Ipv4Header> ()
323  ;
324  return tid;
325 }
326 TypeId
328 {
329  NS_LOG_FUNCTION (this);
330  return GetTypeId ();
331 }
332 void
333 Ipv4Header::Print (std::ostream &os) const
334 {
335  NS_LOG_FUNCTION (this << &os);
336  // ipv4, right ?
337  std::string flags;
338  if (m_flags == 0)
339  {
340  flags = "none";
341  }
342  else if (m_flags & MORE_FRAGMENTS &&
343  m_flags & DONT_FRAGMENT)
344  {
345  flags = "MF|DF";
346  }
347  else if (m_flags & DONT_FRAGMENT)
348  {
349  flags = "DF";
350  }
351  else if (m_flags & MORE_FRAGMENTS)
352  {
353  flags = "MF";
354  }
355  else
356  {
357  flags = "XX";
358  }
359  os << "tos 0x" << std::hex << m_tos << std::dec << " "
360  << "DSCP " << DscpTypeToString (GetDscp ()) << " "
361  << "ECN " << EcnTypeToString (GetEcn ()) << " "
362  << "ttl " << m_ttl << " "
363  << "id " << m_identification << " "
364  << "protocol " << m_protocol << " "
365  << "offset (bytes) " << m_fragmentOffset << " "
366  << "flags [" << flags << "] "
367  << "length: " << (m_payloadSize + 5 * 4)
368  << " "
369  << m_source << " > " << m_destination
370  ;
371 }
372 uint32_t
374 {
375  NS_LOG_FUNCTION (this);
376  //return 5 * 4;
377  return m_headerSize;
378 }
379 
380 void
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);
390  i.WriteHtonU16 (m_identification);
391  uint32_t fragmentOffset = m_fragmentOffset / 8;
392  uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
393  if (m_flags & DONT_FRAGMENT)
394  {
395  flagsFrag |= (1<<6);
396  }
397  if (m_flags & MORE_FRAGMENTS)
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);
405  i.WriteU8 (m_protocol);
406  i.WriteHtonU16 (0);
407  i.WriteHtonU32 (m_source.Get ());
408  i.WriteHtonU32 (m_destination.Get ());
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 uint32_t
422 {
423  NS_LOG_FUNCTION (this << &start);
424  Buffer::Iterator i = start;
425  uint8_t verIhl = i.ReadU8 ();
426  uint8_t ihl = verIhl & 0x0f;
427  uint16_t headerSize = ihl * 4;
428  NS_ASSERT ((verIhl >> 4) == 4);
429  m_tos = i.ReadU8 ();
430  uint16_t size = i.ReadNtohU16 ();
431  m_payloadSize = size - headerSize;
432  m_identification = i.ReadNtohU16 ();
433  uint8_t flags = i.ReadU8 ();
434  m_flags = 0;
435  if (flags & (1<<6))
436  {
437  m_flags |= DONT_FRAGMENT;
438  }
439  if (flags & (1<<5))
440  {
441  m_flags |= MORE_FRAGMENTS;
442  }
443  i.Prev ();
444  m_fragmentOffset = i.ReadU8 () & 0x1f;
445  m_fragmentOffset <<= 8;
446  m_fragmentOffset |= i.ReadU8 ();
447  m_fragmentOffset <<= 3;
448  m_ttl = i.ReadU8 ();
449  m_protocol = i.ReadU8 ();
450  m_checksum = i.ReadU16 ();
451  /* i.Next (2); // checksum */
452  m_source.Set (i.ReadNtohU32 ());
453  m_destination.Set (i.ReadNtohU32 ());
454  m_headerSize = headerSize;
455 
456  if (m_calcChecksum)
457  {
458  i = start;
459  uint16_t checksum = i.CalculateIpChecksum (headerSize);
460  NS_LOG_LOGIC ("checksum=" <<checksum);
461 
462  m_goodChecksum = (checksum == 0);
463  }
464  return GetSerializedSize ();
465 }
466 
467 } // namespace ns3
uint16_t ReadU16(void)
Definition: buffer.h:845
Protocol header serialization and deserialization.
Definition: header.h:42
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1158
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:284
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:297
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
DscpType
DiffServ Code Points Code Points defined in Assured Forwarding (AF) RFC 2597 Expedited Forwarding (EF...
Definition: ipv4-header.h:64
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
#define NS_ASSERT(condition)
Definition: assert.h:64
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:271
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
bool IsDontFragment(void) const
Definition: ipv4-header.cc:231
void SetFragmentOffset(uint16_t offsetBytes)
Definition: ipv4-header.cc:238
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:277
std::string DscpTypeToString(DscpType dscp) const
Definition: ipv4-header.cc:113
void SetDontFragment(void)
Definition: ipv4-header.cc:219
uint32_t ReadNtohU32(void)
Definition: buffer.h:791
iterator in a Buffer instance
Definition: buffer.h:98
void SetLastFragment(void)
Definition: ipv4-header.cc:206
void Prev(void)
Definition: buffer.h:672
uint32_t Get(void) const
DscpType GetDscp(void) const
Definition: ipv4-header.cc:105
Ipv4Header()
Construct a null IPv4 header.
Definition: ipv4-header.cc:33
void WriteU16(uint16_t data)
Definition: buffer.cc:895
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:726
void Next(void)
Definition: buffer.h:666
void SetIdentification(uint16_t identification)
Definition: ipv4-header.cc:75
void SetMayFragment(void)
Definition: ipv4-header.cc:225
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void SetMoreFragments(void)
Definition: ipv4-header.cc:200
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
virtual void Print(std::ostream &os) const
Definition: ipv4-header.cc:333
void WriteHtonU32(uint32_t data)
Definition: buffer.h:745
virtual TypeId GetInstanceTypeId(void) const
Definition: ipv4-header.cc:327
void Set(uint32_t address)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
void WriteU8(uint8_t data)
Definition: buffer.h:690
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
#define NS_LOG_WARN(msg)
Definition: log.h:246
void SetEcn(EcnType ecn)
Set ECN Field.
Definition: ipv4-header.cc:97
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:258
uint8_t ReadU8(void)
Definition: buffer.h:819
virtual void Serialize(Buffer::Iterator start) const
Definition: ipv4-header.cc:381
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:311
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:264
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
std::string EcnTypeToString(EcnType ecn) const
Definition: ipv4-header.cc:175
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.
Definition: abort.h:98
uint16_t ReadNtohU16(void)
Definition: buffer.h:767
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:373
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
EcnType GetEcn(void) const
Definition: ipv4-header.cc:167
EcnType
ECN Type defined in RFC 3168.
Definition: ipv4-header.h:105
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: ipv4-header.cc:421