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