A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 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  m_calcChecksum = true;
52 }
53 
54 void
56 {
57  m_payloadSize = size;
58 }
59 uint16_t
61 {
62  return m_payloadSize;
63 }
64 
65 uint16_t
67 {
68  return m_identification;
69 }
70 void
71 Ipv4Header::SetIdentification (uint16_t identification)
72 {
73  m_identification = identification;
74 }
75 
76 void
77 Ipv4Header::SetTos (uint8_t tos)
78 {
79  m_tos = tos;
80 }
81 
82 void
84 {
85  m_tos &= 0x3; // Clear out the DSCP part, retain 2 bits of ECN
86  m_tos |= dscp;
87 }
88 
89 void
91 {
92  m_tos &= 0xFC; // Clear out the ECN part, retain 6 bits of DSCP
93  m_tos |= ecn;
94 }
95 
97 Ipv4Header::GetDscp (void) const
98 {
99  // Extract only first 6 bits of TOS byte, i.e 0xFC
100  return DscpType (m_tos & 0xFC);
101 }
102 
103 std::string
105 {
106  switch (dscp)
107  {
108  case DscpDefault:
109  return "Default";
110  case CS1:
111  return "CS1";
112  case AF11:
113  return "AF11";
114  case AF12:
115  return "AF12";
116  case AF13:
117  return "AF13";
118  case CS2:
119  return "CS2";
120  case AF21:
121  return "AF21";
122  case AF22:
123  return "AF22";
124  case AF23:
125  return "AF23";
126  case CS3:
127  return "CS3";
128  case AF31:
129  return "AF31";
130  case AF32:
131  return "AF32";
132  case AF33:
133  return "AF33";
134  case CS4:
135  return "CS4";
136  case AF41:
137  return "AF41";
138  case AF42:
139  return "AF42";
140  case AF43:
141  return "AF43";
142  case CS5:
143  return "CS5";
144  case EF:
145  return "EF";
146  case CS6:
147  return "CS6";
148  case CS7:
149  return "CS7";
150  default:
151  return "Unrecognized DSCP";
152  };
153 }
154 
155 
157 Ipv4Header::GetEcn (void) const
158 {
159  // Extract only last 2 bits of TOS byte, i.e 0x3
160  return EcnType (m_tos & 0x3);
161 }
162 
163 std::string
165 {
166  switch (ecn)
167  {
168  case NotECT:
169  return "Not-ECT";
170  case ECT1:
171  return "ECT (1)";
172  case ECT0:
173  return "ECT (0)";
174  case CE:
175  return "CE";
176  default:
177  return "Unknown ECN";
178  };
179 }
180 
181 uint8_t
182 Ipv4Header::GetTos (void) const
183 {
184  return m_tos;
185 }
186 void
188 {
190 }
191 void
193 {
195 }
196 bool
198 {
199  return !(m_flags & MORE_FRAGMENTS);
200 }
201 
202 void
204 {
206 }
207 void
209 {
211 }
212 bool
214 {
215  return (m_flags & DONT_FRAGMENT);
216 }
217 
218 void
219 Ipv4Header::SetFragmentOffset (uint16_t offsetBytes)
220 {
221  // check if the user is trying to set an invalid offset
222  NS_ABORT_MSG_IF ((offsetBytes & 0x7), "offsetBytes must be multiple of 8 bytes");
223  m_fragmentOffset = offsetBytes;
224 }
225 uint16_t
227 {
228  if ((m_fragmentOffset+m_payloadSize+5*4) > 65535)
229  {
230  NS_LOG_WARN("Fragment will exceed the maximum packet size once reassembled");
231  }
232 
233  return m_fragmentOffset;
234 }
235 
236 void
237 Ipv4Header::SetTtl (uint8_t ttl)
238 {
239  m_ttl = ttl;
240 }
241 uint8_t
242 Ipv4Header::GetTtl (void) const
243 {
244  return m_ttl;
245 }
246 
247 uint8_t
249 {
250  return m_protocol;
251 }
252 void
253 Ipv4Header::SetProtocol (uint8_t protocol)
254 {
255  m_protocol = protocol;
256 }
257 
258 void
260 {
261  m_source = source;
262 }
265 {
266  return m_source;
267 }
268 
269 void
271 {
272  m_destination = dst;
273 }
276 {
277  return m_destination;
278 }
279 
280 
281 bool
283 {
284  return m_goodChecksum;
285 }
286 
287 TypeId
289 {
290  static TypeId tid = TypeId ("ns3::Ipv4Header")
291  .SetParent<Header> ()
292  .AddConstructor<Ipv4Header> ()
293  ;
294  return tid;
295 }
296 TypeId
298 {
299  return GetTypeId ();
300 }
301 void
302 Ipv4Header::Print (std::ostream &os) const
303 {
304  // ipv4, right ?
305  std::string flags;
306  if (m_flags == 0)
307  {
308  flags = "none";
309  }
310  else if (m_flags & MORE_FRAGMENTS &&
312  {
313  flags = "MF|DF";
314  }
315  else if (m_flags & DONT_FRAGMENT)
316  {
317  flags = "DF";
318  }
319  else if (m_flags & MORE_FRAGMENTS)
320  {
321  flags = "MF";
322  }
323  else
324  {
325  flags = "XX";
326  }
327  os << "tos 0x" << std::hex << m_tos << std::dec << " "
328  << "DSCP " << DscpTypeToString (GetDscp ()) << " "
329  << "ECN " << EcnTypeToString (GetEcn ()) << " "
330  << "ttl " << m_ttl << " "
331  << "id " << m_identification << " "
332  << "protocol " << m_protocol << " "
333  << "offset (bytes) " << m_fragmentOffset << " "
334  << "flags [" << flags << "] "
335  << "length: " << (m_payloadSize + 5 * 4)
336  << " "
337  << m_source << " > " << m_destination
338  ;
339 }
340 uint32_t
342 {
343  //return 5 * 4;
344  return m_headerSize;
345 }
346 
347 void
349 {
351 
352  uint8_t verIhl = (4 << 4) | (5);
353  i.WriteU8 (verIhl);
354  i.WriteU8 (m_tos);
355  i.WriteHtonU16 (m_payloadSize + 5*4);
357  uint32_t fragmentOffset = m_fragmentOffset / 8;
358  uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
359  if (m_flags & DONT_FRAGMENT)
360  {
361  flagsFrag |= (1<<6);
362  }
363  if (m_flags & MORE_FRAGMENTS)
364  {
365  flagsFrag |= (1<<5);
366  }
367  i.WriteU8 (flagsFrag);
368  uint8_t frag = fragmentOffset & 0xff;
369  i.WriteU8 (frag);
370  i.WriteU8 (m_ttl);
371  i.WriteU8 (m_protocol);
372  i.WriteHtonU16 (0);
373  i.WriteHtonU32 (m_source.Get ());
375 
376  if (m_calcChecksum)
377  {
378  i = start;
379  uint16_t checksum = i.CalculateIpChecksum (20);
380  NS_LOG_LOGIC ("checksum=" <<checksum);
381  i = start;
382  i.Next (10);
383  i.WriteU16 (checksum);
384  }
385 }
386 uint32_t
388 {
390  uint8_t verIhl = i.ReadU8 ();
391  uint8_t ihl = verIhl & 0x0f;
392  uint16_t headerSize = ihl * 4;
393  NS_ASSERT ((verIhl >> 4) == 4);
394  m_tos = i.ReadU8 ();
395  uint16_t size = i.ReadNtohU16 ();
396  m_payloadSize = size - headerSize;
398  uint8_t flags = i.ReadU8 ();
399  m_flags = 0;
400  if (flags & (1<<6))
401  {
403  }
404  if (flags & (1<<5))
405  {
407  }
408  i.Prev ();
409  m_fragmentOffset = i.ReadU8 () & 0x1f;
410  m_fragmentOffset <<= 8;
411  m_fragmentOffset |= i.ReadU8 ();
412  m_fragmentOffset <<= 3;
413  m_ttl = i.ReadU8 ();
414  m_protocol = i.ReadU8 ();
415  m_checksum = i.ReadU16 ();
416  /* i.Next (2); // checksum */
417  m_source.Set (i.ReadNtohU32 ());
419  m_headerSize = headerSize;
420 
421  if (m_calcChecksum)
422  {
423  i = start;
424  uint16_t checksum = i.CalculateIpChecksum (headerSize);
425  NS_LOG_LOGIC ("checksum=" <<checksum);
426 
427  m_goodChecksum = (checksum == 0);
428  }
429  return GetSerializedSize ();
430 }
431 
432 } // namespace ns3