A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-l3-protocol.cc
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
52 Ipv4L3Protocol::GetTypeId (void)
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)),
68  MakeTimeAccessor (&Ipv4L3Protocol::m_fragmentExpirationTimeout),
69  MakeTimeChecker ())
70  .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
71  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
72  .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
73  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
74  .AddTraceSource ("Drop", "Drop ipv4 packet",
75  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
76  .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
77  ObjectVectorValue (),
78  MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
79  MakeObjectVectorChecker<Ipv4Interface> ())
80 
81  .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
82  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_sendOutgoingTrace))
83  .AddTraceSource ("UnicastForward", "A unicast IPv4 packet was received by this node and is being forwarded to another node",
84  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_unicastForwardTrace))
85  .AddTraceSource ("LocalDeliver", "An IPv4 packet was received by/for this node, and it is being forward up the stack",
86  MakeTraceSourceAccessor (&Ipv4L3Protocol::m_localDeliverTrace))
87 
88  ;
89  return tid;
90 }
91 
92 Ipv4L3Protocol::Ipv4L3Protocol()
93  : m_identification (0)
94 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
99 Ipv4L3Protocol::~Ipv4L3Protocol ()
100 {
101  NS_LOG_FUNCTION (this);
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION (this << protocol);
108  m_protocols.push_back (protocol);
109 }
111 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
112 {
113  NS_LOG_FUNCTION (this << protocolNumber);
114  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
115  {
116  if ((*i)->GetProtocolNumber () == protocolNumber)
117  {
118  return *i;
119  }
120  }
121  return 0;
122 }
123 void
125 {
126  NS_LOG_FUNCTION (this << protocol);
127  m_protocols.remove (protocol);
128 }
129 
130 void
131 Ipv4L3Protocol::SetNode (Ptr<Node> node)
132 {
133  NS_LOG_FUNCTION (this << node);
134  m_node = node;
135  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
136  SetupLoopback ();
137 }
138 
139 Ptr<Socket>
141 {
142  NS_LOG_FUNCTION (this);
143  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
144  socket->SetNode (m_node);
145  m_sockets.push_back (socket);
146  return socket;
147 }
148 void
150 {
151  NS_LOG_FUNCTION (this << socket);
152  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
153  {
154  if ((*i) == socket)
155  {
156  m_sockets.erase (i);
157  return;
158  }
159  }
160  return;
161 }
162 /*
163  * This method is called by AddAgregate and completes the aggregation
164  * by setting the node in the ipv4 stack
165  */
166 void
168 {
169  NS_LOG_FUNCTION (this);
170  if (m_node == 0)
171  {
172  Ptr<Node>node = this->GetObject<Node>();
173  // verify that it's a valid node and that
174  // the node has not been set before
175  if (node != 0)
176  {
177  this->SetNode (node);
178  }
179  }
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << routingProtocol);
187  m_routingProtocol = routingProtocol;
188  m_routingProtocol->SetIpv4 (this);
189 }
190 
191 
194 {
195  NS_LOG_FUNCTION (this);
196  return m_routingProtocol;
197 }
198 
199 void
201 {
202  NS_LOG_FUNCTION (this);
203  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
204  {
205  *i = 0;
206  }
207  m_protocols.clear ();
208 
209  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
210  {
211  *i = 0;
212  }
213  m_interfaces.clear ();
214  m_sockets.clear ();
215  m_node = 0;
216  m_routingProtocol = 0;
217 
218  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
219  {
220  it->second = 0;
221  }
222 
223  for (MapFragmentsTimers_t::iterator it = m_fragmentsTimers.begin (); it != m_fragmentsTimers.end (); it++)
224  {
225  if (it->second.IsRunning ())
226  {
227  it->second.Cancel ();
228  }
229  }
230 
231  m_fragments.clear ();
232  m_fragmentsTimers.clear ();
233 
235 }
236 
237 void
238 Ipv4L3Protocol::SetupLoopback (void)
239 {
240  NS_LOG_FUNCTION (this);
241 
242  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
243  Ptr<LoopbackNetDevice> device = 0;
244  // First check whether an existing LoopbackNetDevice exists on the node
245  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
246  {
247  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
248  {
249  break;
250  }
251  }
252  if (device == 0)
253  {
254  device = CreateObject<LoopbackNetDevice> ();
255  m_node->AddDevice (device);
256  }
257  interface->SetDevice (device);
258  interface->SetNode (m_node);
259  Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
260  interface->AddAddress (ifaceAddr);
261  uint32_t index = AddIpv4Interface (interface);
262  Ptr<Node> node = GetObject<Node> ();
263  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
264  Ipv4L3Protocol::PROT_NUMBER, device);
265  interface->SetUp ();
266  if (m_routingProtocol != 0)
267  {
268  m_routingProtocol->NotifyInterfaceUp (index);
269  }
270 }
271 
272 void
274 {
275  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
276  m_defaultTtl = ttl;
277 }
278 
279 uint32_t
281 {
282  NS_LOG_FUNCTION (this << device);
283 
284  Ptr<Node> node = GetObject<Node> ();
286  Ipv4L3Protocol::PROT_NUMBER, device);
287  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
288  ArpL3Protocol::PROT_NUMBER, device);
289 
290  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
291  interface->SetNode (m_node);
292  interface->SetDevice (device);
293  interface->SetForwarding (m_ipForward);
294  return AddIpv4Interface (interface);
295 }
296 
297 uint32_t
298 Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
299 {
300  NS_LOG_FUNCTION (this << interface);
301  uint32_t index = m_interfaces.size ();
302  m_interfaces.push_back (interface);
303  return index;
304 }
305 
306 Ptr<Ipv4Interface>
307 Ipv4L3Protocol::GetInterface (uint32_t index) const
308 {
309  NS_LOG_FUNCTION (this << index);
310  if (index < m_interfaces.size ())
311  {
312  return m_interfaces[index];
313  }
314  return 0;
315 }
316 
317 uint32_t
319 {
320  NS_LOG_FUNCTION (this);
321  return m_interfaces.size ();
322 }
323 
324 int32_t
326  Ipv4Address address) const
327 {
328  NS_LOG_FUNCTION (this << address);
329  int32_t interface = 0;
330  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
331  i != m_interfaces.end ();
332  i++, interface++)
333  {
334  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
335  {
336  if ((*i)->GetAddress (j).GetLocal () == address)
337  {
338  return interface;
339  }
340  }
341  }
342 
343  return -1;
344 }
345 
346 int32_t
348  Ipv4Address address,
349  Ipv4Mask mask) const
350 {
351  NS_LOG_FUNCTION (this << address << mask);
352  int32_t interface = 0;
353  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
354  i != m_interfaces.end ();
355  i++, interface++)
356  {
357  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
358  {
359  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
360  {
361  return interface;
362  }
363  }
364  }
365 
366  return -1;
367 }
368 
369 int32_t
371  Ptr<const NetDevice> device) const
372 {
373  NS_LOG_FUNCTION (this << device);
374  int32_t interface = 0;
375  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
376  i != m_interfaces.end ();
377  i++, interface++)
378  {
379  if ((*i)->GetDevice () == device)
380  {
381  return interface;
382  }
383  }
384 
385  return -1;
386 }
387 
388 bool
390 {
391  NS_LOG_FUNCTION (this << address << iif);
392  // First check the incoming interface for a unicast address match
393  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
394  {
395  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
396  if (address == iaddr.GetLocal ())
397  {
398  NS_LOG_LOGIC ("For me (destination " << address << " match)");
399  return true;
400  }
401  if (address == iaddr.GetBroadcast ())
402  {
403  NS_LOG_LOGIC ("For me (interface broadcast address)");
404  return true;
405  }
406  }
407 
408  if (address.IsMulticast ())
409  {
410 #ifdef NOTYET
411  if (MulticastCheckGroup (iif, address ))
412 #endif
413  if (true)
414  {
415  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
416  return true;
417  }
418  }
419 
420  if (address.IsBroadcast ())
421  {
422  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
423  return true;
424  }
425 
426  if (GetWeakEsModel ()) // Check other interfaces
427  {
428  for (uint32_t j = 0; j < GetNInterfaces (); j++)
429  {
430  if (j == uint32_t (iif)) continue;
431  for (uint32_t i = 0; i < GetNAddresses (j); i++)
432  {
433  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
434  if (address == iaddr.GetLocal ())
435  {
436  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
437  return true;
438  }
439  // This is a small corner case: match another interface's broadcast address
440  if (address == iaddr.GetBroadcast ())
441  {
442  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
443  return true;
444  }
445  }
446  }
447  }
448  return false;
449 }
450 
451 void
452 Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
453  const Address &to, NetDevice::PacketType packetType)
454 {
455  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
456 
457  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
458  m_node->GetId () << " on device: " << device->GetAddress());
459 
460  uint32_t interface = 0;
461  Ptr<Packet> packet = p->Copy ();
462 
463  Ptr<Ipv4Interface> ipv4Interface;
464  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
465  i != m_interfaces.end ();
466  i++, interface++)
467  {
468  ipv4Interface = *i;
469  if (ipv4Interface->GetDevice () == device)
470  {
471  if (ipv4Interface->IsUp ())
472  {
473  m_rxTrace (packet, m_node->GetObject<Ipv4> (), interface);
474  break;
475  }
476  else
477  {
478  NS_LOG_LOGIC ("Dropping received packet -- interface is down");
479  Ipv4Header ipHeader;
480  packet->RemoveHeader (ipHeader);
481  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
482  return;
483  }
484  }
485  }
486 
487  Ipv4Header ipHeader;
488  if (Node::ChecksumEnabled ())
489  {
490  ipHeader.EnableChecksum ();
491  }
492  packet->RemoveHeader (ipHeader);
493 
494  // Trim any residual frame padding from underlying devices
495  if (ipHeader.GetPayloadSize () < packet->GetSize ())
496  {
497  packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
498  }
499 
500  if (!ipHeader.IsChecksumOk ())
501  {
502  NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
503  m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject<Ipv4> (), interface);
504  return;
505  }
506 
507  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
508  {
509  NS_LOG_LOGIC ("Forwarding to raw socket");
510  Ptr<Ipv4RawSocketImpl> socket = *i;
511  socket->ForwardUp (packet, ipHeader, ipv4Interface);
512  }
513 
514  NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
515  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
516  MakeCallback (&Ipv4L3Protocol::IpForward, this),
517  MakeCallback (&Ipv4L3Protocol::IpMulticastForward, this),
518  MakeCallback (&Ipv4L3Protocol::LocalDeliver, this),
519  MakeCallback (&Ipv4L3Protocol::RouteInputError, this)
520  ))
521  {
522  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
523  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), interface);
524  }
525 }
526 
529 {
530  NS_LOG_FUNCTION (this);
531  Ptr<IpL4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
532  if (prot != 0)
533  {
534  return prot->GetObject<Icmpv4L4Protocol> ();
535  }
536  else
537  {
538  return 0;
539  }
540 }
541 
542 bool
543 Ipv4L3Protocol::IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const
544 {
545  NS_LOG_FUNCTION (this << ad << interfaceMask);
546  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
547 }
548 
549 void
551  Ipv4Header ipHeader,
552  Ptr<Ipv4Route> route)
553 {
554  NS_LOG_FUNCTION (this << packet << ipHeader << route);
555  if (Node::ChecksumEnabled ())
556  {
557  ipHeader.EnableChecksum ();
558  }
559  SendRealOut (route, packet, ipHeader);
560 }
561 
562 void
564  Ipv4Address source,
565  Ipv4Address destination,
566  uint8_t protocol,
567  Ptr<Ipv4Route> route)
568 {
569  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
570 
571  Ipv4Header ipHeader;
572  bool mayFragment = true;
573  uint8_t ttl = m_defaultTtl;
574  SocketIpTtlTag tag;
575  bool found = packet->RemovePacketTag (tag);
576  if (found)
577  {
578  ttl = tag.GetTtl ();
579  }
580 
581  uint8_t tos = m_defaultTos;
582  SocketIpTosTag ipTosTag;
583  found = packet->RemovePacketTag (ipTosTag);
584  if (found)
585  {
586  tos = ipTosTag.GetTos ();
587  }
588 
589  // Handle a few cases:
590  // 1) packet is destined to limited broadcast address
591  // 2) packet is destined to a subnet-directed broadcast address
592  // 3) packet is not broadcast, and is passed in with a route entry
593  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
594  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
595 
596  // 1) packet is destined to limited broadcast address or link-local multicast address
597  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
598  {
599  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
600  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
601  uint32_t ifaceIndex = 0;
602  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
603  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
604  {
605  Ptr<Ipv4Interface> outInterface = *ifaceIter;
606  Ptr<Packet> packetCopy = packet->Copy ();
607 
608  NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ());
609 
610  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
611  packetCopy->AddHeader (ipHeader);
612  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
613  outInterface->Send (packetCopy, destination);
614  }
615  return;
616  }
617 
618  // 2) check: packet is destined to a subnet-directed broadcast address
619  uint32_t ifaceIndex = 0;
620  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
621  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
622  {
623  Ptr<Ipv4Interface> outInterface = *ifaceIter;
624  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
625  {
626  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
627  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
628  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
629  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
630  {
631  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
632  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
633  Ptr<Packet> packetCopy = packet->Copy ();
634  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
635  packetCopy->AddHeader (ipHeader);
636  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
637  outInterface->Send (packetCopy, destination);
638  return;
639  }
640  }
641  }
642 
643  // 3) packet is not broadcast, and is passed in with a route entry
644  // with a valid Ipv4Address as the gateway
645  if (route && route->GetGateway () != Ipv4Address ())
646  {
647  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
648  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
649  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
650  m_sendOutgoingTrace (ipHeader, packet, interface);
652  if (packet->PeekPacketTag(cbt))
653  NS_LOG_LOGIC ("Node[" << m_node->GetId() << "] is sending to channel: " << cbt.GetChannel() << " on RX");
654  SendRealOut (route, packet->Copy (), ipHeader);
655  return;
656  }
657  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
658  if (route && route->GetGateway () == Ipv4Address ())
659  {
660  // This could arise because the synchronous RouteOutput() call
661  // returned to the transport protocol with a source address but
662  // there was no next hop available yet (since a route may need
663  // to be queried).
664  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 4: This case not yet implemented");
665  }
666  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
667  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 5: passed in with no route " << destination);
668  Socket::SocketErrno errno_;
669  Ptr<NetDevice> oif (0); // unused for now
670  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
671  Ptr<Ipv4Route> newRoute;
672  if (m_routingProtocol != 0)
673  {
674  newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
675  }
676  else
677  {
678  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
679  }
680  if (newRoute)
681  {
682  int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
683  m_sendOutgoingTrace (ipHeader, packet, interface);
684  SendRealOut (newRoute, packet->Copy (), ipHeader);
685  }
686  else
687  {
688  NS_LOG_WARN ("No route to host. Drop.");
689  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
690  }
691 }
692 
693 // XXX when should we set ip_id? check whether we are incrementing
694 // m_identification on packets that may later be dropped in this stack
695 // and whether that deviates from Linux
697 Ipv4L3Protocol::BuildHeader (
698  Ipv4Address source,
699  Ipv4Address destination,
700  uint8_t protocol,
701  uint16_t payloadSize,
702  uint8_t ttl,
703  uint8_t tos,
704  bool mayFragment)
705 {
706  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
707  Ipv4Header ipHeader;
708  ipHeader.SetSource (source);
709  ipHeader.SetDestination (destination);
710  ipHeader.SetProtocol (protocol);
711  ipHeader.SetPayloadSize (payloadSize);
712  ipHeader.SetTtl (ttl);
713  ipHeader.SetTos (tos);
714  if (mayFragment == true)
715  {
716  ipHeader.SetMayFragment ();
717  ipHeader.SetIdentification (m_identification);
718  m_identification++;
719  }
720  else
721  {
722  ipHeader.SetDontFragment ();
723  // TBD: set to zero here; will cause traces to change
724  ipHeader.SetIdentification (m_identification);
725  m_identification++;
726  }
727  if (Node::ChecksumEnabled ())
728  {
729  ipHeader.EnableChecksum ();
730  }
731  return ipHeader;
732 }
733 
734 void
735 Ipv4L3Protocol::SendRealOut (Ptr<Ipv4Route> route,
736  Ptr<Packet> packet,
737  Ipv4Header const &ipHeader)
738 {
739  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
740  if (route == 0)
741  {
742  NS_LOG_WARN ("No route to host. Drop.");
743  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
744  return;
745  }
746  packet->AddHeader (ipHeader);
747  Ptr<NetDevice> outDev = route->GetOutputDevice ();
748  int32_t interface = GetInterfaceForDevice (outDev);
749  NS_ASSERT (interface >= 0);
750  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
751  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
752 
753  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
754  {
755  if (outInterface->IsUp ())
756  {
757  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
758  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
759  {
760  std::list<Ptr<Packet> > listFragments;
761  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
762  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
763  {
764  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
765  outInterface->Send (*it, route->GetGateway ());
766  }
767  }
768  else
769  {
770  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
771  outInterface->Send (packet, route->GetGateway ());
772  }
773  }
774  else
775  {
776  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
777  Ipv4Header ipHeader;
778  packet->RemoveHeader (ipHeader);
779  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
780  }
781  }
782  else
783  {
784  if (outInterface->IsUp ())
785  {
786  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
787  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
788  {
789  std::list<Ptr<Packet> > listFragments;
790  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
791  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
792  {
793  NS_LOG_LOGIC ("Sending fragment " << **it );
794  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
795  outInterface->Send (*it, ipHeader.GetDestination ());
796  }
797  }
798  else
799  {
800  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
801  outInterface->Send (packet, ipHeader.GetDestination ());
802  }
803  }
804  else
805  {
806  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
807  Ipv4Header ipHeader;
808  packet->RemoveHeader (ipHeader);
809  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
810  }
811  }
812 }
813 
814 // This function analogous to Linux ip_mr_forward()
815 void
816 Ipv4L3Protocol::IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv4Header &header)
817 {
818  NS_LOG_FUNCTION (this << mrtentry << p << header);
819  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
820 
821  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
822  std::map<uint32_t, uint32_t>::iterator mapIter;
823 
824  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
825  {
826  uint32_t interfaceId = mapIter->first;
827  //uint32_t outputTtl = mapIter->second; // Unused for now
828 
829  Ptr<Packet> packet = p->Copy ();
830  Ipv4Header h = header;
831  h.SetTtl (header.GetTtl () - 1);
832  if (h.GetTtl () == 0)
833  {
834  NS_LOG_WARN ("TTL exceeded. Drop.");
835  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interfaceId);
836  return;
837  }
838  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
839  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
840  rtentry->SetSource (h.GetSource ());
841  rtentry->SetDestination (h.GetDestination ());
842  rtentry->SetGateway (Ipv4Address::GetAny ());
843  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
844  SendRealOut (rtentry, packet, h);
845  continue;
846  }
847 }
848 
849 // This function analogous to Linux ip_forward()
850 void
851 Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ipv4Header &header)
852 {
853  NS_LOG_FUNCTION (this << rtentry << p << header);
854  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
855  // Forwarding
856  Ipv4Header ipHeader = header;
857  Ptr<Packet> packet = p->Copy ();
858  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
859  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
860  if (ipHeader.GetTtl () == 0)
861  {
862  // Do not reply to ICMP or to multicast/broadcast IP address
863  if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
864  ipHeader.GetDestination ().IsBroadcast () == false &&
865  ipHeader.GetDestination ().IsMulticast () == false)
866  {
867  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
868  icmp->SendTimeExceededTtl (ipHeader, packet);
869  }
870  NS_LOG_WARN ("TTL exceeded. Drop.");
871  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
872  return;
873  }
874  m_unicastForwardTrace (ipHeader, packet, interface);
875  SendRealOut (rtentry, packet, ipHeader);
876 }
877 
878 void
879 Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
880 {
881  NS_LOG_FUNCTION (this << packet << &ip << iif);
882  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
883  Ipv4Header ipHeader = ip;
884 
885  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
886  {
887  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
888  bool isPacketComplete;
889  isPacketComplete = ProcessFragment (p, ipHeader, iif);
890  if ( isPacketComplete == false)
891  {
892  return;
893  }
894  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
895  }
896 
897  m_localDeliverTrace (ip, packet, iif);
898 
899  Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ());
900  if (protocol != 0)
901  {
902  // we need to make a copy in the unlikely event we hit the
903  // RX_ENDPOINT_UNREACH codepath
904  Ptr<Packet> copy = p->Copy ();
905  enum IpL4Protocol::RxStatus status =
906  protocol->Receive (p, ip, GetInterface (iif));
907  switch (status) {
908  case IpL4Protocol::RX_OK:
909  // fall through
910  case IpL4Protocol::RX_ENDPOINT_CLOSED:
911  // fall through
912  case IpL4Protocol::RX_CSUM_FAILED:
913  break;
914  case IpL4Protocol::RX_ENDPOINT_UNREACH:
915  if (ip.GetDestination ().IsBroadcast () == true ||
916  ip.GetDestination ().IsMulticast () == true)
917  {
918  break; // Do not reply to broadcast or multicast
919  }
920  // Another case to suppress ICMP is a subnet-directed broadcast
921  bool subnetDirected = false;
922  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
923  {
924  Ipv4InterfaceAddress addr = GetAddress (iif, i);
925  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination ().CombineMask (addr.GetMask ()) &&
926  ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
927  {
928  subnetDirected = true;
929  }
930  }
931  if (subnetDirected == false)
932  {
933  GetIcmp ()->SendDestUnreachPort (ip, copy);
934  }
935  }
936  }
937 }
938 
939 bool
941 {
942  NS_LOG_FUNCTION (this << i << address);
943  Ptr<Ipv4Interface> interface = GetInterface (i);
944  bool retVal = interface->AddAddress (address);
945  if (m_routingProtocol != 0)
946  {
947  m_routingProtocol->NotifyAddAddress (i, address);
948  }
949  return retVal;
950 }
951 
953 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
954 {
955  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
956  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
957  return interface->GetAddress (addressIndex);
958 }
959 
960 uint32_t
961 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
962 {
963  NS_LOG_FUNCTION (this << interface);
964  Ptr<Ipv4Interface> iface = GetInterface (interface);
965  return iface->GetNAddresses ();
966 }
967 
968 bool
969 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
970 {
971  NS_LOG_FUNCTION (this << i << addressIndex);
972  Ptr<Ipv4Interface> interface = GetInterface (i);
973  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
974  if (address != Ipv4InterfaceAddress ())
975  {
976  if (m_routingProtocol != 0)
977  {
978  m_routingProtocol->NotifyRemoveAddress (i, address);
979  }
980  return true;
981  }
982  return false;
983 }
984 
987  Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
988 {
989  NS_LOG_FUNCTION (this << device << dst << scope);
990  Ipv4Address addr ("0.0.0.0");
991  Ipv4InterfaceAddress iaddr;
992  bool found = false;
993 
994  if (device != 0)
995  {
996  int32_t i = GetInterfaceForDevice (device);
997  NS_ASSERT_MSG (i >= 0, "No device found on node");
998  for (uint32_t j = 0; j < GetNAddresses (i); j++)
999  {
1000  iaddr = GetAddress (i, j);
1001  if (iaddr.IsSecondary ()) continue;
1002  if (iaddr.GetScope () > scope) continue;
1003  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1004  {
1005  return iaddr.GetLocal ();
1006  }
1007  if (!found)
1008  {
1009  addr = iaddr.GetLocal ();
1010  found = true;
1011  }
1012  }
1013  }
1014  if (found)
1015  {
1016  return addr;
1017  }
1018 
1019  // Iterate among all interfaces
1020  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1021  {
1022  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1023  {
1024  iaddr = GetAddress (i, j);
1025  if (iaddr.IsSecondary ()) continue;
1026  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1027  && iaddr.GetScope () <= scope)
1028  {
1029  return iaddr.GetLocal ();
1030  }
1031  }
1032  }
1033  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1034  << scope << ", returning 0");
1035  return addr;
1036 }
1037 
1038 void
1039 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1040 {
1041  NS_LOG_FUNCTION (this << i << metric);
1042  Ptr<Ipv4Interface> interface = GetInterface (i);
1043  interface->SetMetric (metric);
1044 }
1045 
1046 uint16_t
1047 Ipv4L3Protocol::GetMetric (uint32_t i) const
1048 {
1049  NS_LOG_FUNCTION (this << i);
1050  Ptr<Ipv4Interface> interface = GetInterface (i);
1051  return interface->GetMetric ();
1052 }
1053 
1054 uint16_t
1055 Ipv4L3Protocol::GetMtu (uint32_t i) const
1056 {
1057  NS_LOG_FUNCTION (this << i);
1058  Ptr<Ipv4Interface> interface = GetInterface (i);
1059  return interface->GetDevice ()->GetMtu ();
1060 }
1061 
1062 bool
1063 Ipv4L3Protocol::IsUp (uint32_t i) const
1064 {
1065  NS_LOG_FUNCTION (this << i);
1066  Ptr<Ipv4Interface> interface = GetInterface (i);
1067  return interface->IsUp ();
1068 }
1069 
1070 void
1072 {
1073  NS_LOG_FUNCTION (this << i);
1074  Ptr<Ipv4Interface> interface = GetInterface (i);
1075  interface->SetUp ();
1076 
1077  if (m_routingProtocol != 0)
1078  {
1079  m_routingProtocol->NotifyInterfaceUp (i);
1080  }
1081 }
1082 
1083 void
1084 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1085 {
1086  NS_LOG_FUNCTION (this << ifaceIndex);
1087  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1088  interface->SetDown ();
1089 
1090  if (m_routingProtocol != 0)
1091  {
1092  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1093  }
1094 }
1095 
1096 bool
1098 {
1099  NS_LOG_FUNCTION (this << i);
1100  Ptr<Ipv4Interface> interface = GetInterface (i);
1101  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1102  return interface->IsForwarding ();
1103 }
1104 
1105 void
1106 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1107 {
1108  NS_LOG_FUNCTION (this << i);
1109  Ptr<Ipv4Interface> interface = GetInterface (i);
1110  interface->SetForwarding (val);
1111 }
1112 
1115 {
1116  NS_LOG_FUNCTION (this << i);
1117  return GetInterface (i)->GetDevice ();
1118 }
1119 
1120 void
1121 Ipv4L3Protocol::SetIpForward (bool forward)
1122 {
1123  NS_LOG_FUNCTION (this << forward);
1124  m_ipForward = forward;
1125  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1126  {
1127  (*i)->SetForwarding (forward);
1128  }
1129 }
1130 
1131 bool
1132 Ipv4L3Protocol::GetIpForward (void) const
1133 {
1134  NS_LOG_FUNCTION (this);
1135  return m_ipForward;
1136 }
1137 
1138 void
1139 Ipv4L3Protocol::SetWeakEsModel (bool model)
1140 {
1141  NS_LOG_FUNCTION (this << model);
1142  m_weakEsModel = model;
1143 }
1144 
1145 bool
1146 Ipv4L3Protocol::GetWeakEsModel (void) const
1147 {
1148  NS_LOG_FUNCTION (this);
1149  return m_weakEsModel;
1150 }
1151 
1152 void
1153 Ipv4L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv4Header & ipHeader, Socket::SocketErrno sockErrno)
1154 {
1155  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1156  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1157  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1158 }
1159 
1160 void
1161 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::list<Ptr<Packet> >& listFragments)
1162 {
1163  // BEWARE: here we do assume that the header options are not present.
1164  // a much more complex handling is necessary in case there are options.
1165  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1166  // Of course also the reassemby code shall be changed as well.
1167 
1168  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1169 
1170  Ptr<Packet> p = packet->Copy ();
1171 
1172  Ipv4Header ipv4Header;
1173  p->RemoveHeader (ipv4Header);
1174 
1175  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1176  "IPv4 fragmentation implementation only works without option headers." );
1177 
1178  uint16_t offset = 0;
1179  bool moreFragment = true;
1180  uint16_t originalOffset = 0;
1181  bool alreadyFragmented = false;
1182  uint32_t currentFragmentablePartSize = 0;
1183 
1184  if (!ipv4Header.IsLastFragment())
1185  {
1186  alreadyFragmented = true;
1187  originalOffset = ipv4Header.GetFragmentOffset();
1188  }
1189 
1190  // IPv4 fragments are all 8 bytes aligned but the last.
1191  // The IP payload size is:
1192  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1193  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1194 
1195  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1196 
1197  do
1198  {
1199  Ipv4Header fragmentHeader = ipv4Header;
1200 
1201  if (p->GetSize () > offset + fragmentSize )
1202  {
1203  moreFragment = true;
1204  currentFragmentablePartSize = fragmentSize;
1205  fragmentHeader.SetMoreFragments ();
1206  }
1207  else
1208  {
1209  moreFragment = false;
1210  currentFragmentablePartSize = p->GetSize () - offset;
1211  if (alreadyFragmented)
1212  {
1213  fragmentHeader.SetMoreFragments ();
1214  }
1215  else
1216  {
1217  fragmentHeader.SetLastFragment ();
1218  }
1219  }
1220 
1221  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1222  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1223  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1224 
1225  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1226  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1227 
1228  if (Node::ChecksumEnabled ())
1229  {
1230  fragmentHeader.EnableChecksum ();
1231  }
1232 
1233  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1234 
1235  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1236  fragment->AddHeader (fragmentHeader);
1237 
1238  std::ostringstream oss;
1239  fragment->Print (oss);
1240 
1241  NS_LOG_LOGIC ("New fragment " << *fragment);
1242 
1243  listFragments.push_back (fragment);
1244 
1245  offset += currentFragmentablePartSize;
1246 
1247  }
1248  while (moreFragment);
1249 
1250  return;
1251 }
1252 
1253 bool
1254 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1255 {
1256  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1257 
1258  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 & uint64_t (ipHeader.GetDestination ().Get ());
1259  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 & uint32_t (ipHeader.GetProtocol ());
1260  std::pair<uint64_t, uint32_t> key;
1261  bool ret = false;
1262  Ptr<Packet> p = packet->Copy ();
1263 
1264  key.first = addressCombination;
1265  key.second = idProto;
1266 
1267  Ptr<Fragments> fragments;
1268 
1269  MapFragments_t::iterator it = m_fragments.find (key);
1270  if (it == m_fragments.end ())
1271  {
1272  fragments = Create<Fragments> ();
1273  m_fragments.insert (std::make_pair (key, fragments));
1274  m_fragmentsTimers[key] = Simulator::Schedule (m_fragmentExpirationTimeout,
1276  key, ipHeader, iif);
1277  }
1278  else
1279  {
1280  fragments = it->second;
1281  }
1282 
1283  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1284 
1285  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1286 
1287  if ( fragments->IsEntire () )
1288  {
1289  packet = fragments->GetPacket ();
1290  fragments = 0;
1291  m_fragments.erase (key);
1292  if (m_fragmentsTimers[key].IsRunning ())
1293  {
1294  NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1295  m_fragmentsTimers[key].Cancel ();
1296  }
1297  m_fragmentsTimers.erase (key);
1298  ret = true;
1299  }
1300 
1301  return ret;
1302 }
1303 
1305  : m_moreFragment (0)
1306 {
1307  NS_LOG_FUNCTION (this);
1308 }
1309 
1311 {
1312  NS_LOG_FUNCTION (this);
1313 }
1314 
1315 void
1316 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1317 {
1318  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1319 
1320  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1321 
1322  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1323  {
1324  if (it->second > fragmentOffset)
1325  {
1326  break;
1327  }
1328  }
1329 
1330  if (it == m_fragments.end ())
1331  {
1332  m_moreFragment = moreFragment;
1333  }
1334 
1335  m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1336 }
1337 
1338 bool
1340 {
1341  NS_LOG_FUNCTION (this);
1342 
1343  bool ret = !m_moreFragment && m_fragments.size () > 0;
1344 
1345  if (ret)
1346  {
1347  uint16_t lastEndOffset = 0;
1348 
1349  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1350  {
1351  // overlapping fragments do exist
1352  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1353 
1354  if (lastEndOffset < it->second)
1355  {
1356  ret = false;
1357  break;
1358  }
1359  // fragments might overlap in strange ways
1360  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1361  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1362  }
1363  }
1364 
1365  return ret;
1366 }
1367 
1370 {
1371  NS_LOG_FUNCTION (this);
1372 
1373  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1374 
1375  Ptr<Packet> p = Create<Packet> ();
1376  uint16_t lastEndOffset = 0;
1377 
1378  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1379  {
1380  if ( lastEndOffset > it->second )
1381  {
1382  // The fragments are overlapping.
1383  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1384  // This is different from what Linux does.
1385  // It is not possible to emulate a fragmentation attack.
1386  uint32_t newStart = lastEndOffset - it->second;
1387  if ( it->first->GetSize () > newStart )
1388  {
1389  uint32_t newSize = it->first->GetSize () - newStart;
1390  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1391  p->AddAtEnd (tempFragment);
1392  }
1393  }
1394  else
1395  {
1396  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1397  p->AddAtEnd (it->first);
1398  }
1399  lastEndOffset = p->GetSize ();
1400  }
1401 
1402  return p;
1403 }
1404 
1407 {
1408  NS_LOG_FUNCTION (this);
1409 
1410  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1411 
1412  Ptr<Packet> p = Create<Packet> ();
1413  uint16_t lastEndOffset = 0;
1414 
1415  if ( m_fragments.begin ()->second > 0 )
1416  {
1417  return p;
1418  }
1419 
1420  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1421  {
1422  if ( lastEndOffset > it->second )
1423  {
1424  uint32_t newStart = lastEndOffset - it->second;
1425  uint32_t newSize = it->first->GetSize () - newStart;
1426  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1427  p->AddAtEnd (tempFragment);
1428  }
1429  else if ( lastEndOffset == it->second )
1430  {
1431  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1432  p->AddAtEnd (it->first);
1433  }
1434  lastEndOffset = p->GetSize ();
1435  }
1436 
1437  return p;
1438 }
1439 
1440 void
1441 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
1442 {
1443  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1444 
1445  MapFragments_t::iterator it = m_fragments.find (key);
1446  Ptr<Packet> packet = it->second->GetPartialPacket ();
1447 
1448  // if we have at least 8 bytes, we can send an ICMP.
1449  if ( packet->GetSize () > 8 )
1450  {
1451  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1452  icmp->SendTimeExceededTtl (ipHeader, packet);
1453  }
1454  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1455 
1456  // clear the buffers
1457  it->second = 0;
1458 
1459  m_fragments.erase (key);
1460  m_fragmentsTimers.erase (key);
1461 }
1462 
1463 } // namespace ns3
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:284
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
void SetForwarding(bool val)
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
void SetDefaultTtl(uint8_t ttl)
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:297
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void NotifyNewAggregate()
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:210
void Send(Ptr< Packet > p, Ipv4Address dest)
static bool ChecksumEnabled(void)
Definition: node.cc:267
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
bool IsLocalMulticast(void) const
The IPv4 representation of a network interface.
#define NS_ASSERT(condition)
Definition: assert.h:64
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:271
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint32_t GetSize(void) const
Definition: packet.h:620
bool IsMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
void SetFragmentOffset(uint16_t offsetBytes)
Definition: ipv4-header.cc:238
Ipv4InterfaceAddress RemoveAddress(uint32_t index)
virtual void DoDispose(void)
Definition: object.cc:335
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
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:277
uint32_t AddInterface(Ptr< NetDevice > device)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:869
void SetDontFragment(void)
Definition: ipv4-header.cc:219
void Print(std::ostream &os) const
Definition: packet.cc:450
void SetUp(uint32_t i)
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
a polymophic address class
Definition: address.h:86
Ipv4InterfaceAddress GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
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.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:243
Packet header for IPv4.
Definition: ipv4-header.h:31
void AddAtEnd(Ptr< const Packet > packet)
Definition: packet.cc:334
void SetLastFragment(void)
Definition: ipv4-header.cc:206
bool PeekPacketTag(Tag &tag) const
Definition: packet.cc:881
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
uint32_t Get(void) const
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)
bool IsBroadcast(void) const
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:133
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
virtual enum RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > incomingInterface)=0
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)
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void SetMayFragment(void)
Definition: ipv4-header.cc:225
bool IsUp(uint32_t i) const
MapFragments_t m_fragments
The hash of fragmented packets.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
Ipv4Address GetGateway(void) const
Definition: ipv4-route.cc:70
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
virtual void NotifyNewAggregate(void)
Definition: object.cc:314
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
uint32_t GetNDevices(void) const
Definition: node.cc:141
void SetForwarding(uint32_t i, bool val)
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address...
void SetMoreFragments(void)
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
static Time Now(void)
Definition: simulator.cc:179
static Ipv4Address GetLoopback(void)
static Ipv4Mask GetLoopback(void)
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:218
Ptr< NetDevice > GetNetDevice(uint32_t i)
uint16_t GetMetric(void) const
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
bool ProcessFragment(Ptr< Packet > &packet, Ipv4Header &ipHeader, uint32_t iif)
Process a packet fragment.
void Remove(Ptr< IpL4Protocol > protocol)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
uint32_t AddDevice(Ptr< NetDevice > device)
Definition: node.cc:119
uint32_t GetId(void) const
Definition: node.cc:105
a class to store IPv4 address information on an interface
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
void DeleteRawSocket(Ptr< Socket > socket)
Deletes a particular raw socket.
bool AddAddress(uint32_t i, Ipv4InterfaceAddress address)
#define NS_LOG_WARN(msg)
Definition: log.h:246
Ptr< NetDevice > GetDevice(void) const
void Insert(Ptr< IpL4Protocol > protocol)
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
uint32_t GetNAddresses(uint32_t interface) const
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:258
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)
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:311
uint32_t GetNInterfaces(void) const
Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
void SetMetric(uint16_t metric)
#define NS_LOG_ERROR(msg)
Definition: log.h:237
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:373
Ptr< T > GetObject(void) const
Definition: object.h:332
uint32_t GetNAddresses(void) const
void SetDown(uint32_t i)
bool IsForwarding(void) const
void HandleFragmentsTimeout(std::pair< uint64_t, uint32_t > key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
void AddHeader(const Header &header)
Definition: packet.cc:270
bool IsUp(void) const
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.