src/internet-node/ipv4-header.cc
changeset 3248 39f736210ab2
parent 3247 05e66ff64e10
parent 3229 ec45f705b9ca
child 3249 a7203cfb5f37
equal deleted inserted replaced
3247:05e66ff64e10 3248:39f736210ab2
     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/log.h"
       
    23 #include "ns3/header.h"
       
    24 #include "ipv4-header.h"
       
    25 
       
    26 NS_LOG_COMPONENT_DEFINE ("Ipv4Header");
       
    27 
       
    28 namespace ns3 {
       
    29 
       
    30 NS_OBJECT_ENSURE_REGISTERED (Ipv4Header);
       
    31 
       
    32 bool Ipv4Header::m_calcChecksum = false;
       
    33 
       
    34 Ipv4Header::Ipv4Header ()
       
    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_goodChecksum (true)
       
    43 {}
       
    44 
       
    45 void 
       
    46 Ipv4Header::EnableChecksums (void)
       
    47 {
       
    48   m_calcChecksum = true;
       
    49 }
       
    50 
       
    51 void 
       
    52 Ipv4Header::SetPayloadSize (uint16_t size)
       
    53 {
       
    54   m_payloadSize = size;
       
    55 }
       
    56 uint16_t 
       
    57 Ipv4Header::GetPayloadSize (void) const
       
    58 {
       
    59   return m_payloadSize;
       
    60 }
       
    61 
       
    62 uint16_t 
       
    63 Ipv4Header::GetIdentification (void) const
       
    64 {
       
    65   return m_identification;
       
    66 }
       
    67 void 
       
    68 Ipv4Header::SetIdentification (uint16_t identification)
       
    69 {
       
    70   m_identification = identification;
       
    71 }
       
    72 
       
    73 
       
    74 
       
    75 void 
       
    76 Ipv4Header::SetTos (uint8_t tos)
       
    77 {
       
    78   m_tos = tos;
       
    79 }
       
    80 uint8_t 
       
    81 Ipv4Header::GetTos (void) const
       
    82 {
       
    83   return m_tos;
       
    84 }
       
    85 void 
       
    86 Ipv4Header::SetMoreFragments (void)
       
    87 {
       
    88   m_flags |= MORE_FRAGMENTS;
       
    89 }
       
    90 void
       
    91 Ipv4Header::SetLastFragment (void)
       
    92 {
       
    93   m_flags &= ~MORE_FRAGMENTS;
       
    94 }
       
    95 bool 
       
    96 Ipv4Header::IsLastFragment (void) const
       
    97 {
       
    98   return !(m_flags & MORE_FRAGMENTS);
       
    99 }
       
   100 
       
   101 void 
       
   102 Ipv4Header::SetDontFragment (void)
       
   103 {
       
   104   m_flags |= DONT_FRAGMENT;
       
   105 }
       
   106 void 
       
   107 Ipv4Header::SetMayFragment (void)
       
   108 {
       
   109   m_flags &= ~DONT_FRAGMENT;
       
   110 }
       
   111 bool 
       
   112 Ipv4Header::IsDontFragment (void) const
       
   113 {
       
   114   return (m_flags & DONT_FRAGMENT);
       
   115 }
       
   116 
       
   117 void 
       
   118 Ipv4Header::SetFragmentOffset (uint16_t offset)
       
   119 {
       
   120   NS_ASSERT (!(offset & (~0x3fff)));
       
   121   m_fragmentOffset = offset;
       
   122 }
       
   123 uint16_t 
       
   124 Ipv4Header::GetFragmentOffset (void) const
       
   125 {
       
   126   NS_ASSERT (!(m_fragmentOffset & (~0x3fff)));
       
   127   return m_fragmentOffset;
       
   128 }
       
   129 
       
   130 void 
       
   131 Ipv4Header::SetTtl (uint8_t ttl)
       
   132 {
       
   133   m_ttl = ttl;
       
   134 }
       
   135 uint8_t 
       
   136 Ipv4Header::GetTtl (void) const
       
   137 {
       
   138   return m_ttl;
       
   139 }
       
   140   
       
   141 uint8_t 
       
   142 Ipv4Header::GetProtocol (void) const
       
   143 {
       
   144   return m_protocol;
       
   145 }
       
   146 void 
       
   147 Ipv4Header::SetProtocol (uint8_t protocol)
       
   148 {
       
   149   m_protocol = protocol;
       
   150 }
       
   151 
       
   152 void 
       
   153 Ipv4Header::SetSource (Ipv4Address source)
       
   154 {
       
   155   m_source = source;
       
   156 }
       
   157 Ipv4Address
       
   158 Ipv4Header::GetSource (void) const
       
   159 {
       
   160   return m_source;
       
   161 }
       
   162 
       
   163 void 
       
   164 Ipv4Header::SetDestination (Ipv4Address dst)
       
   165 {
       
   166   m_destination = dst;
       
   167 }
       
   168 Ipv4Address
       
   169 Ipv4Header::GetDestination (void) const
       
   170 {
       
   171   return m_destination;
       
   172 }
       
   173 
       
   174 
       
   175 bool
       
   176 Ipv4Header::IsChecksumOk (void) const
       
   177 {
       
   178   return m_goodChecksum;
       
   179 }
       
   180 
       
   181 
       
   182 TypeId 
       
   183 Ipv4Header::GetTypeId (void)
       
   184 {
       
   185   static TypeId tid = TypeId ("ns3::Ipv4Header")
       
   186     .SetParent<Header> ()
       
   187     .AddConstructor<Ipv4Header> ()
       
   188     ;
       
   189   return tid;
       
   190 }
       
   191 TypeId 
       
   192 Ipv4Header::GetInstanceTypeId (void) const
       
   193 {
       
   194   return GetTypeId ();
       
   195 }
       
   196 void 
       
   197 Ipv4Header::Print (std::ostream &os) const
       
   198 {
       
   199   // ipv4, right ?
       
   200   std::string flags;
       
   201   if (m_flags == 0)
       
   202     {
       
   203       flags = "none";
       
   204     }
       
   205   else if (m_flags & MORE_FRAGMENTS &&
       
   206            m_flags & DONT_FRAGMENT)
       
   207     {
       
   208       flags = "MF|DF";
       
   209     }
       
   210   else if (m_flags & DONT_FRAGMENT)
       
   211     {
       
   212       flags = "DF";
       
   213     }
       
   214   else if (m_flags & MORE_FRAGMENTS)
       
   215     {
       
   216       flags = "MF";
       
   217     }
       
   218   else
       
   219     {
       
   220       flags = "XX";
       
   221     }
       
   222   os << "tos 0x" << std::hex << m_tos << std::dec << " "
       
   223      << "ttl " << m_ttl << " "
       
   224      << "id " << m_identification << " "
       
   225      << "offset " << m_fragmentOffset << " "
       
   226      << "flags [" << flags << "] "
       
   227      << "length: " << (m_payloadSize + 5 * 4)
       
   228      << " " 
       
   229      << m_source << " > " << m_destination
       
   230     ;
       
   231 }
       
   232 uint32_t 
       
   233 Ipv4Header::GetSerializedSize (void) const
       
   234 {
       
   235   return 5 * 4;
       
   236 }
       
   237 
       
   238 void
       
   239 Ipv4Header::Serialize (Buffer::Iterator start) const
       
   240 {
       
   241   Buffer::Iterator i = start;
       
   242   
       
   243   uint8_t verIhl = (4 << 4) | (5);
       
   244   i.WriteU8 (verIhl);
       
   245   i.WriteU8 (m_tos);
       
   246   i.WriteHtonU16 (m_payloadSize + 5*4);
       
   247   i.WriteHtonU16 (m_identification);
       
   248   uint32_t fragmentOffset = m_fragmentOffset / 8;
       
   249   uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
       
   250   if (m_flags & DONT_FRAGMENT) 
       
   251     {
       
   252       flagsFrag |= (1<<6);
       
   253     }
       
   254   if (m_flags & MORE_FRAGMENTS) 
       
   255     {
       
   256       flagsFrag |= (1<<5);
       
   257     }
       
   258   i.WriteU8 (flagsFrag);
       
   259   uint8_t frag = fragmentOffset & 0xff;
       
   260   i.WriteU8 (frag);
       
   261   i.WriteU8 (m_ttl);
       
   262   i.WriteU8 (m_protocol);
       
   263   i.WriteHtonU16 (0);
       
   264   i.WriteHtonU32 (m_source.GetHostOrder ());
       
   265   i.WriteHtonU32 (m_destination.GetHostOrder ());
       
   266 
       
   267   if (m_calcChecksum) 
       
   268     {
       
   269 #if 0
       
   270       // XXX we need to add Buffer::Iterator::PeekData method
       
   271       uint8_t *data = start.PeekData ();
       
   272       uint16_t checksum = UtilsChecksumCalculate (0, data, GetSize ());
       
   273       checksum = UtilsChecksumComplete (checksum);
       
   274       NS_LOG_LOGIC ("checksum=" <<checksum);
       
   275       i = start;
       
   276       i.Next (10);
       
   277       i.WriteU16 (checksum);
       
   278 #endif
       
   279     }
       
   280 }
       
   281 uint32_t
       
   282 Ipv4Header::Deserialize (Buffer::Iterator start)
       
   283 {
       
   284   Buffer::Iterator i = start;
       
   285   uint8_t verIhl = i.ReadU8 ();
       
   286   uint8_t ihl = verIhl & 0x0f; 
       
   287   uint16_t headerSize = ihl * 4;
       
   288   NS_ASSERT ((verIhl >> 4) == 4);
       
   289   m_tos = i.ReadU8 ();
       
   290   uint16_t size = i.ReadNtohU16 ();
       
   291   m_payloadSize = size - headerSize;
       
   292   m_identification = i.ReadNtohU16 ();
       
   293   uint8_t flags = i.ReadU8 ();
       
   294   m_flags = 0;
       
   295   if (flags & (1<<6)) 
       
   296     {
       
   297       m_flags |= DONT_FRAGMENT;
       
   298     }
       
   299   if (flags & (1<<5)) 
       
   300     {
       
   301       m_flags |= MORE_FRAGMENTS;
       
   302     }
       
   303   //XXXX I think we should clear some bits in fragmentOffset !
       
   304   i.Prev ();
       
   305   m_fragmentOffset = i.ReadNtohU16 ();
       
   306   m_fragmentOffset *= 8;
       
   307   m_ttl = i.ReadU8 ();
       
   308   m_protocol = i.ReadU8 ();
       
   309   i.Next (2); // checksum
       
   310   m_source.SetHostOrder (i.ReadNtohU32 ());
       
   311   m_destination.SetHostOrder (i.ReadNtohU32 ());
       
   312 
       
   313   if (m_calcChecksum) 
       
   314     {
       
   315 #if 0
       
   316       uint8_t *data = start.PeekData ();
       
   317       uint16_t localChecksum = UtilsChecksumCalculate (0, data, headerSize);
       
   318       if (localChecksum == 0xffff) 
       
   319         {
       
   320           m_goodChecksum = true;
       
   321         } 
       
   322       else 
       
   323         {
       
   324           m_goodChecksum = false;
       
   325         }
       
   326 #endif
       
   327     }
       
   328   return GetSerializedSize ();
       
   329 }
       
   330 
       
   331 }; // namespace ns3