A Discrete-Event Network Simulator
API
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 
27 namespace ns3
28 {
29 
30 NS_LOG_COMPONENT_DEFINE("Ipv4Header");
31 
32 NS_OBJECT_ENSURE_REGISTERED(Ipv4Header);
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 
49 void
51 {
52  NS_LOG_FUNCTION(this);
53  m_calcChecksum = true;
54 }
55 
56 void
58 {
59  NS_LOG_FUNCTION(this << size);
60  m_payloadSize = size;
61 }
62 
63 uint16_t
65 {
66  NS_LOG_FUNCTION(this);
67  return m_payloadSize;
68 }
69 
70 uint16_t
72 {
73  NS_LOG_FUNCTION(this);
74  return m_identification;
75 }
76 
77 void
78 Ipv4Header::SetIdentification(uint16_t identification)
79 {
80  NS_LOG_FUNCTION(this << identification);
81  m_identification = identification;
82 }
83 
84 void
85 Ipv4Header::SetTos(uint8_t tos)
86 {
87  NS_LOG_FUNCTION(this << static_cast<uint32_t>(tos));
88  m_tos = tos;
89 }
90 
91 void
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 
99 void
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 
115 std::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 
176 std::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 
195 uint8_t
197 {
198  NS_LOG_FUNCTION(this);
199  return m_tos;
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION(this);
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION(this);
214 }
215 
216 bool
218 {
219  NS_LOG_FUNCTION(this);
220  return !(m_flags & MORE_FRAGMENTS);
221 }
222 
223 void
225 {
226  NS_LOG_FUNCTION(this);
228 }
229 
230 void
232 {
233  NS_LOG_FUNCTION(this);
235 }
236 
237 bool
239 {
240  NS_LOG_FUNCTION(this);
241  return (m_flags & DONT_FRAGMENT);
242 }
243 
244 void
245 Ipv4Header::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 
253 uint16_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 
266 void
267 Ipv4Header::SetTtl(uint8_t ttl)
268 {
269  NS_LOG_FUNCTION(this << static_cast<uint32_t>(ttl));
270  m_ttl = ttl;
271 }
272 
273 uint8_t
275 {
276  NS_LOG_FUNCTION(this);
277  return m_ttl;
278 }
279 
280 uint8_t
282 {
283  NS_LOG_FUNCTION(this);
284  return m_protocol;
285 }
286 
287 void
288 Ipv4Header::SetProtocol(uint8_t protocol)
289 {
290  NS_LOG_FUNCTION(this << static_cast<uint32_t>(protocol));
291  m_protocol = protocol;
292 }
293 
294 void
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 
308 void
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 
322 bool
324 {
325  NS_LOG_FUNCTION(this);
326  return m_goodChecksum;
327 }
328 
329 TypeId
331 {
332  static TypeId tid = TypeId("ns3::Ipv4Header")
333  .SetParent<Header>()
334  .SetGroupName("Internet")
335  .AddConstructor<Ipv4Header>();
336  return tid;
337 }
338 
339 TypeId
341 {
342  NS_LOG_FUNCTION(this);
343  return GetTypeId();
344 }
345 
346 void
347 Ipv4Header::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 
383 uint32_t
385 {
386  NS_LOG_FUNCTION(this);
387  // return 5 * 4;
388  return m_headerSize;
389 }
390 
391 void
393 {
394  NS_LOG_FUNCTION(this << &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;
404  if (m_flags & DONT_FRAGMENT)
405  {
406  flagsFrag |= (1 << 6);
407  }
408  if (m_flags & MORE_FRAGMENTS)
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);
416  i.WriteU8(m_protocol);
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 
432 uint32_t
434 {
435  NS_LOG_FUNCTION(this << &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;
465  m_fragmentOffset |= i.ReadU8();
466  m_fragmentOffset <<= 3;
467  m_ttl = i.ReadU8();
468  m_protocol = i.ReadU8();
469  m_checksum = i.ReadU16();
470  /* i.Next (2); // checksum */
471  m_source.Set(i.ReadNtohU32());
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:1135
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteU16(uint16_t data)
Definition: buffer.cc:859
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
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
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
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:931
#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.