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