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