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  if (mayFragment == true)
739  {
740  ipHeader.SetMayFragment ();
741  ipHeader.SetIdentification (m_identification[protocol]);
742  m_identification[protocol]++;
743  }
744  else
745  {
746  ipHeader.SetDontFragment ();
747  // RFC 6864 does not state anything about atomic datagrams
748  // identification requirement:
749  // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
750  // to any value.
751  ipHeader.SetIdentification (m_identification[protocol]);
752  m_identification[protocol]++;
753  }
754  if (Node::ChecksumEnabled ())
755  {
756  ipHeader.EnableChecksum ();
757  }
758  return ipHeader;
759 }
760 
761 void
763  Ptr<Packet> packet,
764  Ipv4Header const &ipHeader)
765 {
766  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
767  if (route == 0)
768  {
769  NS_LOG_WARN ("No route to host. Drop.");
770  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
771  return;
772  }
773  packet->AddHeader (ipHeader);
774  Ptr<NetDevice> outDev = route->GetOutputDevice ();
775  int32_t interface = GetInterfaceForDevice (outDev);
776  NS_ASSERT (interface >= 0);
777  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
778  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
779 
780  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
781  {
782  if (outInterface->IsUp ())
783  {
784  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
785  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
786  {
787  std::list<Ptr<Packet> > listFragments;
788  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
789  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
790  {
791  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
792  outInterface->Send (*it, route->GetGateway ());
793  }
794  }
795  else
796  {
797  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
798  outInterface->Send (packet, route->GetGateway ());
799  }
800  }
801  else
802  {
803  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
804  Ipv4Header ipHeader;
805  packet->RemoveHeader (ipHeader);
806  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
807  }
808  }
809  else
810  {
811  if (outInterface->IsUp ())
812  {
813  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
814  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
815  {
816  std::list<Ptr<Packet> > listFragments;
817  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
818  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
819  {
820  NS_LOG_LOGIC ("Sending fragment " << **it );
821  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
822  outInterface->Send (*it, ipHeader.GetDestination ());
823  }
824  }
825  else
826  {
827  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
828  outInterface->Send (packet, ipHeader.GetDestination ());
829  }
830  }
831  else
832  {
833  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
834  Ipv4Header ipHeader;
835  packet->RemoveHeader (ipHeader);
836  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
837  }
838  }
839 }
840 
841 // This function analogous to Linux ip_mr_forward()
842 void
844 {
845  NS_LOG_FUNCTION (this << mrtentry << p << header);
846  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
847 
848  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
849  std::map<uint32_t, uint32_t>::iterator mapIter;
850 
851  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
852  {
853  uint32_t interfaceId = mapIter->first;
854  //uint32_t outputTtl = mapIter->second; // Unused for now
855 
856  Ptr<Packet> packet = p->Copy ();
857  Ipv4Header h = header;
858  h.SetTtl (header.GetTtl () - 1);
859  if (h.GetTtl () == 0)
860  {
861  NS_LOG_WARN ("TTL exceeded. Drop.");
862  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interfaceId);
863  return;
864  }
865  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
866  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
867  rtentry->SetSource (h.GetSource ());
868  rtentry->SetDestination (h.GetDestination ());
869  rtentry->SetGateway (Ipv4Address::GetAny ());
870  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
871  SendRealOut (rtentry, packet, h);
872  continue;
873  }
874 }
875 
876 // This function analogous to Linux ip_forward()
877 void
879 {
880  NS_LOG_FUNCTION (this << rtentry << p << header);
881  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
882  // Forwarding
883  Ipv4Header ipHeader = header;
884  Ptr<Packet> packet = p->Copy ();
885  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
886  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
887  if (ipHeader.GetTtl () == 0)
888  {
889  // Do not reply to ICMP or to multicast/broadcast IP address
890  if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
891  ipHeader.GetDestination ().IsBroadcast () == false &&
892  ipHeader.GetDestination ().IsMulticast () == false)
893  {
894  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
895  icmp->SendTimeExceededTtl (ipHeader, packet);
896  }
897  NS_LOG_WARN ("TTL exceeded. Drop.");
898  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
899  return;
900  }
901  m_unicastForwardTrace (ipHeader, packet, interface);
902  SendRealOut (rtentry, packet, ipHeader);
903 }
904 
905 void
907 {
908  NS_LOG_FUNCTION (this << packet << &ip << iif);
909  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
910  Ipv4Header ipHeader = ip;
911 
912  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
913  {
914  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
915  bool isPacketComplete;
916  isPacketComplete = ProcessFragment (p, ipHeader, iif);
917  if ( isPacketComplete == false)
918  {
919  return;
920  }
921  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
922  ipHeader.SetFragmentOffset (0);
923  ipHeader.SetPayloadSize (p->GetSize () + ipHeader.GetSerializedSize ());
924  }
925 
926  m_localDeliverTrace (ipHeader, p, iif);
927 
928  Ptr<IpL4Protocol> protocol = GetProtocol (ipHeader.GetProtocol ());
929  if (protocol != 0)
930  {
931  // we need to make a copy in the unlikely event we hit the
932  // RX_ENDPOINT_UNREACH codepath
933  Ptr<Packet> copy = p->Copy ();
934  enum IpL4Protocol::RxStatus status =
935  protocol->Receive (p, ipHeader, GetInterface (iif));
936  switch (status) {
937  case IpL4Protocol::RX_OK:
938  // fall through
940  // fall through
942  break;
944  if (ipHeader.GetDestination ().IsBroadcast () == true ||
945  ipHeader.GetDestination ().IsMulticast () == true)
946  {
947  break; // Do not reply to broadcast or multicast
948  }
949  // Another case to suppress ICMP is a subnet-directed broadcast
950  bool subnetDirected = false;
951  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
952  {
953  Ipv4InterfaceAddress addr = GetAddress (iif, i);
954  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ipHeader.GetDestination ().CombineMask (addr.GetMask ()) &&
955  ipHeader.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
956  {
957  subnetDirected = true;
958  }
959  }
960  if (subnetDirected == false)
961  {
962  GetIcmp ()->SendDestUnreachPort (ipHeader, copy);
963  }
964  }
965  }
966 }
967 
968 bool
970 {
971  NS_LOG_FUNCTION (this << i << address);
972  Ptr<Ipv4Interface> interface = GetInterface (i);
973  bool retVal = interface->AddAddress (address);
974  if (m_routingProtocol != 0)
975  {
976  m_routingProtocol->NotifyAddAddress (i, address);
977  }
978  return retVal;
979 }
980 
982 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
983 {
984  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
985  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
986  return interface->GetAddress (addressIndex);
987 }
988 
989 uint32_t
990 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
991 {
992  NS_LOG_FUNCTION (this << interface);
993  Ptr<Ipv4Interface> iface = GetInterface (interface);
994  return iface->GetNAddresses ();
995 }
996 
997 bool
998 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
999 {
1000  NS_LOG_FUNCTION (this << i << addressIndex);
1001  Ptr<Ipv4Interface> interface = GetInterface (i);
1002  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
1003  if (address != Ipv4InterfaceAddress ())
1004  {
1005  if (m_routingProtocol != 0)
1006  {
1007  m_routingProtocol->NotifyRemoveAddress (i, address);
1008  }
1009  return true;
1010  }
1011  return false;
1012 }
1013 
1014 bool
1016 {
1017  NS_LOG_FUNCTION (this << i << address);
1018 
1019  if (address == Ipv4Address::GetLoopback())
1020  {
1021  NS_LOG_WARN ("Cannot remove loopback address.");
1022  return false;
1023  }
1024  Ptr<Ipv4Interface> interface = GetInterface (i);
1025  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
1026  if (ifAddr != Ipv4InterfaceAddress ())
1027  {
1028  if (m_routingProtocol != 0)
1029  {
1030  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
1031  }
1032  return true;
1033  }
1034  return false;
1035 }
1036 
1037 Ipv4Address
1040 {
1041  NS_LOG_FUNCTION (this << device << dst << scope);
1042  Ipv4Address addr ("0.0.0.0");
1043  Ipv4InterfaceAddress iaddr;
1044  bool found = false;
1045 
1046  if (device != 0)
1047  {
1048  int32_t i = GetInterfaceForDevice (device);
1049  NS_ASSERT_MSG (i >= 0, "No device found on node");
1050  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1051  {
1052  iaddr = GetAddress (i, j);
1053  if (iaddr.IsSecondary ()) continue;
1054  if (iaddr.GetScope () > scope) continue;
1055  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1056  {
1057  return iaddr.GetLocal ();
1058  }
1059  if (!found)
1060  {
1061  addr = iaddr.GetLocal ();
1062  found = true;
1063  }
1064  }
1065  }
1066  if (found)
1067  {
1068  return addr;
1069  }
1070 
1071  // Iterate among all interfaces
1072  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1073  {
1074  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1075  {
1076  iaddr = GetAddress (i, j);
1077  if (iaddr.IsSecondary ()) continue;
1078  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1079  && iaddr.GetScope () <= scope)
1080  {
1081  return iaddr.GetLocal ();
1082  }
1083  }
1084  }
1085  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1086  << scope << ", returning 0");
1087  return addr;
1088 }
1089 
1090 void
1091 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1092 {
1093  NS_LOG_FUNCTION (this << i << metric);
1094  Ptr<Ipv4Interface> interface = GetInterface (i);
1095  interface->SetMetric (metric);
1096 }
1097 
1098 uint16_t
1099 Ipv4L3Protocol::GetMetric (uint32_t i) const
1100 {
1101  NS_LOG_FUNCTION (this << i);
1102  Ptr<Ipv4Interface> interface = GetInterface (i);
1103  return interface->GetMetric ();
1104 }
1105 
1106 uint16_t
1107 Ipv4L3Protocol::GetMtu (uint32_t i) const
1108 {
1109  NS_LOG_FUNCTION (this << i);
1110  Ptr<Ipv4Interface> interface = GetInterface (i);
1111  return interface->GetDevice ()->GetMtu ();
1112 }
1113 
1114 bool
1115 Ipv4L3Protocol::IsUp (uint32_t i) const
1116 {
1117  NS_LOG_FUNCTION (this << i);
1118  Ptr<Ipv4Interface> interface = GetInterface (i);
1119  return interface->IsUp ();
1120 }
1121 
1122 void
1124 {
1125  NS_LOG_FUNCTION (this << i);
1126  Ptr<Ipv4Interface> interface = GetInterface (i);
1127 
1128  // RFC 791, pg.25:
1129  // Every internet module must be able to forward a datagram of 68
1130  // octets without further fragmentation. This is because an internet
1131  // header may be up to 60 octets, and the minimum fragment is 8 octets.
1132  if (interface->GetDevice ()->GetMtu () >= 68)
1133  {
1134  interface->SetUp ();
1135 
1136  if (m_routingProtocol != 0)
1137  {
1138  m_routingProtocol->NotifyInterfaceUp (i);
1139  }
1140  }
1141  else
1142  {
1143  NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octects)");
1144  }
1145 }
1146 
1147 void
1148 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1149 {
1150  NS_LOG_FUNCTION (this << ifaceIndex);
1151  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1152  interface->SetDown ();
1153 
1154  if (m_routingProtocol != 0)
1155  {
1156  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1157  }
1158 }
1159 
1160 bool
1162 {
1163  NS_LOG_FUNCTION (this << i);
1164  Ptr<Ipv4Interface> interface = GetInterface (i);
1165  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1166  return interface->IsForwarding ();
1167 }
1168 
1169 void
1170 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1171 {
1172  NS_LOG_FUNCTION (this << i);
1173  Ptr<Ipv4Interface> interface = GetInterface (i);
1174  interface->SetForwarding (val);
1175 }
1176 
1179 {
1180  NS_LOG_FUNCTION (this << i);
1181  return GetInterface (i)->GetDevice ();
1182 }
1183 
1184 void
1186 {
1187  NS_LOG_FUNCTION (this << forward);
1188  m_ipForward = forward;
1189  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1190  {
1191  (*i)->SetForwarding (forward);
1192  }
1193 }
1194 
1195 bool
1197 {
1198  NS_LOG_FUNCTION (this);
1199  return m_ipForward;
1200 }
1201 
1202 void
1204 {
1205  NS_LOG_FUNCTION (this << model);
1206  m_weakEsModel = model;
1207 }
1208 
1209 bool
1211 {
1212  NS_LOG_FUNCTION (this);
1213  return m_weakEsModel;
1214 }
1215 
1216 void
1218 {
1219  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1220  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1221  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1222 }
1223 
1224 void
1225 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::list<Ptr<Packet> >& listFragments)
1226 {
1227  // BEWARE: here we do assume that the header options are not present.
1228  // a much more complex handling is necessary in case there are options.
1229  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1230  // Of course also the reassemby code shall be changed as well.
1231 
1232  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1233 
1234  Ptr<Packet> p = packet->Copy ();
1235 
1236  Ipv4Header ipv4Header;
1237  p->RemoveHeader (ipv4Header);
1238 
1239  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1240  "IPv4 fragmentation implementation only works without option headers." );
1241 
1242  uint16_t offset = 0;
1243  bool moreFragment = true;
1244  uint16_t originalOffset = 0;
1245  bool alreadyFragmented = false;
1246  uint32_t currentFragmentablePartSize = 0;
1247 
1248  if (!ipv4Header.IsLastFragment())
1249  {
1250  alreadyFragmented = true;
1251  originalOffset = ipv4Header.GetFragmentOffset();
1252  }
1253 
1254  // IPv4 fragments are all 8 bytes aligned but the last.
1255  // The IP payload size is:
1256  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1257  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1258 
1259  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1260 
1261  do
1262  {
1263  Ipv4Header fragmentHeader = ipv4Header;
1264 
1265  if (p->GetSize () > offset + fragmentSize )
1266  {
1267  moreFragment = true;
1268  currentFragmentablePartSize = fragmentSize;
1269  fragmentHeader.SetMoreFragments ();
1270  }
1271  else
1272  {
1273  moreFragment = false;
1274  currentFragmentablePartSize = p->GetSize () - offset;
1275  if (alreadyFragmented)
1276  {
1277  fragmentHeader.SetMoreFragments ();
1278  }
1279  else
1280  {
1281  fragmentHeader.SetLastFragment ();
1282  }
1283  }
1284 
1285  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1286  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1287  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1288 
1289  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1290  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1291 
1292  if (Node::ChecksumEnabled ())
1293  {
1294  fragmentHeader.EnableChecksum ();
1295  }
1296 
1297  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1298 
1299  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1300  fragment->AddHeader (fragmentHeader);
1301 
1302  std::ostringstream oss;
1303  fragment->Print (oss);
1304 
1305  NS_LOG_LOGIC ("New fragment " << *fragment);
1306 
1307  listFragments.push_back (fragment);
1308 
1309  offset += currentFragmentablePartSize;
1310 
1311  }
1312  while (moreFragment);
1313 
1314  return;
1315 }
1316 
1317 bool
1318 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1319 {
1320  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1321 
1322  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
1323  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
1324  std::pair<uint64_t, uint32_t> key;
1325  bool ret = false;
1326  Ptr<Packet> p = packet->Copy ();
1327 
1328  key.first = addressCombination;
1329  key.second = idProto;
1330 
1331  Ptr<Fragments> fragments;
1332 
1333  MapFragments_t::iterator it = m_fragments.find (key);
1334  if (it == m_fragments.end ())
1335  {
1336  fragments = Create<Fragments> ();
1337  m_fragments.insert (std::make_pair (key, fragments));
1340  key, ipHeader, iif);
1341  }
1342  else
1343  {
1344  fragments = it->second;
1345  }
1346 
1347  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1348 
1349  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1350 
1351  if ( fragments->IsEntire () )
1352  {
1353  packet = fragments->GetPacket ();
1354  fragments = 0;
1355  m_fragments.erase (key);
1356  if (m_fragmentsTimers[key].IsRunning ())
1357  {
1358  NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1359  m_fragmentsTimers[key].Cancel ();
1360  }
1361  m_fragmentsTimers.erase (key);
1362  ret = true;
1363  }
1364 
1365  return ret;
1366 }
1367 
1369  : m_moreFragment (0)
1370 {
1371  NS_LOG_FUNCTION (this);
1372 }
1373 
1375 {
1376  NS_LOG_FUNCTION (this);
1377 }
1378 
1379 void
1380 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1381 {
1382  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1383 
1384  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1385 
1386  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1387  {
1388  if (it->second > fragmentOffset)
1389  {
1390  break;
1391  }
1392  }
1393 
1394  if (it == m_fragments.end ())
1395  {
1396  m_moreFragment = moreFragment;
1397  }
1398 
1399  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1400 }
1401 
1402 bool
1404 {
1405  NS_LOG_FUNCTION (this);
1406 
1407  bool ret = !m_moreFragment && m_fragments.size () > 0;
1408 
1409  if (ret)
1410  {
1411  uint16_t lastEndOffset = 0;
1412 
1413  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1414  {
1415  // overlapping fragments do exist
1416  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1417 
1418  if (lastEndOffset < it->second)
1419  {
1420  ret = false;
1421  break;
1422  }
1423  // fragments might overlap in strange ways
1424  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1425  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1426  }
1427  }
1428 
1429  return ret;
1430 }
1431 
1434 {
1435  NS_LOG_FUNCTION (this);
1436 
1437  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1438 
1439  Ptr<Packet> p = it->first->Copy ();
1440  uint16_t lastEndOffset = p->GetSize ();
1441  it++;
1442 
1443  for ( ; it != m_fragments.end (); it++)
1444  {
1445  if ( lastEndOffset > it->second )
1446  {
1447  // The fragments are overlapping.
1448  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1449  // This is different from what Linux does.
1450  // It is not possible to emulate a fragmentation attack.
1451  uint32_t newStart = lastEndOffset - it->second;
1452  if ( it->first->GetSize () > newStart )
1453  {
1454  uint32_t newSize = it->first->GetSize () - newStart;
1455  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1456  p->AddAtEnd (tempFragment);
1457  }
1458  }
1459  else
1460  {
1461  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1462  p->AddAtEnd (it->first);
1463  }
1464  lastEndOffset = p->GetSize ();
1465  }
1466 
1467  return p;
1468 }
1469 
1472 {
1473  NS_LOG_FUNCTION (this);
1474 
1475  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1476 
1477  Ptr<Packet> p = Create<Packet> ();
1478  uint16_t lastEndOffset = 0;
1479 
1480  if ( m_fragments.begin ()->second > 0 )
1481  {
1482  return p;
1483  }
1484 
1485  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1486  {
1487  if ( lastEndOffset > it->second )
1488  {
1489  uint32_t newStart = lastEndOffset - it->second;
1490  uint32_t newSize = it->first->GetSize () - newStart;
1491  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1492  p->AddAtEnd (tempFragment);
1493  }
1494  else if ( lastEndOffset == it->second )
1495  {
1496  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1497  p->AddAtEnd (it->first);
1498  }
1499  lastEndOffset = p->GetSize ();
1500  }
1501 
1502  return p;
1503 }
1504 
1505 void
1506 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
1507 {
1508  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1509 
1510  MapFragments_t::iterator it = m_fragments.find (key);
1511  Ptr<Packet> packet = it->second->GetPartialPacket ();
1512 
1513  // if we have at least 8 bytes, we can send an ICMP.
1514  if ( packet->GetSize () > 8 )
1515  {
1516  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1517  icmp->SendTimeExceededTtl (ipHeader, packet);
1518  }
1519  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1520 
1521  // clear the buffers
1522  it->second = 0;
1523 
1524  m_fragments.erase (key);
1525  m_fragmentsTimers.erase (key);
1526 }
1527 
1528 } // 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:996
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...
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.
hold objects of type ns3::Time
Definition: nstime.h:1008
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
Definition: node.cc:134
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1242
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
std::map< uint8_t, uint16_t > m_identification
Identification (for each protocol)
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)
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.
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
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:441
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:1142
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
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.