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/string.h"
31 #include "ns3/boolean.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "ns3/object-vector.h"
34 #include "ns3/ipv4-header.h"
35 #include "ns3/boolean.h"
36 #include "ns3/ipv4-routing-table-entry.h"
37 #include "ns3/traffic-control-layer.h"
38 
39 #include "loopback-net-device.h"
40 #include "arp-l3-protocol.h"
41 #include "arp-cache.h"
42 #include "ipv4-l3-protocol.h"
43 #include "icmpv4-l4-protocol.h"
44 #include "ipv4-interface.h"
45 #include "ipv4-raw-socket-impl.h"
46 
47 namespace ns3 {
48 
49 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
50 
51 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
52 
53 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
54 
55 TypeId
57 {
58  static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
59  .SetParent<Ipv4> ()
60  .SetGroupName ("Internet")
61  .AddConstructor<Ipv4L3Protocol> ()
62  .AddAttribute ("DefaultTtl",
63  "The TTL value set by default on "
64  "all outgoing packets generated on this node.",
65  UintegerValue (64),
67  MakeUintegerChecker<uint8_t> ())
68  .AddAttribute ("FragmentExpirationTimeout",
69  "When this timeout expires, the fragments "
70  "will be cleared from the buffer.",
71  TimeValue (Seconds (30)),
73  MakeTimeChecker ())
74  .AddAttribute ("EnableDuplicatePacketDetection",
75  "Enable multicast duplicate packet detection based on RFC 6621",
76  BooleanValue (false),
79  .AddAttribute ("DuplicateExpire", "Expiration delay for duplicate cache entries",
80  TimeValue (MilliSeconds (1)),
82  MakeTimeChecker ())
83  .AddAttribute ("PurgeExpiredPeriod",
84  "Time between purges of expired duplicate packet entries, "
85  "0 means never purge",
86  TimeValue (Seconds (1)),
89  .AddTraceSource ("Tx",
90  "Send ipv4 packet to outgoing interface.",
92  "ns3::Ipv4L3Protocol::TxRxTracedCallback")
93  .AddTraceSource ("Rx",
94  "Receive ipv4 packet from incoming interface.",
96  "ns3::Ipv4L3Protocol::TxRxTracedCallback")
97  .AddTraceSource ("Drop",
98  "Drop ipv4 packet",
100  "ns3::Ipv4L3Protocol::DropTracedCallback")
101  .AddAttribute ("InterfaceList",
102  "The set of Ipv4 interfaces associated to this Ipv4 stack.",
105  MakeObjectVectorChecker<Ipv4Interface> ())
106 
107  .AddTraceSource ("SendOutgoing",
108  "A newly-generated packet by this node is "
109  "about to be queued for transmission",
111  "ns3::Ipv4L3Protocol::SentTracedCallback")
112  .AddTraceSource ("UnicastForward",
113  "A unicast IPv4 packet was received by this node "
114  "and is being forwarded to another node",
116  "ns3::Ipv4L3Protocol::SentTracedCallback")
117  .AddTraceSource ("LocalDeliver",
118  "An IPv4 packet was received by/for this node, "
119  "and it is being forward up the stack",
121  "ns3::Ipv4L3Protocol::SentTracedCallback")
122 
123  ;
124  return tid;
125 }
126 
128 {
129  NS_LOG_FUNCTION (this);
130 }
131 
133 {
134  NS_LOG_FUNCTION (this);
135 }
136 
137 void
139 {
140  NS_LOG_FUNCTION (this << protocol);
141  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
142  if (m_protocols.find (key) != m_protocols.end ())
143  {
144  NS_LOG_WARN ("Overwriting default protocol " << int(protocol->GetProtocolNumber ()));
145  }
146  m_protocols[key] = protocol;
147 }
148 
149 void
150 Ipv4L3Protocol::Insert (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
151 {
152  NS_LOG_FUNCTION (this << protocol << interfaceIndex);
153 
154  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
155  if (m_protocols.find (key) != m_protocols.end ())
156  {
157  NS_LOG_WARN ("Overwriting protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
158  }
159  m_protocols[key] = protocol;
160 }
161 
162 void
164 {
165  NS_LOG_FUNCTION (this << protocol);
166 
167  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
168  L4List_t::iterator iter = m_protocols.find (key);
169  if (iter == m_protocols.end ())
170  {
171  NS_LOG_WARN ("Trying to remove an non-existent default protocol " << int(protocol->GetProtocolNumber ()));
172  }
173  else
174  {
175  m_protocols.erase (key);
176  }
177 }
178 
179 void
180 Ipv4L3Protocol::Remove (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
181 {
182  NS_LOG_FUNCTION (this << protocol << interfaceIndex);
183 
184  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
185  L4List_t::iterator iter = m_protocols.find (key);
186  if (iter == m_protocols.end ())
187  {
188  NS_LOG_WARN ("Trying to remove an non-existent protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
189  }
190  else
191  {
192  m_protocols.erase (key);
193  }
194 }
195 
197 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
198 {
199  NS_LOG_FUNCTION (this << protocolNumber);
200 
201  return GetProtocol (protocolNumber, -1);
202 }
203 
205 Ipv4L3Protocol::GetProtocol (int protocolNumber, int32_t interfaceIndex) const
206 {
207  NS_LOG_FUNCTION (this << protocolNumber << interfaceIndex);
208 
209  L4ListKey_t key;
210  L4List_t::const_iterator i;
211  if (interfaceIndex >= 0)
212  {
213  // try the interface-specific protocol.
214  key = std::make_pair (protocolNumber, interfaceIndex);
215  i = m_protocols.find (key);
216  if (i != m_protocols.end ())
217  {
218  return i->second;
219  }
220  }
221  // try the generic protocol.
222  key = std::make_pair (protocolNumber, -1);
223  i = m_protocols.find (key);
224  if (i != m_protocols.end ())
225  {
226  return i->second;
227  }
228 
229  return 0;
230 }
231 
232 void
234 {
235  NS_LOG_FUNCTION (this << node);
236  m_node = node;
237  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
238  SetupLoopback ();
239 }
240 
243 {
244  NS_LOG_FUNCTION (this);
245  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
246  socket->SetNode (m_node);
247  m_sockets.push_back (socket);
248  return socket;
249 }
250 void
252 {
253  NS_LOG_FUNCTION (this << socket);
254  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
255  {
256  if ((*i) == socket)
257  {
258  m_sockets.erase (i);
259  return;
260  }
261  }
262  return;
263 }
264 /*
265  * This method is called by AggregateObject and completes the aggregation
266  * by setting the node in the ipv4 stack
267  */
268 void
270 {
271  NS_LOG_FUNCTION (this);
272  if (m_node == 0)
273  {
274  Ptr<Node>node = this->GetObject<Node>();
275  // verify that it's a valid node and that
276  // the node has not been set before
277  if (node != 0)
278  {
279  this->SetNode (node);
280  }
281  }
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION (this << routingProtocol);
289  m_routingProtocol = routingProtocol;
290  m_routingProtocol->SetIpv4 (this);
291 }
292 
293 
296 {
297  NS_LOG_FUNCTION (this);
298  return m_routingProtocol;
299 }
300 
301 void
303 {
304  NS_LOG_FUNCTION (this);
305  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
306  {
307  i->second = 0;
308  }
309  m_protocols.clear ();
310 
311  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
312  {
313  *i = 0;
314  }
315  m_interfaces.clear ();
317 
318  m_sockets.clear ();
319  m_node = 0;
320  m_routingProtocol = 0;
321 
322  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
323  {
324  it->second = 0;
325  }
326 
327  m_fragments.clear ();
328  m_timeoutEventList.clear ();
329  if (m_timeoutEvent.IsRunning ())
330  {
332  }
333 
334  if (m_cleanDpd.IsRunning ())
335  {
336  m_cleanDpd.Cancel ();
337  }
338  m_dups.clear ();
339 
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION (this);
347 
349  Ptr<LoopbackNetDevice> device = 0;
350  // First check whether an existing LoopbackNetDevice exists on the node
351  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
352  {
353  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
354  {
355  break;
356  }
357  }
358  if (device == 0)
359  {
360  device = CreateObject<LoopbackNetDevice> ();
361  m_node->AddDevice (device);
362  }
363  interface->SetDevice (device);
364  interface->SetNode (m_node);
366  interface->AddAddress (ifaceAddr);
367  uint32_t index = AddIpv4Interface (interface);
368  Ptr<Node> node = GetObject<Node> ();
371  interface->SetUp ();
372  if (m_routingProtocol != 0)
373  {
374  m_routingProtocol->NotifyInterfaceUp (index);
375  }
376 }
377 
378 void
380 {
381  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
382  m_defaultTtl = ttl;
383 }
384 
385 uint32_t
387 {
388  NS_LOG_FUNCTION (this << device);
389  NS_ASSERT (m_node != 0);
390 
392 
393  NS_ASSERT (tc != 0);
394 
399 
400  tc->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
402  tc->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
404 
406  interface->SetNode (m_node);
407  interface->SetDevice (device);
408  interface->SetTrafficControl (tc);
409  interface->SetForwarding (m_ipForward);
410  return AddIpv4Interface (interface);
411 }
412 
413 uint32_t
415 {
416  NS_LOG_FUNCTION (this << interface);
417  uint32_t index = m_interfaces.size ();
418  m_interfaces.push_back (interface);
419  m_reverseInterfacesContainer[interface->GetDevice ()] = index;
420  return index;
421 }
422 
424 Ipv4L3Protocol::GetInterface (uint32_t index) const
425 {
426  NS_LOG_FUNCTION (this << index);
427  if (index < m_interfaces.size ())
428  {
429  return m_interfaces[index];
430  }
431  return 0;
432 }
433 
434 uint32_t
436 {
437  NS_LOG_FUNCTION (this);
438  return m_interfaces.size ();
439 }
440 
441 int32_t
443  Ipv4Address address) const
444 {
445  NS_LOG_FUNCTION (this << address);
446  int32_t interface = 0;
447  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
448  i != m_interfaces.end ();
449  i++, interface++)
450  {
451  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
452  {
453  if ((*i)->GetAddress (j).GetLocal () == address)
454  {
455  return interface;
456  }
457  }
458  }
459 
460  return -1;
461 }
462 
463 int32_t
466  Ipv4Mask mask) const
467 {
468  NS_LOG_FUNCTION (this << address << mask);
469  int32_t interface = 0;
470  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
471  i != m_interfaces.end ();
472  i++, interface++)
473  {
474  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
475  {
476  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
477  {
478  return interface;
479  }
480  }
481  }
482 
483  return -1;
484 }
485 
486 int32_t
488  Ptr<const NetDevice> device) const
489 {
490  NS_LOG_FUNCTION (this << device);
491 
492  Ipv4InterfaceReverseContainer::const_iterator iter = m_reverseInterfacesContainer.find (device);
493  if (iter != m_reverseInterfacesContainer.end ())
494  {
495  return (*iter).second;
496  }
497 
498  return -1;
499 }
500 
501 bool
503 {
504  NS_LOG_FUNCTION (this << address << iif);
505  // First check the incoming interface for a unicast address match
506  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
507  {
508  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
509  if (address == iaddr.GetLocal ())
510  {
511  NS_LOG_LOGIC ("For me (destination " << address << " match)");
512  return true;
513  }
514  if (address == iaddr.GetBroadcast ())
515  {
516  NS_LOG_LOGIC ("For me (interface broadcast address)");
517  return true;
518  }
519  }
520 
521  if (address.IsMulticast ())
522  {
523 #ifdef NOTYET
524  if (MulticastCheckGroup (iif, address ))
525 #endif
526  if (true)
527  {
528  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address)");
529  return true;
530  }
531  }
532 
533  if (address.IsBroadcast ())
534  {
535  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
536  return true;
537  }
538 
539  if (GetWeakEsModel ()) // Check other interfaces
540  {
541  for (uint32_t j = 0; j < GetNInterfaces (); j++)
542  {
543  if (j == uint32_t (iif)) continue;
544  for (uint32_t i = 0; i < GetNAddresses (j); i++)
545  {
546  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
547  if (address == iaddr.GetLocal ())
548  {
549  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
550  return true;
551  }
552  // This is a small corner case: match another interface's broadcast address
553  if (address == iaddr.GetBroadcast ())
554  {
555  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
556  return true;
557  }
558  }
559  }
560  }
561  return false;
562 }
563 
564 void
565 Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
566  const Address &to, NetDevice::PacketType packetType)
567 {
568  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
569 
570  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
571  m_node->GetId ());
572 
573 
574  int32_t interface = GetInterfaceForDevice(device);
575  NS_ASSERT_MSG (interface != -1, "Received a packet from an interface that is not known to IPv4");
576 
577  Ptr<Packet> packet = p->Copy ();
578 
579  Ptr<Ipv4Interface> ipv4Interface = m_interfaces[interface];
580 
581  if (ipv4Interface->IsUp ())
582  {
583  m_rxTrace (packet, m_node->GetObject<Ipv4> (), interface);
584  }
585  else
586  {
587  NS_LOG_LOGIC ("Dropping received packet -- interface is down");
588  Ipv4Header ipHeader;
589  packet->RemoveHeader (ipHeader);
590  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
591  return;
592  }
593 
594  Ipv4Header ipHeader;
595  if (Node::ChecksumEnabled ())
596  {
597  ipHeader.EnableChecksum ();
598  }
599  packet->RemoveHeader (ipHeader);
600 
601  // Trim any residual frame padding from underlying devices
602  if (ipHeader.GetPayloadSize () < packet->GetSize ())
603  {
604  packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
605  }
606 
607  if (!ipHeader.IsChecksumOk ())
608  {
609  NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
610  m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject<Ipv4> (), interface);
611  return;
612  }
613 
614  // the packet is valid, we update the ARP cache entry (if present)
615  Ptr<ArpCache> arpCache = ipv4Interface->GetArpCache ();
616  if (arpCache)
617  {
618  // case one, it's a a direct routing.
619  ArpCache::Entry *entry = arpCache->Lookup (ipHeader.GetSource ());
620  if (entry)
621  {
622  if (entry->IsAlive ())
623  {
624  entry->UpdateSeen ();
625  }
626  }
627  else
628  {
629  // It's not in the direct routing, so it's the router, and it could have multiple IP addresses.
630  // In doubt, update all of them.
631  // Note: it's a confirmed behavior for Linux routers.
632  std::list<ArpCache::Entry *> entryList = arpCache->LookupInverse (from);
633  std::list<ArpCache::Entry *>::iterator iter;
634  for (iter = entryList.begin (); iter != entryList.end (); iter ++)
635  {
636  if ((*iter)->IsAlive ())
637  {
638  (*iter)->UpdateSeen ();
639  }
640  }
641  }
642  }
643 
644  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
645  {
646  NS_LOG_LOGIC ("Forwarding to raw socket");
647  Ptr<Ipv4RawSocketImpl> socket = *i;
648  socket->ForwardUp (packet, ipHeader, ipv4Interface);
649  }
650 
651  if (m_enableDpd && ipHeader.GetDestination ().IsMulticast () && UpdateDuplicate (packet, ipHeader))
652  {
653  NS_LOG_LOGIC ("Dropping received packet -- duplicate.");
654  m_dropTrace (ipHeader, packet, DROP_DUPLICATE, m_node->GetObject<Ipv4> (), interface);
655  return;
656  }
657 
658  NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
659  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
664  ))
665  {
666  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
667  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), interface);
668  }
669 }
670 
673 {
674  NS_LOG_FUNCTION (this);
676  if (prot != 0)
677  {
678  return prot->GetObject<Icmpv4L4Protocol> ();
679  }
680  else
681  {
682  return 0;
683  }
684 }
685 
686 bool
688 {
689  NS_LOG_FUNCTION (this << ad);
690 
691  if (ad.IsBroadcast () || ad.IsMulticast ())
692  {
693  return false;
694  }
695  else
696  {
697  // check for subnet-broadcast
698  for (uint32_t ifaceIndex = 0; ifaceIndex < GetNInterfaces (); ifaceIndex++)
699  {
700  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
701  {
702  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
703  NS_LOG_LOGIC ("Testing address " << ad << " with subnet-directed broadcast " << ifAddr.GetBroadcast () );
704  if (ad == ifAddr.GetBroadcast () )
705  {
706  return false;
707  }
708  }
709  }
710  }
711 
712  return true;
713 }
714 
715 bool
717 {
718  NS_LOG_FUNCTION (this << ad << interfaceMask);
719  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
720 }
721 
722 void
724  Ipv4Header ipHeader,
725  Ptr<Ipv4Route> route)
726 {
727  NS_LOG_FUNCTION (this << packet << ipHeader << route);
728  if (Node::ChecksumEnabled ())
729  {
730  ipHeader.EnableChecksum ();
731  }
732  SendRealOut (route, packet, ipHeader);
733 }
734 
735 void
737  Ptr<Ipv4> ipv4, uint32_t interface)
738 {
739  Ptr<Packet> packetCopy = packet->Copy ();
740  packetCopy->AddHeader (ipHeader);
741  m_txTrace (packetCopy, ipv4, interface);
742 }
743 
744 void
746  Ipv4Address source,
747  Ipv4Address destination,
748  uint8_t protocol,
749  Ptr<Ipv4Route> route)
750 {
751  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
752 
753  Ipv4Header ipHeader;
754  bool mayFragment = true;
755  uint8_t ttl = m_defaultTtl;
756  SocketIpTtlTag tag;
757  bool found = packet->RemovePacketTag (tag);
758  if (found)
759  {
760  ttl = tag.GetTtl ();
761  }
762 
763  uint8_t tos = 0;
764  SocketIpTosTag ipTosTag;
765  found = packet->RemovePacketTag (ipTosTag);
766  if (found)
767  {
768  tos = ipTosTag.GetTos ();
769  }
770 
771  // Handle a few cases:
772  // 1) packet is destined to limited broadcast address
773  // 2) packet is destined to a subnet-directed broadcast address
774  // 3) packet is not broadcast, and is passed in with a route entry
775  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
776  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
777 
778  // 1) packet is destined to limited broadcast address or link-local multicast address
779  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
780  {
781  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
782  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
783  uint32_t ifaceIndex = 0;
784  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
785  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
786  {
787  Ptr<Ipv4Interface> outInterface = *ifaceIter;
788  bool sendIt = false;
789  if (source == Ipv4Address::GetAny ())
790  {
791  sendIt = true;
792  }
793  for (uint32_t index = 0; index < outInterface->GetNAddresses (); index++)
794  {
795  if (outInterface->GetAddress (index).GetLocal () == source)
796  {
797  sendIt = true;
798  }
799  }
800  if (sendIt)
801  {
802  Ptr<Packet> packetCopy = packet->Copy ();
803 
804  NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ());
805 
806  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
807  CallTxTrace (ipHeader, packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
808  outInterface->Send (packetCopy, ipHeader, destination);
809  }
810  }
811  return;
812  }
813 
814  // 2) check: packet is destined to a subnet-directed broadcast address
815  uint32_t ifaceIndex = 0;
816  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
817  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
818  {
819  Ptr<Ipv4Interface> outInterface = *ifaceIter;
820  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
821  {
822  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
823  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
824  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
825  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
826  {
827  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
828  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
829  Ptr<Packet> packetCopy = packet->Copy ();
830  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
831  CallTxTrace (ipHeader, packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
832  outInterface->Send (packetCopy, ipHeader, destination);
833  return;
834  }
835  }
836  }
837 
838  // 3) packet is not broadcast, and is passed in with a route entry
839  // with a valid Ipv4Address as the gateway
840  if (route && route->GetGateway () != Ipv4Address ())
841  {
842  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
843  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
844  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
845  m_sendOutgoingTrace (ipHeader, packet, interface);
846  SendRealOut (route, packet->Copy (), ipHeader);
847  return;
848  }
849  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
850  if (route && route->GetGateway () == Ipv4Address ())
851  {
852  // This could arise because the synchronous RouteOutput() call
853  // returned to the transport protocol with a source address but
854  // there was no next hop available yet (since a route may need
855  // to be queried).
856  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 4: This case not yet implemented");
857  }
858  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
859  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 5: passed in with no route " << destination);
860  Socket::SocketErrno errno_;
861  Ptr<NetDevice> oif (0); // unused for now
862  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
863  Ptr<Ipv4Route> newRoute;
864  if (m_routingProtocol != 0)
865  {
866  newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
867  }
868  else
869  {
870  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
871  }
872  if (newRoute)
873  {
874  int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
875  m_sendOutgoingTrace (ipHeader, packet, interface);
876  SendRealOut (newRoute, packet->Copy (), ipHeader);
877  }
878  else
879  {
880  NS_LOG_WARN ("No route to host. Drop.");
881  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
882  }
883 }
884 
885 // \todo when should we set ip_id? check whether we are incrementing
886 // m_identification on packets that may later be dropped in this stack
887 // and whether that deviates from Linux
890  Ipv4Address source,
891  Ipv4Address destination,
892  uint8_t protocol,
893  uint16_t payloadSize,
894  uint8_t ttl,
895  uint8_t tos,
896  bool mayFragment)
897 {
898  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
899  Ipv4Header ipHeader;
900  ipHeader.SetSource (source);
901  ipHeader.SetDestination (destination);
902  ipHeader.SetProtocol (protocol);
903  ipHeader.SetPayloadSize (payloadSize);
904  ipHeader.SetTtl (ttl);
905  ipHeader.SetTos (tos);
906 
907  uint64_t src = source.Get ();
908  uint64_t dst = destination.Get ();
909  uint64_t srcDst = dst | (src << 32);
910  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
911 
912  if (mayFragment == true)
913  {
914  ipHeader.SetMayFragment ();
915  ipHeader.SetIdentification (m_identification[key]);
916  m_identification[key]++;
917  }
918  else
919  {
920  ipHeader.SetDontFragment ();
921  // RFC 6864 does not state anything about atomic datagrams
922  // identification requirement:
923  // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
924  // to any value.
925  ipHeader.SetIdentification (m_identification[key]);
926  m_identification[key]++;
927  }
928  if (Node::ChecksumEnabled ())
929  {
930  ipHeader.EnableChecksum ();
931  }
932  return ipHeader;
933 }
934 
935 void
937  Ptr<Packet> packet,
938  Ipv4Header const &ipHeader)
939 {
940  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
941  if (route == 0)
942  {
943  NS_LOG_WARN ("No route to host. Drop.");
944  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
945  return;
946  }
947  Ptr<NetDevice> outDev = route->GetOutputDevice ();
948  int32_t interface = GetInterfaceForDevice (outDev);
949  NS_ASSERT (interface >= 0);
950  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
951  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
952 
953  if (route->GetGateway () != Ipv4Address ("0.0.0.0"))
954  {
955  if (outInterface->IsUp ())
956  {
957  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
958  if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () )
959  {
960  std::list<Ipv4PayloadHeaderPair> listFragments;
961  DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments);
962  for ( std::list<Ipv4PayloadHeaderPair>::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
963  {
964  CallTxTrace (it->second, it->first, m_node->GetObject<Ipv4> (), interface);
965  outInterface->Send (it->first, it->second, route->GetGateway ());
966  }
967  }
968  else
969  {
970  CallTxTrace (ipHeader, packet, m_node->GetObject<Ipv4> (), interface);
971  outInterface->Send (packet, ipHeader, route->GetGateway ());
972  }
973  }
974  else
975  {
976  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
977  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
978  }
979  }
980  else
981  {
982  if (outInterface->IsUp ())
983  {
984  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
985  if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () )
986  {
987  std::list<Ipv4PayloadHeaderPair> listFragments;
988  DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments);
989  for ( std::list<Ipv4PayloadHeaderPair>::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
990  {
991  NS_LOG_LOGIC ("Sending fragment " << *(it->first) );
992  CallTxTrace (it->second, it->first, m_node->GetObject<Ipv4> (), interface);
993  outInterface->Send (it->first, it->second, ipHeader.GetDestination ());
994  }
995  }
996  else
997  {
998  CallTxTrace (ipHeader, packet, m_node->GetObject<Ipv4> (), interface);
999  outInterface->Send (packet, ipHeader, ipHeader.GetDestination ());
1000  }
1001  }
1002  else
1003  {
1004  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
1005  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
1006  }
1007  }
1008 }
1009 
1010 // This function analogous to Linux ip_mr_forward()
1011 void
1013 {
1014  NS_LOG_FUNCTION (this << mrtentry << p << header);
1015  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
1016 
1017  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
1018  std::map<uint32_t, uint32_t>::iterator mapIter;
1019 
1020  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
1021  {
1022  uint32_t interfaceId = mapIter->first;
1023  //uint32_t outputTtl = mapIter->second; // Unused for now
1024 
1025  Ptr<Packet> packet = p->Copy ();
1026  Ipv4Header h = header;
1027  h.SetTtl (header.GetTtl () - 1);
1028  if (h.GetTtl () == 0)
1029  {
1030  NS_LOG_WARN ("TTL exceeded. Drop.");
1031  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interfaceId);
1032  return;
1033  }
1034  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
1035  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
1036  rtentry->SetSource (h.GetSource ());
1037  rtentry->SetDestination (h.GetDestination ());
1038  rtentry->SetGateway (Ipv4Address::GetAny ());
1039  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
1040  SendRealOut (rtentry, packet, h);
1041  continue;
1042  }
1043 }
1044 
1045 // This function analogous to Linux ip_forward()
1046 void
1048 {
1049  NS_LOG_FUNCTION (this << rtentry << p << header);
1050  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
1051  // Forwarding
1052  Ipv4Header ipHeader = header;
1053  Ptr<Packet> packet = p->Copy ();
1054  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
1055  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
1056  if (ipHeader.GetTtl () == 0)
1057  {
1058  // Do not reply to multicast/broadcast IP address
1059  if (ipHeader.GetDestination ().IsBroadcast () == false &&
1060  ipHeader.GetDestination ().IsMulticast () == false)
1061  {
1062  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1063  icmp->SendTimeExceededTtl (ipHeader, packet, false);
1064  }
1065  NS_LOG_WARN ("TTL exceeded. Drop.");
1066  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
1067  return;
1068  }
1069  // in case the packet still has a priority tag attached, remove it
1070  SocketPriorityTag priorityTag;
1071  packet->RemovePacketTag (priorityTag);
1072  uint8_t priority = Socket::IpTos2Priority (ipHeader.GetTos ());
1073  // add a priority tag if the priority is not null
1074  if (priority)
1075  {
1076  priorityTag.SetPriority (priority);
1077  packet->AddPacketTag (priorityTag);
1078  }
1079 
1080  m_unicastForwardTrace (ipHeader, packet, interface);
1081  SendRealOut (rtentry, packet, ipHeader);
1082 }
1083 
1084 void
1086 {
1087  NS_LOG_FUNCTION (this << packet << &ip << iif);
1088  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
1089  Ipv4Header ipHeader = ip;
1090 
1091  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
1092  {
1093  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
1094  bool isPacketComplete;
1095  isPacketComplete = ProcessFragment (p, ipHeader, iif);
1096  if ( isPacketComplete == false)
1097  {
1098  return;
1099  }
1100  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
1101  ipHeader.SetFragmentOffset (0);
1102  ipHeader.SetPayloadSize (p->GetSize ());
1103  }
1104 
1105  m_localDeliverTrace (ipHeader, p, iif);
1106 
1107  Ptr<IpL4Protocol> protocol = GetProtocol (ipHeader.GetProtocol (), iif);
1108  if (protocol != 0)
1109  {
1110  // we need to make a copy in the unlikely event we hit the
1111  // RX_ENDPOINT_UNREACH codepath
1112  Ptr<Packet> copy = p->Copy ();
1113  enum IpL4Protocol::RxStatus status =
1114  protocol->Receive (p, ipHeader, GetInterface (iif));
1115  switch (status) {
1116  case IpL4Protocol::RX_OK:
1117  // fall through
1119  // fall through
1121  break;
1123  if (ipHeader.GetDestination ().IsBroadcast () == true ||
1124  ipHeader.GetDestination ().IsMulticast () == true)
1125  {
1126  break; // Do not reply to broadcast or multicast
1127  }
1128  // Another case to suppress ICMP is a subnet-directed broadcast
1129  bool subnetDirected = false;
1130  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
1131  {
1132  Ipv4InterfaceAddress addr = GetAddress (iif, i);
1133  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ipHeader.GetDestination ().CombineMask (addr.GetMask ()) &&
1134  ipHeader.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
1135  {
1136  subnetDirected = true;
1137  }
1138  }
1139  if (subnetDirected == false)
1140  {
1141  GetIcmp ()->SendDestUnreachPort (ipHeader, copy);
1142  }
1143  }
1144  }
1145 }
1146 
1147 bool
1149 {
1150  NS_LOG_FUNCTION (this << i << address);
1151  Ptr<Ipv4Interface> interface = GetInterface (i);
1152  bool retVal = interface->AddAddress (address);
1153  if (m_routingProtocol != 0)
1154  {
1155  m_routingProtocol->NotifyAddAddress (i, address);
1156  }
1157  return retVal;
1158 }
1159 
1161 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
1162 {
1163  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
1164  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
1165  return interface->GetAddress (addressIndex);
1166 }
1167 
1168 uint32_t
1169 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
1170 {
1171  NS_LOG_FUNCTION (this << interface);
1172  Ptr<Ipv4Interface> iface = GetInterface (interface);
1173  return iface->GetNAddresses ();
1174 }
1175 
1176 bool
1177 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
1178 {
1179  NS_LOG_FUNCTION (this << i << addressIndex);
1180  Ptr<Ipv4Interface> interface = GetInterface (i);
1181  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
1182  if (address != Ipv4InterfaceAddress ())
1183  {
1184  if (m_routingProtocol != 0)
1185  {
1186  m_routingProtocol->NotifyRemoveAddress (i, address);
1187  }
1188  return true;
1189  }
1190  return false;
1191 }
1192 
1193 bool
1195 {
1196  NS_LOG_FUNCTION (this << i << address);
1197 
1199  {
1200  NS_LOG_WARN ("Cannot remove loopback address.");
1201  return false;
1202  }
1203  Ptr<Ipv4Interface> interface = GetInterface (i);
1204  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
1205  if (ifAddr != Ipv4InterfaceAddress ())
1206  {
1207  if (m_routingProtocol != 0)
1208  {
1209  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
1210  }
1211  return true;
1212  }
1213  return false;
1214 }
1215 
1218 {
1219  NS_LOG_FUNCTION (this << interfaceIdx << " " << dest);
1220  if (GetNAddresses (interfaceIdx) == 1) // common case
1221  {
1222  return GetAddress (interfaceIdx, 0).GetLocal ();
1223  }
1224  // no way to determine the scope of the destination, so adopt the
1225  // following rule: pick the first available address (index 0) unless
1226  // a subsequent address is on link (in which case, pick the primary
1227  // address if there are multiple)
1228  Ipv4Address candidate = GetAddress (interfaceIdx, 0).GetLocal ();
1229  for (uint32_t i = 0; i < GetNAddresses (interfaceIdx); i++)
1230  {
1231  Ipv4InterfaceAddress test = GetAddress (interfaceIdx, i);
1232  if (test.GetLocal ().CombineMask (test.GetMask ()) == dest.CombineMask (test.GetMask ()))
1233  {
1234  if (test.IsSecondary () == false)
1235  {
1236  return test.GetLocal ();
1237  }
1238  }
1239  }
1240  return candidate;
1241 }
1242 
1243 Ipv4Address
1246 {
1247  NS_LOG_FUNCTION (this << device << dst << scope);
1248  Ipv4Address addr ("0.0.0.0");
1249  Ipv4InterfaceAddress iaddr;
1250  bool found = false;
1251 
1252  if (device != 0)
1253  {
1254  int32_t i = GetInterfaceForDevice (device);
1255  NS_ASSERT_MSG (i >= 0, "No device found on node");
1256  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1257  {
1258  iaddr = GetAddress (i, j);
1259  if (iaddr.IsSecondary ()) continue;
1260  if (iaddr.GetScope () > scope) continue;
1261  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1262  {
1263  return iaddr.GetLocal ();
1264  }
1265  if (!found)
1266  {
1267  addr = iaddr.GetLocal ();
1268  found = true;
1269  }
1270  }
1271  }
1272  if (found)
1273  {
1274  return addr;
1275  }
1276 
1277  // Iterate among all interfaces
1278  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1279  {
1280  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1281  {
1282  iaddr = GetAddress (i, j);
1283  if (iaddr.IsSecondary ()) continue;
1284  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1285  && iaddr.GetScope () <= scope)
1286  {
1287  return iaddr.GetLocal ();
1288  }
1289  }
1290  }
1291  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1292  << scope << ", returning 0");
1293  return addr;
1294 }
1295 
1296 void
1297 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1298 {
1299  NS_LOG_FUNCTION (this << i << metric);
1300  Ptr<Ipv4Interface> interface = GetInterface (i);
1301  interface->SetMetric (metric);
1302 }
1303 
1304 uint16_t
1305 Ipv4L3Protocol::GetMetric (uint32_t i) const
1306 {
1307  NS_LOG_FUNCTION (this << i);
1308  Ptr<Ipv4Interface> interface = GetInterface (i);
1309  return interface->GetMetric ();
1310 }
1311 
1312 uint16_t
1313 Ipv4L3Protocol::GetMtu (uint32_t i) const
1314 {
1315  NS_LOG_FUNCTION (this << i);
1316  Ptr<Ipv4Interface> interface = GetInterface (i);
1317  return interface->GetDevice ()->GetMtu ();
1318 }
1319 
1320 bool
1321 Ipv4L3Protocol::IsUp (uint32_t i) const
1322 {
1323  NS_LOG_FUNCTION (this << i);
1324  Ptr<Ipv4Interface> interface = GetInterface (i);
1325  return interface->IsUp ();
1326 }
1327 
1328 void
1330 {
1331  NS_LOG_FUNCTION (this << i);
1332  Ptr<Ipv4Interface> interface = GetInterface (i);
1333 
1334  // RFC 791, pg.25:
1335  // Every internet module must be able to forward a datagram of 68
1336  // octets without further fragmentation. This is because an internet
1337  // header may be up to 60 octets, and the minimum fragment is 8 octets.
1338  if (interface->GetDevice ()->GetMtu () >= 68)
1339  {
1340  interface->SetUp ();
1341 
1342  if (m_routingProtocol != 0)
1343  {
1344  m_routingProtocol->NotifyInterfaceUp (i);
1345  }
1346  }
1347  else
1348  {
1349  NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octects)");
1350  }
1351 }
1352 
1353 void
1354 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1355 {
1356  NS_LOG_FUNCTION (this << ifaceIndex);
1357  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1358  interface->SetDown ();
1359 
1360  if (m_routingProtocol != 0)
1361  {
1362  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1363  }
1364 }
1365 
1366 bool
1368 {
1369  NS_LOG_FUNCTION (this << i);
1370  Ptr<Ipv4Interface> interface = GetInterface (i);
1371  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1372  return interface->IsForwarding ();
1373 }
1374 
1375 void
1376 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1377 {
1378  NS_LOG_FUNCTION (this << i);
1379  Ptr<Ipv4Interface> interface = GetInterface (i);
1380  interface->SetForwarding (val);
1381 }
1382 
1385 {
1386  NS_LOG_FUNCTION (this << i);
1387  return GetInterface (i)->GetDevice ();
1388 }
1389 
1390 void
1392 {
1393  NS_LOG_FUNCTION (this << forward);
1394  m_ipForward = forward;
1395  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1396  {
1397  (*i)->SetForwarding (forward);
1398  }
1399 }
1400 
1401 bool
1403 {
1404  NS_LOG_FUNCTION (this);
1405  return m_ipForward;
1406 }
1407 
1408 void
1410 {
1411  NS_LOG_FUNCTION (this << model);
1412  m_weakEsModel = model;
1413 }
1414 
1415 bool
1417 {
1418  NS_LOG_FUNCTION (this);
1419  return m_weakEsModel;
1420 }
1421 
1422 void
1424 {
1425  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1426  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1427  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1428 
1429  // \todo Send an ICMP no route.
1430 }
1431 
1432 void
1433 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, const Ipv4Header & ipv4Header, uint32_t outIfaceMtu, std::list<Ipv4PayloadHeaderPair>& listFragments)
1434 {
1435  // BEWARE: here we do assume that the header options are not present.
1436  // a much more complex handling is necessary in case there are options.
1437  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1438  // Of course also the reassemby code shall be changed as well.
1439 
1440  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1441 
1442  Ptr<Packet> p = packet->Copy ();
1443 
1444  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1445  "IPv4 fragmentation implementation only works without option headers." );
1446 
1447  uint16_t offset = 0;
1448  bool moreFragment = true;
1449  uint16_t originalOffset = ipv4Header.GetFragmentOffset();
1450  bool isLastFragment = ipv4Header.IsLastFragment();
1451  uint32_t currentFragmentablePartSize = 0;
1452 
1453  // IPv4 fragments are all 8 bytes aligned but the last.
1454  // The IP payload size is:
1455  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1456  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1457 
1458  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1459 
1460  do
1461  {
1462  Ipv4Header fragmentHeader = ipv4Header;
1463 
1464  if (p->GetSize () > offset + fragmentSize )
1465  {
1466  moreFragment = true;
1467  currentFragmentablePartSize = fragmentSize;
1468  fragmentHeader.SetMoreFragments ();
1469  }
1470  else
1471  {
1472  moreFragment = false;
1473  currentFragmentablePartSize = p->GetSize () - offset;
1474  if (!isLastFragment)
1475  {
1476  fragmentHeader.SetMoreFragments ();
1477  }
1478  else
1479  {
1480  fragmentHeader.SetLastFragment ();
1481  }
1482  }
1483 
1484  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1485  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1486  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1487 
1488  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1489  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1490 
1491  if (Node::ChecksumEnabled ())
1492  {
1493  fragmentHeader.EnableChecksum ();
1494  }
1495 
1496  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1497 
1498  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1499 
1500  std::ostringstream oss;
1501  oss << fragmentHeader;
1502  fragment->Print (oss);
1503 
1504  NS_LOG_LOGIC ("New fragment " << *fragment);
1505 
1506  listFragments.emplace_back (fragment, fragmentHeader);
1507 
1508  offset += currentFragmentablePartSize;
1509 
1510  }
1511  while (moreFragment);
1512 
1513  return;
1514 }
1515 
1516 bool
1517 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1518 {
1519  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1520 
1521  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
1522  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
1523  FragmentKey_t key;
1524  bool ret = false;
1525  Ptr<Packet> p = packet->Copy ();
1526 
1527  key.first = addressCombination;
1528  key.second = idProto;
1529 
1530  Ptr<Fragments> fragments;
1531 
1532  MapFragments_t::iterator it = m_fragments.find (key);
1533  if (it == m_fragments.end ())
1534  {
1535  fragments = Create<Fragments> ();
1536  m_fragments.insert (std::make_pair (key, fragments));
1537 
1538  FragmentsTimeoutsListI_t iter = SetTimeout (key, ipHeader, iif);
1539  fragments->SetTimeoutIter (iter);
1540  }
1541  else
1542  {
1543  fragments = it->second;
1544  }
1545 
1546  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1547 
1548  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1549 
1550  if ( fragments->IsEntire () )
1551  {
1552  packet = fragments->GetPacket ();
1553  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
1554  fragments = 0;
1555  m_fragments.erase (key);
1556  ret = true;
1557  }
1558 
1559  return ret;
1560 }
1561 
1563  : m_moreFragment (0)
1564 {
1565  NS_LOG_FUNCTION (this);
1566 }
1567 
1569 {
1570  NS_LOG_FUNCTION (this);
1571 }
1572 
1573 void
1574 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1575 {
1576  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1577 
1578  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1579 
1580  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1581  {
1582  if (it->second > fragmentOffset)
1583  {
1584  break;
1585  }
1586  }
1587 
1588  if (it == m_fragments.end ())
1589  {
1590  m_moreFragment = moreFragment;
1591  }
1592 
1593  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1594 }
1595 
1596 bool
1598 {
1599  NS_LOG_FUNCTION (this);
1600 
1601  bool ret = !m_moreFragment && m_fragments.size () > 0;
1602 
1603  if (ret)
1604  {
1605  uint16_t lastEndOffset = 0;
1606 
1607  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1608  {
1609  // overlapping fragments do exist
1610  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1611 
1612  if (lastEndOffset < it->second)
1613  {
1614  ret = false;
1615  break;
1616  }
1617  // fragments might overlap in strange ways
1618  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1619  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1620  }
1621  }
1622 
1623  return ret;
1624 }
1625 
1628 {
1629  NS_LOG_FUNCTION (this);
1630 
1631  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1632 
1633  Ptr<Packet> p = it->first->Copy ();
1634  uint16_t lastEndOffset = p->GetSize ();
1635  it++;
1636 
1637  for ( ; it != m_fragments.end (); it++)
1638  {
1639  if ( lastEndOffset > it->second )
1640  {
1641  // The fragments are overlapping.
1642  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1643  // This is different from what Linux does.
1644  // It is not possible to emulate a fragmentation attack.
1645  uint32_t newStart = lastEndOffset - it->second;
1646  if ( it->first->GetSize () > newStart )
1647  {
1648  uint32_t newSize = it->first->GetSize () - newStart;
1649  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1650  p->AddAtEnd (tempFragment);
1651  }
1652  }
1653  else
1654  {
1655  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1656  p->AddAtEnd (it->first);
1657  }
1658  lastEndOffset = p->GetSize ();
1659  }
1660 
1661  return p;
1662 }
1663 
1666 {
1667  NS_LOG_FUNCTION (this);
1668 
1669  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1670 
1671  Ptr<Packet> p = Create<Packet> ();
1672  uint16_t lastEndOffset = 0;
1673 
1674  if ( m_fragments.begin ()->second > 0 )
1675  {
1676  return p;
1677  }
1678 
1679  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1680  {
1681  if ( lastEndOffset > it->second )
1682  {
1683  uint32_t newStart = lastEndOffset - it->second;
1684  uint32_t newSize = it->first->GetSize () - newStart;
1685  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1686  p->AddAtEnd (tempFragment);
1687  }
1688  else if ( lastEndOffset == it->second )
1689  {
1690  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1691  p->AddAtEnd (it->first);
1692  }
1693  lastEndOffset = p->GetSize ();
1694  }
1695 
1696  return p;
1697 }
1698 
1699 void
1701 {
1702  m_timeoutIter = iter;
1703  return;
1704 }
1705 
1708 {
1709  return m_timeoutIter;
1710 }
1711 
1712 
1713 void
1715 {
1716  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1717 
1718  MapFragments_t::iterator it = m_fragments.find (key);
1719  Ptr<Packet> packet = it->second->GetPartialPacket ();
1720 
1721  // if we have at least 8 bytes, we can send an ICMP.
1722  if ( packet->GetSize () > 8 )
1723  {
1724  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1725  icmp->SendTimeExceededTtl (ipHeader, packet, true);
1726  }
1727  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1728 
1729  // clear the buffers
1730  it->second = 0;
1731 
1732  m_fragments.erase (key);
1733 }
1734 
1735 bool
1737 {
1738  NS_LOG_FUNCTION (this << p << header);
1739 
1740  // \todo RFC 6621 mandates SHA-1 hash. For now ns3 hash should be fine.
1741  uint8_t proto = header.GetProtocol ();
1742  Ipv4Address src = header.GetSource ();
1743  Ipv4Address dst = header.GetDestination ();
1744  uint64_t id = header.GetIdentification ();
1745 
1746  // concat hash value onto id
1747  uint64_t hash = id << 32;
1748  if (header.GetFragmentOffset () || !header.IsLastFragment ())
1749  {
1750  // use I-DPD (RFC 6621, Sec 6.2.1)
1751  hash |= header.GetFragmentOffset ();
1752  }
1753  else
1754  {
1755  // use H-DPD (RFC 6621, Sec 6.2.2)
1756 
1757  // serialize packet
1758  Ptr<Packet> pkt = p->Copy ();
1759  pkt->AddHeader (header);
1760 
1761  std::ostringstream oss (std::ios_base::binary);
1762  pkt->CopyData (&oss, pkt->GetSize ());
1763  std::string bytes = oss.str ();
1764 
1765  NS_ASSERT_MSG (bytes.size () >= 20, "Degenerate header serialization");
1766 
1767  // zero out mutable fields
1768  bytes[1] = 0; // DSCP / ECN
1769  bytes[6] = bytes[7] = 0; // Flags / Fragment offset
1770  bytes[8] = 0; // TTL
1771  bytes[10] = bytes[11] = 0; // Header checksum
1772  if (header.GetSerializedSize () > 20) // assume options should be 0'd
1773  {
1774  std::fill_n (bytes.begin () + 20, header.GetSerializedSize () - 20, 0);
1775  }
1776 
1777  // concat hash onto ID
1778  hash |= (uint64_t)Hash32 (bytes);
1779  }
1780 
1781  // set cleanup job for new duplicate entries
1783  {
1785  }
1786 
1787  // assume this is a new entry
1788  DupTuple_t key {hash, proto, src, dst};
1789  NS_LOG_DEBUG ("Packet " << p->GetUid () << " key = (" <<
1790  std::hex << std::get<0> (key) << ", " <<
1791  std::dec << +std::get<1> (key) << ", " <<
1792  std::get<2> (key) << ", " <<
1793  std::get<3> (key) << ")");
1794 
1795  // place a new entry, on collision the existing entry iterator is returned
1796  DupMap_t::iterator iter;
1797  bool inserted, isDup;
1798  std::tie (iter, inserted) = m_dups.emplace (key, Seconds (0));
1799  isDup = !inserted && iter->second > Simulator::Now ();
1800 
1801  // set the expiration event
1802  iter->second = Simulator::Now () + m_expire;
1803  return isDup;
1804 }
1805 
1806 void
1808 {
1809  NS_LOG_FUNCTION (this);
1810 
1811  DupMap_t::size_type n = 0;
1812  Time expire = Simulator::Now ();
1813  auto iter = m_dups.cbegin ();
1814  while (iter != m_dups.cend ())
1815  {
1816  if (iter->second < expire)
1817  {
1818  NS_LOG_LOGIC ("Remove key = (" <<
1819  std::hex << std::get<0> (iter->first) << ", " <<
1820  std::dec << +std::get<1> (iter->first) << ", " <<
1821  std::get<2> (iter->first) << ", " <<
1822  std::get<3> (iter->first) << ")");
1823  iter = m_dups.erase (iter);
1824  ++n;
1825  }
1826  else
1827  {
1828  ++iter;
1829  }
1830  }
1831 
1832  NS_LOG_DEBUG ("Purged " << n << " expired duplicate entries out of " << (n + m_dups.size ()));
1833 
1834  // keep cleaning up if necessary
1835  if (!m_dups.empty () && m_purge.IsStrictlyPositive ())
1836  {
1838  }
1839 }
1840 
1843 {
1845 
1846  if (m_timeoutEventList.empty ())
1847  {
1849  }
1850  m_timeoutEventList.emplace_back (now, key, ipHeader, iif);
1851 
1853 
1854  return (iter);
1855 }
1856 
1857 void
1859 {
1860  Time now = Simulator::Now ();
1861 
1862  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
1863  {
1864  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
1865  std::get<2> (*m_timeoutEventList.begin ()),
1866  std::get<3> (*m_timeoutEventList.begin ()));
1867  m_timeoutEventList.pop_front ();
1868  }
1869 
1870  if (m_timeoutEventList.empty ())
1871  {
1872  return;
1873  }
1874 
1875  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
1877 
1878  return;
1879 }
1880 
1881 } // namespace ns3
virtual Ipv4Address SourceAddressSelection(uint32_t interface, Ipv4Address dest)
Choose the source address to use with destination address.
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:280
uint8_t GetTos(void) const
Get the tag&#39;s TOS.
Definition: socket.cc:791
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
bool m_weakEsModel
Weak ES model state.
void SetForwarding(bool val)
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
uint64_t GetUid(void) const
Returns the packet&#39;s Uid.
Definition: packet.cc:390
void SetDefaultTtl(uint8_t ttl)
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
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.
void Send(Ptr< Packet > p, const Ipv4Header &hdr, Ipv4Address dest)
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:434
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t GetNAddresses(uint32_t interface) const
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const
Determine whether address and interface corresponding to received packet can be accepted for local de...
virtual void NotifyNewAggregate()
This function will notify other components connected to the node that a new stack member is now conne...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Time m_fragmentExpirationTimeout
Expiration timeout.
Definition: second.py:1
uint32_t GetId(void) const
Definition: node.cc:107
bool IsBroadcast(void) const
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
Introspection did not find any typical Config paths.
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:263
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:142
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:85
static bool ChecksumEnabled(void)
Definition: node.cc:276
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:318
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
The IPv4 representation of a network interface.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
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:227
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:566
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1078
void HandleFragmentsTimeout(FragmentKey_t key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
DupMap_t m_dups
map of packet duplicate tuples to expiry event
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
Definition: ipv4-header.cc:238
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
bool IsStrictlyPositive(void) const
Definition: nstime.h:314
void RemoveDuplicates(void)
Remove duplicate packet entry.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
virtual void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Called by NetDevices, incoming packet.
bool AddAddress(Ipv4InterfaceAddress address)
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
uint32_t AddInterface(Ptr< NetDevice > device)
TracedCallback< const Ipv4Header &, Ptr< const Packet >, DropReason, Ptr< Ipv4 >, uint32_t > m_dropTrace
Trace of dropped packets.
bool IsEntire() const
If all fragments have been added.
static uint8_t IpTos2Priority(uint8_t ipTos)
Return the priority corresponding to a given TOS value.
Definition: socket.cc:402
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address...
virtual int GetProtocolNumber(void) const =0
Returns the protocol number of this protocol.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1115
void SetDontFragment(void)
Don&#39;t fragment this packet: if you need to anyway, drop it.
Definition: ipv4-header.cc:219
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
virtual bool GetIpForward(void) const
Get the IP forwarding state.
bool IsAlive(void)
Definition: arp-cache.cc:375
Ipv4InterfaceAddress GetAddress(uint32_t index) const
Ptr< Ipv4RoutingProtocol > m_routingProtocol
Routing protocol associated with the stack.
uint32_t GetNInterfaces(void) const
void SetUp(uint32_t i)
L4List_t m_protocols
List of transport protocol.
void SetNode(Ptr< Node > node)
Set node associated with interface.
a polymophic address class
Definition: address.h:90
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< Packet > GetPartialPacket() const
Get the complete part of the packet.
bool m_enableDpd
Enable multicast duplicate packet detection.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:449
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
Ipv4InterfaceList m_interfaces
List of IPv4 interfaces.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_rxTrace
Trace of received packets.
Packet header for IPv4.
Definition: ipv4-header.h:33
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
bool IsMulticast(void) const
std::tuple< uint64_t, uint8_t, Ipv4Address, Ipv4Address > DupTuple_t
IETF RFC 6621, Section 6.2 de-duplication w/o IPSec RFC 6621 recommended duplicate packet tuple: {IPV...
void SetLastFragment(void)
This packet is the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:206
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1390
#define max(a, b)
Definition: 80211b.c:43
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
void SetupLoopback(void)
Setup loopback interface.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
AttributeValue implementation for Time.
Definition: nstime.h:1132
bool IsUnicast(Ipv4Address ad) const
Check if an IPv4 address is unicast according to the node.
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
Ptr< Ipv4Interface > GetInterface(uint32_t i) const
Get an interface.
void SetMetric(uint32_t i, uint16_t metric)
virtual void DoDispose(void)
Destructor implementation.
EventId m_cleanDpd
event to cleanup expired duplicate entries
indicates whether the socket has a priority set.
Definition: socket.h:1307
void CallTxTrace(const Ipv4Header &ipHeader, Ptr< Packet > packet, Ptr< Ipv4 > ipv4, uint32_t interface)
Make a copy of the packet, add the header and invoke the TX trace callback.
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
bool IsLocalMulticast(void) const
EventId m_timeoutEvent
Event for the next scheduled timeout.
virtual bool GetWeakEsModel(void) const
Get the Weak Es Model status.
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1610
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
std::pair< uint64_t, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address GetBroadcast(void) const
Get the broadcast address.
MapFragments_t m_fragments
Fragmented packets.
Ipv4Mask GetMask(void) const
Get the network mask.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
void IpForward(Ptr< Ipv4Route > rtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a packet.
Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(void) const
Get the routing protocol to be used by this Ipv4 stack.
#define list
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
Remove the address at addressIndex on named interface.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
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...
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
bool UpdateDuplicate(Ptr< const Packet > p, const Ipv4Header &header)
Registers duplicate entry, return false if new.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
bool m_ipForward
Forwarding packets (i.e.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:464
void SetForwarding(uint32_t i, bool val)
void DoFragmentation(Ptr< Packet > packet, const Ipv4Header &ipv4Header, uint32_t outIfaceMtu, std::list< Ipv4PayloadHeaderPair > &listFragments)
Fragment a packet.
Time m_expire
duplicate entry expiration delay
Implement the IPv4 layer.
Ptr< NetDevice > GetOutputDevice(void) const
Definition: ipv4-route.cc:84
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
address
Definition: first.py:44
uint32_t Hash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer, using the default hash function.
Definition: hash.h:276
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< NetDevice > GetDevice(void) const
void SetMoreFragments(void)
This packet is not the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:200
Ptr< ArpCache > GetArpCache() const
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
std::pair< int, int32_t > L4ListKey_t
Container of the IPv4 L4 keys: protocol number, interface index.
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
Time m_purge
time between purging expired duplicate entries
bool IsForwarding(uint32_t i) const
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.
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:188
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:1133
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, Ipv4Header ipHeader, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:193
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Equivalent in Linux to dst_entry.dev.
Definition: ipv4-route.cc:77
static Ipv4Address GetLoopback(void)
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
static Ipv4Mask GetLoopback(void)
bool IsUp(void) const
These are IP interface states and may be distinct from NetDevice states, such as found in real implem...
Ipv4Address GetGateway(void) const
Definition: ipv4-route.cc:70
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:227
Ptr< NetDevice > GetNetDevice(uint32_t i)
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
void HandleTimeout(void)
Handles a fragmented packet timeout.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:532
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.
uint16_t GetMetric(uint32_t i) const
uint16_t GetMetric(void) const
virtual void Remove(Ptr< IpL4Protocol > protocol)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
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:128
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
a class to store IPv4 address information on an interface
Ptr< Packet > GetPacket() const
Get the entire packet.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
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:265
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
static uint16_t GetStaticProtocolNumber(void)
Get the protocol number.
virtual void Insert(Ptr< IpL4Protocol > protocol)
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
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:1070
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:259
Ipv4InterfaceAddress GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
Because addresses can be removed, the addressIndex is not guaranteed to be static across calls to thi...
void 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.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
bool IsSecondary(void) const
Check if the address is a secondary address.
Ipv4Address GetLocal(void) const
Get the local address.
uint8_t m_defaultTtl
Default TTL.
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:312
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
Ptr< T > CreateObject(void)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:533
Interface is down so can not send packet.
void SetMetric(uint16_t metric)
RxStatus
Rx status codes.
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:300
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
std::list< std::tuple< Time, FragmentKey_t, Ipv4Header, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts..
uint32_t Get(void) const
Get the host-order 32-bit IP address.
uint32_t GetNAddresses(void) const
uint16_t GetMtu(uint32_t i) const
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:296
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
Trace of unicast forwarded packets.
Container for a set of ns3::Object pointers.
This is the implementation of the ICMP protocol as described in RFC 792.
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
void SetPriority(uint8_t priority)
Set the tag&#39;s priority.
Definition: socket.cc:842
Ipv4InterfaceReverseContainer m_reverseInterfacesContainer
Container of NetDevice / Interface index associations.
indicates whether the socket has IP_TOS set.
Definition: socket.h:1261
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
std::map< std::pair< uint64_t, uint8_t >, uint16_t > m_identification
Identification (for each {src, dst, proto} tuple)
Duplicate packet received.
bool IsUp(uint32_t i) const
void SetDown(uint32_t i)
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
virtual Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint8_t GetTtl(void) const
Get the tag&#39;s TTL.
Definition: socket.cc:611
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35
uint32_t GetNDevices(void) const
Definition: node.cc:150
void SetUp(void)
Enable this interface.
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.