A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv4-l3-protocol.cc
Go to the documentation of this file.
1 // -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
2 //
3 // Copyright (c) 2006 Georgia Tech Research Corporation
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: George F. Riley<riley@ece.gatech.edu>
19 //
20 
21 #include "ns3/packet.h"
22 #include "ns3/log.h"
23 #include "ns3/callback.h"
24 #include "ns3/ipv4-address.h"
25 #include "ns3/ipv4-route.h"
26 #include "ns3/node.h"
27 #include "ns3/socket.h"
28 #include "ns3/net-device.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/trace-source-accessor.h"
31 #include "ns3/object-vector.h"
32 #include "ns3/ipv4-header.h"
33 #include "ns3/boolean.h"
34 #include "ns3/ipv4-routing-table-entry.h"
35 
36 #include "loopback-net-device.h"
37 #include "arp-l3-protocol.h"
38 #include "ipv4-l3-protocol.h"
39 #include "icmpv4-l4-protocol.h"
40 #include "ipv4-interface.h"
41 #include "ipv4-raw-socket-impl.h"
42 
43 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
44 
45 namespace ns3 {
46 
47 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
48 
49 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
50 
51 TypeId
53 {
54  static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
55  .SetParent<Ipv4> ()
56  .AddConstructor<Ipv4L3Protocol> ()
57  .AddAttribute ("DefaultTos", "The TOS value set by default on all outgoing packets generated on this node.",
58  UintegerValue (0),
59  MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTos),
60  MakeUintegerChecker<uint8_t> ())
61  .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
62  UintegerValue (64),
63  MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
64  MakeUintegerChecker<uint8_t> ())
65  .AddAttribute ("FragmentExpirationTimeout",
66  "When this timeout expires, the fragments will be cleared from the buffer.",
67  TimeValue (Seconds (30)),
69  MakeTimeChecker ())
70  .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
72  .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
74  .AddTraceSource ("Drop", "Drop ipv4 packet",
76  .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
79  MakeObjectVectorChecker<Ipv4Interface> ())
80 
81  .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
83  .AddTraceSource ("UnicastForward", "A unicast IPv4 packet was received by this node and is being forwarded to another node",
85  .AddTraceSource ("LocalDeliver", "An IPv4 packet was received by/for this node, and it is being forward up the stack",
87 
88  ;
89  return tid;
90 }
91 
93 {
94  NS_LOG_FUNCTION (this);
95 }
96 
98 {
99  NS_LOG_FUNCTION (this);
100 }
101 
102 void
104 {
105  NS_LOG_FUNCTION (this << protocol);
106  m_protocols.push_back (protocol);
107 }
109 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
110 {
111  NS_LOG_FUNCTION (this << protocolNumber);
112  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
113  {
114  if ((*i)->GetProtocolNumber () == protocolNumber)
115  {
116  return *i;
117  }
118  }
119  return 0;
120 }
121 void
123 {
124  NS_LOG_FUNCTION (this << protocol);
125  m_protocols.remove (protocol);
126 }
127 
128 void
130 {
131  NS_LOG_FUNCTION (this << node);
132  m_node = node;
133  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
134  SetupLoopback ();
135 }
136 
139 {
140  NS_LOG_FUNCTION (this);
141  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
142  socket->SetNode (m_node);
143  m_sockets.push_back (socket);
144  return socket;
145 }
146 void
148 {
149  NS_LOG_FUNCTION (this << socket);
150  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
151  {
152  if ((*i) == socket)
153  {
154  m_sockets.erase (i);
155  return;
156  }
157  }
158  return;
159 }
160 /*
161  * This method is called by AddAgregate and completes the aggregation
162  * by setting the node in the ipv4 stack
163  */
164 void
166 {
167  NS_LOG_FUNCTION (this);
168  if (m_node == 0)
169  {
170  Ptr<Node>node = this->GetObject<Node>();
171  // verify that it's a valid node and that
172  // the node has not been set before
173  if (node != 0)
174  {
175  this->SetNode (node);
176  }
177  }
179 }
180 
181 void
183 {
184  NS_LOG_FUNCTION (this << routingProtocol);
185  m_routingProtocol = routingProtocol;
186  m_routingProtocol->SetIpv4 (this);
187 }
188 
189 
192 {
193  NS_LOG_FUNCTION (this);
194  return m_routingProtocol;
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this);
201  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
202  {
203  *i = 0;
204  }
205  m_protocols.clear ();
206 
207  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
208  {
209  *i = 0;
210  }
211  m_interfaces.clear ();
212  m_sockets.clear ();
213  m_node = 0;
214  m_routingProtocol = 0;
215 
216  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
217  {
218  it->second = 0;
219  }
220 
221  for (MapFragmentsTimers_t::iterator it = m_fragmentsTimers.begin (); it != m_fragmentsTimers.end (); it++)
222  {
223  if (it->second.IsRunning ())
224  {
225  it->second.Cancel ();
226  }
227  }
228 
229  m_fragments.clear ();
230  m_fragmentsTimers.clear ();
231 
233 }
234 
235 void
237 {
238  NS_LOG_FUNCTION (this);
239 
240  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
241  Ptr<LoopbackNetDevice> device = 0;
242  // First check whether an existing LoopbackNetDevice exists on the node
243  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
244  {
245  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
246  {
247  break;
248  }
249  }
250  if (device == 0)
251  {
252  device = CreateObject<LoopbackNetDevice> ();
253  m_node->AddDevice (device);
254  }
255  interface->SetDevice (device);
256  interface->SetNode (m_node);
258  interface->AddAddress (ifaceAddr);
259  uint32_t index = AddIpv4Interface (interface);
260  Ptr<Node> node = GetObject<Node> ();
263  interface->SetUp ();
264  if (m_routingProtocol != 0)
265  {
266  m_routingProtocol->NotifyInterfaceUp (index);
267  }
268 }
269 
270 void
272 {
273  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
274  m_defaultTtl = ttl;
275 }
276 
277 uint32_t
279 {
280  NS_LOG_FUNCTION (this << device);
281 
282  Ptr<Node> node = GetObject<Node> ();
285  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
287 
288  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
289  interface->SetNode (m_node);
290  interface->SetDevice (device);
291  interface->SetForwarding (m_ipForward);
292  return AddIpv4Interface (interface);
293 }
294 
295 uint32_t
297 {
298  NS_LOG_FUNCTION (this << interface);
299  uint32_t index = m_interfaces.size ();
300  m_interfaces.push_back (interface);
301  return index;
302 }
303 
305 Ipv4L3Protocol::GetInterface (uint32_t index) const
306 {
307  NS_LOG_FUNCTION (this << index);
308  if (index < m_interfaces.size ())
309  {
310  return m_interfaces[index];
311  }
312  return 0;
313 }
314 
315 uint32_t
317 {
318  NS_LOG_FUNCTION (this);
319  return m_interfaces.size ();
320 }
321 
322 int32_t
324  Ipv4Address address) const
325 {
326  NS_LOG_FUNCTION (this << address);
327  int32_t interface = 0;
328  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
329  i != m_interfaces.end ();
330  i++, interface++)
331  {
332  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
333  {
334  if ((*i)->GetAddress (j).GetLocal () == address)
335  {
336  return interface;
337  }
338  }
339  }
340 
341  return -1;
342 }
343 
344 int32_t
347  Ipv4Mask mask) const
348 {
349  NS_LOG_FUNCTION (this << address << mask);
350  int32_t interface = 0;
351  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
352  i != m_interfaces.end ();
353  i++, interface++)
354  {
355  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
356  {
357  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
358  {
359  return interface;
360  }
361  }
362  }
363 
364  return -1;
365 }
366 
367 int32_t
369  Ptr<const NetDevice> device) const
370 {
371  NS_LOG_FUNCTION (this << device);
372  int32_t interface = 0;
373  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
374  i != m_interfaces.end ();
375  i++, interface++)
376  {
377  if ((*i)->GetDevice () == device)
378  {
379  return interface;
380  }
381  }
382 
383  return -1;
384 }
385 
386 bool
388 {
389  NS_LOG_FUNCTION (this << address << iif);
390  // First check the incoming interface for a unicast address match
391  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
392  {
393  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
394  if (address == iaddr.GetLocal ())
395  {
396  NS_LOG_LOGIC ("For me (destination " << address << " match)");
397  return true;
398  }
399  if (address == iaddr.GetBroadcast ())
400  {
401  NS_LOG_LOGIC ("For me (interface broadcast address)");
402  return true;
403  }
404  }
405 
406  if (address.IsMulticast ())
407  {
408 #ifdef NOTYET
409  if (MulticastCheckGroup (iif, address ))
410 #endif
411  if (true)
412  {
413  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
414  return true;
415  }
416  }
417 
418  if (address.IsBroadcast ())
419  {
420  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
421  return true;
422  }
423 
424  if (GetWeakEsModel ()) // Check other interfaces
425  {
426  for (uint32_t j = 0; j < GetNInterfaces (); j++)
427  {
428  if (j == uint32_t (iif)) continue;
429  for (uint32_t i = 0; i < GetNAddresses (j); i++)
430  {
431  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
432  if (address == iaddr.GetLocal ())
433  {
434  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
435  return true;
436  }
437  // This is a small corner case: match another interface's broadcast address
438  if (address == iaddr.GetBroadcast ())
439  {
440  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
441  return true;
442  }
443  }
444  }
445  }
446  return false;
447 }
448 
449 void
450 Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
451  const Address &to, NetDevice::PacketType packetType)
452 {
453  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
454 
455  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
456  m_node->GetId ());
457 
458  uint32_t interface = 0;
459  Ptr<Packet> packet = p->Copy ();
460 
461  Ptr<Ipv4Interface> ipv4Interface;
462  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
463  i != m_interfaces.end ();
464  i++, interface++)
465  {
466  ipv4Interface = *i;
467  if (ipv4Interface->GetDevice () == device)
468  {
469  if (ipv4Interface->IsUp ())
470  {
471  m_rxTrace (packet, m_node->GetObject<Ipv4> (), interface);
472  break;
473  }
474  else
475  {
476  NS_LOG_LOGIC ("Dropping received packet -- interface is down");
477  Ipv4Header ipHeader;
478  packet->RemoveHeader (ipHeader);
479  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
480  return;
481  }
482  }
483  }
484 
485  Ipv4Header ipHeader;
486  if (Node::ChecksumEnabled ())
487  {
488  ipHeader.EnableChecksum ();
489  }
490  packet->RemoveHeader (ipHeader);
491 
492  // Trim any residual frame padding from underlying devices
493  if (ipHeader.GetPayloadSize () < packet->GetSize ())
494  {
495  packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
496  }
497 
498  if (!ipHeader.IsChecksumOk ())
499  {
500  NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
501  m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject<Ipv4> (), interface);
502  return;
503  }
504 
505  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
506  {
507  NS_LOG_LOGIC ("Forwarding to raw socket");
508  Ptr<Ipv4RawSocketImpl> socket = *i;
509  socket->ForwardUp (packet, ipHeader, ipv4Interface);
510  }
511 
512  NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
513  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
518  ))
519  {
520  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
521  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), interface);
522  }
523 }
524 
527 {
528  NS_LOG_FUNCTION (this);
530  if (prot != 0)
531  {
532  return prot->GetObject<Icmpv4L4Protocol> ();
533  }
534  else
535  {
536  return 0;
537  }
538 }
539 
540 bool
542 {
543  NS_LOG_FUNCTION (this << ad);
544 
545  if (ad.IsBroadcast () || ad.IsMulticast ())
546  {
547  return false;
548  }
549  else
550  {
551  // check for subnet-broadcast
552  for (uint32_t ifaceIndex = 0; ifaceIndex < GetNInterfaces (); ifaceIndex++)
553  {
554  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
555  {
556  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
557  NS_LOG_LOGIC ("Testing address " << ad << " with subnet-directed broadcast " << ifAddr.GetBroadcast () );
558  if (ad == ifAddr.GetBroadcast () )
559  {
560  return false;
561  }
562  }
563  }
564  }
565 
566  return true;
567 }
568 
569 bool
571 {
572  NS_LOG_FUNCTION (this << ad << interfaceMask);
573  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
574 }
575 
576 void
578  Ipv4Header ipHeader,
579  Ptr<Ipv4Route> route)
580 {
581  NS_LOG_FUNCTION (this << packet << ipHeader << route);
582  if (Node::ChecksumEnabled ())
583  {
584  ipHeader.EnableChecksum ();
585  }
586  SendRealOut (route, packet, ipHeader);
587 }
588 
589 void
591  Ipv4Address source,
592  Ipv4Address destination,
593  uint8_t protocol,
594  Ptr<Ipv4Route> route)
595 {
596  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
597 
598  Ipv4Header ipHeader;
599  bool mayFragment = true;
600  uint8_t ttl = m_defaultTtl;
601  SocketIpTtlTag tag;
602  bool found = packet->RemovePacketTag (tag);
603  if (found)
604  {
605  ttl = tag.GetTtl ();
606  }
607 
608  uint8_t tos = m_defaultTos;
609  SocketIpTosTag ipTosTag;
610  found = packet->RemovePacketTag (ipTosTag);
611  if (found)
612  {
613  tos = ipTosTag.GetTos ();
614  }
615 
616  // Handle a few cases:
617  // 1) packet is destined to limited broadcast address
618  // 2) packet is destined to a subnet-directed broadcast address
619  // 3) packet is not broadcast, and is passed in with a route entry
620  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
621  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
622 
623  // 1) packet is destined to limited broadcast address or link-local multicast address
624  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
625  {
626  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
627  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
628  uint32_t ifaceIndex = 0;
629  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
630  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
631  {
632  Ptr<Ipv4Interface> outInterface = *ifaceIter;
633  Ptr<Packet> packetCopy = packet->Copy ();
634 
635  NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ());
636 
637  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
638  packetCopy->AddHeader (ipHeader);
639  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
640  outInterface->Send (packetCopy, destination);
641  }
642  return;
643  }
644 
645  // 2) check: packet is destined to a subnet-directed broadcast address
646  uint32_t ifaceIndex = 0;
647  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
648  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
649  {
650  Ptr<Ipv4Interface> outInterface = *ifaceIter;
651  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
652  {
653  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
654  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
655  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
656  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
657  {
658  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
659  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
660  Ptr<Packet> packetCopy = packet->Copy ();
661  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
662  packetCopy->AddHeader (ipHeader);
663  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
664  outInterface->Send (packetCopy, destination);
665  return;
666  }
667  }
668  }
669 
670  // 3) packet is not broadcast, and is passed in with a route entry
671  // with a valid Ipv4Address as the gateway
672  if (route && route->GetGateway () != Ipv4Address ())
673  {
674  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
675  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
676  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
677  m_sendOutgoingTrace (ipHeader, packet, interface);
678  SendRealOut (route, packet->Copy (), ipHeader);
679  return;
680  }
681  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
682  if (route && route->GetGateway () == Ipv4Address ())
683  {
684  // This could arise because the synchronous RouteOutput() call
685  // returned to the transport protocol with a source address but
686  // there was no next hop available yet (since a route may need
687  // to be queried).
688  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 4: This case not yet implemented");
689  }
690  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
691  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 5: passed in with no route " << destination);
692  Socket::SocketErrno errno_;
693  Ptr<NetDevice> oif (0); // unused for now
694  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
695  Ptr<Ipv4Route> newRoute;
696  if (m_routingProtocol != 0)
697  {
698  newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
699  }
700  else
701  {
702  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
703  }
704  if (newRoute)
705  {
706  int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
707  m_sendOutgoingTrace (ipHeader, packet, interface);
708  SendRealOut (newRoute, packet->Copy (), ipHeader);
709  }
710  else
711  {
712  NS_LOG_WARN ("No route to host. Drop.");
713  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
714  }
715 }
716 
717 // \todo when should we set ip_id? check whether we are incrementing
718 // m_identification on packets that may later be dropped in this stack
719 // and whether that deviates from Linux
722  Ipv4Address source,
723  Ipv4Address destination,
724  uint8_t protocol,
725  uint16_t payloadSize,
726  uint8_t ttl,
727  uint8_t tos,
728  bool mayFragment)
729 {
730  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
731  Ipv4Header ipHeader;
732  ipHeader.SetSource (source);
733  ipHeader.SetDestination (destination);
734  ipHeader.SetProtocol (protocol);
735  ipHeader.SetPayloadSize (payloadSize);
736  ipHeader.SetTtl (ttl);
737  ipHeader.SetTos (tos);
738 
739  uint64_t src = source.Get ();
740  uint64_t dst = destination.Get ();
741  uint64_t srcDst = dst | (src << 32);
742  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
743 
744  if (mayFragment == true)
745  {
746  ipHeader.SetMayFragment ();
747  ipHeader.SetIdentification (m_identification[key]);
748  m_identification[key]++;
749  }
750  else
751  {
752  ipHeader.SetDontFragment ();
753  // RFC 6864 does not state anything about atomic datagrams
754  // identification requirement:
755  // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
756  // to any value.
757  ipHeader.SetIdentification (m_identification[key]);
758  m_identification[key]++;
759  }
760  if (Node::ChecksumEnabled ())
761  {
762  ipHeader.EnableChecksum ();
763  }
764  return ipHeader;
765 }
766 
767 void
769  Ptr<Packet> packet,
770  Ipv4Header const &ipHeader)
771 {
772  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
773  if (route == 0)
774  {
775  NS_LOG_WARN ("No route to host. Drop.");
776  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
777  return;
778  }
779  packet->AddHeader (ipHeader);
780  Ptr<NetDevice> outDev = route->GetOutputDevice ();
781  int32_t interface = GetInterfaceForDevice (outDev);
782  NS_ASSERT (interface >= 0);
783  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
784  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
785 
786  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
787  {
788  if (outInterface->IsUp ())
789  {
790  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
791  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
792  {
793  std::list<Ptr<Packet> > listFragments;
794  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
795  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
796  {
797  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
798  outInterface->Send (*it, route->GetGateway ());
799  }
800  }
801  else
802  {
803  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
804  outInterface->Send (packet, route->GetGateway ());
805  }
806  }
807  else
808  {
809  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
810  Ipv4Header ipHeader;
811  packet->RemoveHeader (ipHeader);
812  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
813  }
814  }
815  else
816  {
817  if (outInterface->IsUp ())
818  {
819  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
820  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
821  {
822  std::list<Ptr<Packet> > listFragments;
823  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
824  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
825  {
826  NS_LOG_LOGIC ("Sending fragment " << **it );
827  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
828  outInterface->Send (*it, ipHeader.GetDestination ());
829  }
830  }
831  else
832  {
833  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
834  outInterface->Send (packet, ipHeader.GetDestination ());
835  }
836  }
837  else
838  {
839  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
840  Ipv4Header ipHeader;
841  packet->RemoveHeader (ipHeader);
842  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
843  }
844  }
845 }
846 
847 // This function analogous to Linux ip_mr_forward()
848 void
850 {
851  NS_LOG_FUNCTION (this << mrtentry << p << header);
852  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
853 
854  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
855  std::map<uint32_t, uint32_t>::iterator mapIter;
856 
857  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
858  {
859  uint32_t interfaceId = mapIter->first;
860  //uint32_t outputTtl = mapIter->second; // Unused for now
861 
862  Ptr<Packet> packet = p->Copy ();
863  Ipv4Header h = header;
864  h.SetTtl (header.GetTtl () - 1);
865  if (h.GetTtl () == 0)
866  {
867  NS_LOG_WARN ("TTL exceeded. Drop.");
868  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interfaceId);
869  return;
870  }
871  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
872  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
873  rtentry->SetSource (h.GetSource ());
874  rtentry->SetDestination (h.GetDestination ());
875  rtentry->SetGateway (Ipv4Address::GetAny ());
876  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
877  SendRealOut (rtentry, packet, h);
878  continue;
879  }
880 }
881 
882 // This function analogous to Linux ip_forward()
883 void
885 {
886  NS_LOG_FUNCTION (this << rtentry << p << header);
887  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
888  // Forwarding
889  Ipv4Header ipHeader = header;
890  Ptr<Packet> packet = p->Copy ();
891  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
892  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
893  if (ipHeader.GetTtl () == 0)
894  {
895  // Do not reply to ICMP or to multicast/broadcast IP address
896  if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
897  ipHeader.GetDestination ().IsBroadcast () == false &&
898  ipHeader.GetDestination ().IsMulticast () == false)
899  {
900  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
901  icmp->SendTimeExceededTtl (ipHeader, packet);
902  }
903  NS_LOG_WARN ("TTL exceeded. Drop.");
904  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
905  return;
906  }
907  m_unicastForwardTrace (ipHeader, packet, interface);
908  SendRealOut (rtentry, packet, ipHeader);
909 }
910 
911 void
913 {
914  NS_LOG_FUNCTION (this << packet << &ip << iif);
915  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
916  Ipv4Header ipHeader = ip;
917 
918  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
919  {
920  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
921  bool isPacketComplete;
922  isPacketComplete = ProcessFragment (p, ipHeader, iif);
923  if ( isPacketComplete == false)
924  {
925  return;
926  }
927  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
928  ipHeader.SetFragmentOffset (0);
929  ipHeader.SetPayloadSize (p->GetSize () + ipHeader.GetSerializedSize ());
930  }
931 
932  m_localDeliverTrace (ipHeader, p, iif);
933 
934  Ptr<IpL4Protocol> protocol = GetProtocol (ipHeader.GetProtocol ());
935  if (protocol != 0)
936  {
937  // we need to make a copy in the unlikely event we hit the
938  // RX_ENDPOINT_UNREACH codepath
939  Ptr<Packet> copy = p->Copy ();
940  enum IpL4Protocol::RxStatus status =
941  protocol->Receive (p, ipHeader, GetInterface (iif));
942  switch (status) {
943  case IpL4Protocol::RX_OK:
944  // fall through
946  // fall through
948  break;
950  if (ipHeader.GetDestination ().IsBroadcast () == true ||
951  ipHeader.GetDestination ().IsMulticast () == true)
952  {
953  break; // Do not reply to broadcast or multicast
954  }
955  // Another case to suppress ICMP is a subnet-directed broadcast
956  bool subnetDirected = false;
957  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
958  {
959  Ipv4InterfaceAddress addr = GetAddress (iif, i);
960  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ipHeader.GetDestination ().CombineMask (addr.GetMask ()) &&
961  ipHeader.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
962  {
963  subnetDirected = true;
964  }
965  }
966  if (subnetDirected == false)
967  {
968  GetIcmp ()->SendDestUnreachPort (ipHeader, copy);
969  }
970  }
971  }
972 }
973 
974 bool
976 {
977  NS_LOG_FUNCTION (this << i << address);
978  Ptr<Ipv4Interface> interface = GetInterface (i);
979  bool retVal = interface->AddAddress (address);
980  if (m_routingProtocol != 0)
981  {
982  m_routingProtocol->NotifyAddAddress (i, address);
983  }
984  return retVal;
985 }
986 
988 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
989 {
990  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
991  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
992  return interface->GetAddress (addressIndex);
993 }
994 
995 uint32_t
996 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
997 {
998  NS_LOG_FUNCTION (this << interface);
999  Ptr<Ipv4Interface> iface = GetInterface (interface);
1000  return iface->GetNAddresses ();
1001 }
1002 
1003 bool
1004 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
1005 {
1006  NS_LOG_FUNCTION (this << i << addressIndex);
1007  Ptr<Ipv4Interface> interface = GetInterface (i);
1008  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
1009  if (address != Ipv4InterfaceAddress ())
1010  {
1011  if (m_routingProtocol != 0)
1012  {
1013  m_routingProtocol->NotifyRemoveAddress (i, address);
1014  }
1015  return true;
1016  }
1017  return false;
1018 }
1019 
1020 bool
1022 {
1023  NS_LOG_FUNCTION (this << i << address);
1024 
1025  if (address == Ipv4Address::GetLoopback())
1026  {
1027  NS_LOG_WARN ("Cannot remove loopback address.");
1028  return false;
1029  }
1030  Ptr<Ipv4Interface> interface = GetInterface (i);
1031  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
1032  if (ifAddr != Ipv4InterfaceAddress ())
1033  {
1034  if (m_routingProtocol != 0)
1035  {
1036  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
1037  }
1038  return true;
1039  }
1040  return false;
1041 }
1042 
1043 Ipv4Address
1046 {
1047  NS_LOG_FUNCTION (this << device << dst << scope);
1048  Ipv4Address addr ("0.0.0.0");
1049  Ipv4InterfaceAddress iaddr;
1050  bool found = false;
1051 
1052  if (device != 0)
1053  {
1054  int32_t i = GetInterfaceForDevice (device);
1055  NS_ASSERT_MSG (i >= 0, "No device found on node");
1056  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1057  {
1058  iaddr = GetAddress (i, j);
1059  if (iaddr.IsSecondary ()) continue;
1060  if (iaddr.GetScope () > scope) continue;
1061  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1062  {
1063  return iaddr.GetLocal ();
1064  }
1065  if (!found)
1066  {
1067  addr = iaddr.GetLocal ();
1068  found = true;
1069  }
1070  }
1071  }
1072  if (found)
1073  {
1074  return addr;
1075  }
1076 
1077  // Iterate among all interfaces
1078  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1079  {
1080  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1081  {
1082  iaddr = GetAddress (i, j);
1083  if (iaddr.IsSecondary ()) continue;
1084  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1085  && iaddr.GetScope () <= scope)
1086  {
1087  return iaddr.GetLocal ();
1088  }
1089  }
1090  }
1091  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1092  << scope << ", returning 0");
1093  return addr;
1094 }
1095 
1096 void
1097 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1098 {
1099  NS_LOG_FUNCTION (this << i << metric);
1100  Ptr<Ipv4Interface> interface = GetInterface (i);
1101  interface->SetMetric (metric);
1102 }
1103 
1104 uint16_t
1105 Ipv4L3Protocol::GetMetric (uint32_t i) const
1106 {
1107  NS_LOG_FUNCTION (this << i);
1108  Ptr<Ipv4Interface> interface = GetInterface (i);
1109  return interface->GetMetric ();
1110 }
1111 
1112 uint16_t
1113 Ipv4L3Protocol::GetMtu (uint32_t i) const
1114 {
1115  NS_LOG_FUNCTION (this << i);
1116  Ptr<Ipv4Interface> interface = GetInterface (i);
1117  return interface->GetDevice ()->GetMtu ();
1118 }
1119 
1120 bool
1121 Ipv4L3Protocol::IsUp (uint32_t i) const
1122 {
1123  NS_LOG_FUNCTION (this << i);
1124  Ptr<Ipv4Interface> interface = GetInterface (i);
1125  return interface->IsUp ();
1126 }
1127 
1128 void
1130 {
1131  NS_LOG_FUNCTION (this << i);
1132  Ptr<Ipv4Interface> interface = GetInterface (i);
1133 
1134  // RFC 791, pg.25:
1135  // Every internet module must be able to forward a datagram of 68
1136  // octets without further fragmentation. This is because an internet
1137  // header may be up to 60 octets, and the minimum fragment is 8 octets.
1138  if (interface->GetDevice ()->GetMtu () >= 68)
1139  {
1140  interface->SetUp ();
1141 
1142  if (m_routingProtocol != 0)
1143  {
1144  m_routingProtocol->NotifyInterfaceUp (i);
1145  }
1146  }
1147  else
1148  {
1149  NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octects)");
1150  }
1151 }
1152 
1153 void
1154 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1155 {
1156  NS_LOG_FUNCTION (this << ifaceIndex);
1157  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1158  interface->SetDown ();
1159 
1160  if (m_routingProtocol != 0)
1161  {
1162  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1163  }
1164 }
1165 
1166 bool
1168 {
1169  NS_LOG_FUNCTION (this << i);
1170  Ptr<Ipv4Interface> interface = GetInterface (i);
1171  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1172  return interface->IsForwarding ();
1173 }
1174 
1175 void
1176 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1177 {
1178  NS_LOG_FUNCTION (this << i);
1179  Ptr<Ipv4Interface> interface = GetInterface (i);
1180  interface->SetForwarding (val);
1181 }
1182 
1185 {
1186  NS_LOG_FUNCTION (this << i);
1187  return GetInterface (i)->GetDevice ();
1188 }
1189 
1190 void
1192 {
1193  NS_LOG_FUNCTION (this << forward);
1194  m_ipForward = forward;
1195  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1196  {
1197  (*i)->SetForwarding (forward);
1198  }
1199 }
1200 
1201 bool
1203 {
1204  NS_LOG_FUNCTION (this);
1205  return m_ipForward;
1206 }
1207 
1208 void
1210 {
1211  NS_LOG_FUNCTION (this << model);
1212  m_weakEsModel = model;
1213 }
1214 
1215 bool
1217 {
1218  NS_LOG_FUNCTION (this);
1219  return m_weakEsModel;
1220 }
1221 
1222 void
1224 {
1225  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1226  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1227  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1228 }
1229 
1230 void
1231 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::list<Ptr<Packet> >& listFragments)
1232 {
1233  // BEWARE: here we do assume that the header options are not present.
1234  // a much more complex handling is necessary in case there are options.
1235  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1236  // Of course also the reassemby code shall be changed as well.
1237 
1238  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1239 
1240  Ptr<Packet> p = packet->Copy ();
1241 
1242  Ipv4Header ipv4Header;
1243  p->RemoveHeader (ipv4Header);
1244 
1245  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1246  "IPv4 fragmentation implementation only works without option headers." );
1247 
1248  uint16_t offset = 0;
1249  bool moreFragment = true;
1250  uint16_t originalOffset = 0;
1251  bool alreadyFragmented = false;
1252  uint32_t currentFragmentablePartSize = 0;
1253 
1254  if (!ipv4Header.IsLastFragment())
1255  {
1256  alreadyFragmented = true;
1257  originalOffset = ipv4Header.GetFragmentOffset();
1258  }
1259 
1260  // IPv4 fragments are all 8 bytes aligned but the last.
1261  // The IP payload size is:
1262  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1263  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1264 
1265  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1266 
1267  do
1268  {
1269  Ipv4Header fragmentHeader = ipv4Header;
1270 
1271  if (p->GetSize () > offset + fragmentSize )
1272  {
1273  moreFragment = true;
1274  currentFragmentablePartSize = fragmentSize;
1275  fragmentHeader.SetMoreFragments ();
1276  }
1277  else
1278  {
1279  moreFragment = false;
1280  currentFragmentablePartSize = p->GetSize () - offset;
1281  if (alreadyFragmented)
1282  {
1283  fragmentHeader.SetMoreFragments ();
1284  }
1285  else
1286  {
1287  fragmentHeader.SetLastFragment ();
1288  }
1289  }
1290 
1291  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1292  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1293  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1294 
1295  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1296  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1297 
1298  if (Node::ChecksumEnabled ())
1299  {
1300  fragmentHeader.EnableChecksum ();
1301  }
1302 
1303  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1304 
1305  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1306  fragment->AddHeader (fragmentHeader);
1307 
1308  std::ostringstream oss;
1309  fragment->Print (oss);
1310 
1311  NS_LOG_LOGIC ("New fragment " << *fragment);
1312 
1313  listFragments.push_back (fragment);
1314 
1315  offset += currentFragmentablePartSize;
1316 
1317  }
1318  while (moreFragment);
1319 
1320  return;
1321 }
1322 
1323 bool
1324 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1325 {
1326  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1327 
1328  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
1329  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
1330  std::pair<uint64_t, uint32_t> key;
1331  bool ret = false;
1332  Ptr<Packet> p = packet->Copy ();
1333 
1334  key.first = addressCombination;
1335  key.second = idProto;
1336 
1337  Ptr<Fragments> fragments;
1338 
1339  MapFragments_t::iterator it = m_fragments.find (key);
1340  if (it == m_fragments.end ())
1341  {
1342  fragments = Create<Fragments> ();
1343  m_fragments.insert (std::make_pair (key, fragments));
1346  key, ipHeader, iif);
1347  }
1348  else
1349  {
1350  fragments = it->second;
1351  }
1352 
1353  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1354 
1355  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1356 
1357  if ( fragments->IsEntire () )
1358  {
1359  packet = fragments->GetPacket ();
1360  fragments = 0;
1361  m_fragments.erase (key);
1362  if (m_fragmentsTimers[key].IsRunning ())
1363  {
1364  NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1365  m_fragmentsTimers[key].Cancel ();
1366  }
1367  m_fragmentsTimers.erase (key);
1368  ret = true;
1369  }
1370 
1371  return ret;
1372 }
1373 
1375  : m_moreFragment (0)
1376 {
1377  NS_LOG_FUNCTION (this);
1378 }
1379 
1381 {
1382  NS_LOG_FUNCTION (this);
1383 }
1384 
1385 void
1386 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1387 {
1388  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1389 
1390  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1391 
1392  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1393  {
1394  if (it->second > fragmentOffset)
1395  {
1396  break;
1397  }
1398  }
1399 
1400  if (it == m_fragments.end ())
1401  {
1402  m_moreFragment = moreFragment;
1403  }
1404 
1405  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1406 }
1407 
1408 bool
1410 {
1411  NS_LOG_FUNCTION (this);
1412 
1413  bool ret = !m_moreFragment && m_fragments.size () > 0;
1414 
1415  if (ret)
1416  {
1417  uint16_t lastEndOffset = 0;
1418 
1419  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1420  {
1421  // overlapping fragments do exist
1422  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1423 
1424  if (lastEndOffset < it->second)
1425  {
1426  ret = false;
1427  break;
1428  }
1429  // fragments might overlap in strange ways
1430  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1431  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1432  }
1433  }
1434 
1435  return ret;
1436 }
1437 
1440 {
1441  NS_LOG_FUNCTION (this);
1442 
1443  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1444 
1445  Ptr<Packet> p = it->first->Copy ();
1446  uint16_t lastEndOffset = p->GetSize ();
1447  it++;
1448 
1449  for ( ; it != m_fragments.end (); it++)
1450  {
1451  if ( lastEndOffset > it->second )
1452  {
1453  // The fragments are overlapping.
1454  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1455  // This is different from what Linux does.
1456  // It is not possible to emulate a fragmentation attack.
1457  uint32_t newStart = lastEndOffset - it->second;
1458  if ( it->first->GetSize () > newStart )
1459  {
1460  uint32_t newSize = it->first->GetSize () - newStart;
1461  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1462  p->AddAtEnd (tempFragment);
1463  }
1464  }
1465  else
1466  {
1467  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1468  p->AddAtEnd (it->first);
1469  }
1470  lastEndOffset = p->GetSize ();
1471  }
1472 
1473  return p;
1474 }
1475 
1478 {
1479  NS_LOG_FUNCTION (this);
1480 
1481  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1482 
1483  Ptr<Packet> p = Create<Packet> ();
1484  uint16_t lastEndOffset = 0;
1485 
1486  if ( m_fragments.begin ()->second > 0 )
1487  {
1488  return p;
1489  }
1490 
1491  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1492  {
1493  if ( lastEndOffset > it->second )
1494  {
1495  uint32_t newStart = lastEndOffset - it->second;
1496  uint32_t newSize = it->first->GetSize () - newStart;
1497  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1498  p->AddAtEnd (tempFragment);
1499  }
1500  else if ( lastEndOffset == it->second )
1501  {
1502  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1503  p->AddAtEnd (it->first);
1504  }
1505  lastEndOffset = p->GetSize ();
1506  }
1507 
1508  return p;
1509 }
1510 
1511 void
1512 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
1513 {
1514  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1515 
1516  MapFragments_t::iterator it = m_fragments.find (key);
1517  Ptr<Packet> packet = it->second->GetPartialPacket ();
1518 
1519  // if we have at least 8 bytes, we can send an ICMP.
1520  if ( packet->GetSize () > 8 )
1521  {
1522  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1523  icmp->SendTimeExceededTtl (ipHeader, packet);
1524  }
1525  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1526 
1527  // clear the buffers
1528  it->second = 0;
1529 
1530  m_fragments.erase (key);
1531  m_fragmentsTimers.erase (key);
1532 }
1533 } // namespace ns3
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:285
void SetDown(void)
Disable this interface.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
bool m_weakEsModel
Weak ES model state.
void SetForwarding(bool val)
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberContainer)
Definition: object-vector.h:51
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
void SetDefaultTtl(uint8_t ttl)
virtual void SetIpForward(bool forward)
Set or unset the IP forwarding state.
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Receive a packet.
Ptr< Packet > GetPacket() const
Get the entire packet.
static Ipv4Address GetAny(void)
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 "...
virtual void NotifyNewAggregate()
This function will notify other components connected to the node that a new stack member is now conne...
Time m_fragmentExpirationTimeout
Expiration timeout.
Ipv4Mask GetMask(void) const
Get the network mask.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
Ipv4Address GetLocal(void) const
Get the local address.
uint8_t GetTos(void) const
Get the tag's TOS.
Definition: socket.cc:766
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_sendOutgoingTrace
Trace of sent packets.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:222
void Send(Ptr< Packet > p, Ipv4Address dest)
static bool ChecksumEnabled(void)
Definition: node.cc:268
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
bool IsLocalMulticast(void) const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual bool GetWeakEsModel(void) const
Get the Weak Es Model status.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
bool IsMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
Definition: ipv4-header.cc:238
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
int32_t GetInterfaceForPrefix(Ipv4Address addr, Ipv4Mask mask) const
Return the interface number of first interface found that has an Ipv4 address within the prefix speci...
bool AddAddress(Ipv4InterfaceAddress address)
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
uint32_t AddInterface(Ptr< NetDevice > device)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
TracedCallback< const Ipv4Header &, Ptr< const Packet >, DropReason, Ptr< Ipv4 >, uint32_t > m_dropTrace
Trace of dropped packets.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:999
void SetDontFragment(void)
Don't fragment this packet: if you need to anyway, drop it.
Definition: ipv4-header.cc:219
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:429
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
Ptr< Ipv4RoutingProtocol > m_routingProtocol
Routing protocol associated with the stack.
void SetUp(uint32_t i)
uint8_t m_defaultTos
Default TOS.
L4List_t m_protocols
List of transport protocol.
a polymophic address class
Definition: address.h:86
Ipv4InterfaceAddress GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
Because addresses can be removed, the addressIndex is not guaranteed to be static across calls to thi...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:444
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
Ptr< T > CreateObject(void)
Definition: object.h:421
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
Ptr< NetDevice > GetOutputDevice(void) const
Definition: ipv4-route.cc:84
Ipv4InterfaceList m_interfaces
List of IPv4 interfaces.
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const
Determine whether address and interface corresponding to received packet can be accepted for local de...
Ptr< Packet > GetPartialPacket() const
Get the complete part of the packet.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_rxTrace
Trace of received packets.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:228
Packet header for IPv4.
Definition: ipv4-header.h:31
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:317
void SetLastFragment(void)
This packet is the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:206
void SetupLoopback(void)
Setup loopback interface.
Attribute for objects of type ns3::Time.
Definition: nstime.h:912
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
uint32_t Get(void) const
Get the host-order 32-bit IP address.
void SetGateway(Ipv4Address gw)
Definition: ipv4-route.cc:63
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_txTrace
Trace of transmitted packets.
Hold an unsigned integer type.
Definition: uinteger.h:46
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_localDeliverTrace
Trace of locally delivered packets.
void EnableChecksum(void)
Enable checksum calculation for this header.
Definition: ipv4-header.cc:49
bool IsEntire() const
If all fragments have been added.
void SetMetric(uint32_t i, uint16_t metric)
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
bool IsBroadcast(void) const
T * PeekPointer(const Ptr< T > &p)
Definition: ptr.h:280
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:134
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1283
virtual enum RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > incomingInterface)=0
Called from lower-level layers to send the packet up in the stack.
void SetIdentification(uint16_t identification)
Definition: ipv4-header.cc:75
void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)
void SetMayFragment(void)
If you need to fragment this packet, you can do it.
Definition: ipv4-header.cc:225
static TypeId GetTypeId(void)
Get the type ID.
bool IsUp(uint32_t i) const
MapFragments_t m_fragments
Fragmented packets.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
void IpForward(Ptr< Ipv4Route > rtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a packet.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
Ipv4Address GetGateway(void) const
Definition: ipv4-route.cc:70
#define list
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
Remove the address at addressIndex on named interface.
bool IsSecondary(void) const
Check if the address is a secondary address.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
virtual void NotifyNewAggregate(void)
This method is invoked whenever two sets of objects are aggregated together.
Definition: object.cc:314
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
bool m_ipForward
Forwarding packets (i.e.
uint32_t GetNDevices(void) const
Definition: node.cc:142
void SetForwarding(uint32_t i, bool val)
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address...
bool IsEqual(const Ipv4Address &other) const
Comparison operation between two Ipv4Addresses.
Definition: ipv4-address.h:81
void SetMoreFragments(void)
This packet is not the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:200
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
void DoFragmentation(Ptr< Packet > packet, uint32_t outIfaceMtu, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
Ptr< Node > m_node
Node attached to stack.
void RouteInputError(Ptr< const Packet > p, const Ipv4Header &ipHeader, Socket::SocketErrno sockErrno)
Fallback when no route is found.
Ipv4Header BuildHeader(Ipv4Address source, Ipv4Address destination, uint8_t protocol, uint16_t payloadSize, uint8_t ttl, uint8_t tos, bool mayFragment)
Construct an IPv4 header.
void SendRealOut(Ptr< Ipv4Route > route, Ptr< Packet > packet, Ipv4Header const &ipHeader)
Send packet with route.
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Equivalent in Linux to dst_entry.dev.
Definition: ipv4-route.cc:77
static Ipv4Address GetLoopback(void)
static Ipv4Mask GetLoopback(void)
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:219
Ptr< NetDevice > GetNetDevice(uint32_t i)
uint16_t GetMetric(void) const
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:84
bool ProcessFragment(Ptr< Packet > &packet, Ipv4Header &ipHeader, uint32_t iif)
Process a packet fragment.
uint32_t AddIpv4Interface(Ptr< Ipv4Interface > interface)
Add an IPv4 interface to the stack.
void Remove(Ptr< IpL4Protocol > protocol)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
Ipv4Address GetBroadcast(void) const
Get the broadcast address.
virtual void SetWeakEsModel(bool model)
Set or unset the Weak Es Model.
void SetNode(Ptr< Node > node)
Set node associated with this stack.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:120
uint32_t GetId(void) const
Definition: node.cc:106
a class to store IPv4 address information on an interface
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
SocketList m_sockets
List of IPv4 raw sockets.
void DeleteRawSocket(Ptr< Socket > socket)
Deletes a particular raw socket.
bool AddAddress(uint32_t i, Ipv4InterfaceAddress address)
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:203
Ptr< NetDevice > GetDevice(void) const
Ptr< Ipv4Interface > GetInterface(uint32_t i) const
Get an interface.
static uint16_t GetStaticProtocolNumber(void)
Get the protocol number.
void Insert(Ptr< IpL4Protocol > protocol)
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:848
bool IsUnicast(Ipv4Address ad) const
Check if an IPv4 address is unicast according to the node.
void LocalDeliver(Ptr< const Packet > p, Ipv4Header const &ip, uint32_t iif)
Deliver a packet.
void IpMulticastForward(Ptr< Ipv4MulticastRoute > mrtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a multicast packet.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:845
uint32_t GetNAddresses(uint32_t interface) const
MapFragmentsTimers_t m_fragmentsTimers
Expiration events.
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:259
uint16_t GetMtu(uint32_t i) const
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Lower layer calls this method after calling L3Demux::Lookup The ARP subclass needs to know from which...
bool ForwardUp(Ptr< const Packet > p, Ipv4Header ipHeader, Ptr< Ipv4Interface > incomingInterface)
Forward up to receive method.
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
uint8_t m_defaultTtl
Default TTL.
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:312
uint32_t GetNInterfaces(void) const
virtual Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
Interface is down so can not send packet.
void SetMetric(uint16_t metric)
RxStatus
Rx status codes.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
tuple address
Definition: first.py:37
uint8_t GetTtl(void) const
Get the tag's TTL.
Definition: socket.cc:589
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:274
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
Trace of unicast forwarded packets.
contain a set of ns3::Object pointers.
uint16_t GetMetric(uint32_t i) const
Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(void) const
Get the routing protocol to be used by this Ipv4 stack.
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:374
indicates whether the socket has IP_TOS set.
Definition: socket.h:1145
Ptr< T > GetObject(void) const
Definition: object.h:362
uint32_t GetNAddresses(void) const
a unique identifier for an interface.
Definition: type-id.h:49
std::map< std::pair< uint64_t, uint8_t >, uint16_t > m_identification
Identification (for each {src, dst, proto} tuple)
void SetDown(uint32_t i)
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void HandleFragmentsTimeout(std::pair< uint64_t, uint32_t > key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
virtual bool GetIpForward(void) const
Get the IP forwarding state.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
static const uint8_t PROT_NUMBER
ICMP protocol number (0x1)
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35
bool IsUp(void) const
These are IP interface states and may be distinct from NetDevice states, such as found in real implem...
void SetUp(void)
Enable this interface.
bool IsForwarding(uint32_t i) const
Ipv4Address SelectSourceAddress(Ptr< const NetDevice > device, Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
Return the first primary source address with scope less than or equal to the requested scope...
void SetRoutingProtocol(Ptr< Ipv4RoutingProtocol > routingProtocol)
Register a new routing protocol to be used by this Ipv4 stack.