A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv6-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) 2007-2009 Strasbourg University
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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/node.h"
23 #include "ns3/uinteger.h"
24 #include "ns3/vector.h"
25 #include "ns3/boolean.h"
26 #include "ns3/callback.h"
27 #include "ns3/trace-source-accessor.h"
28 #include "ns3/object-vector.h"
29 #include "ns3/ipv6-routing-protocol.h"
30 #include "ns3/ipv6-route.h"
31 
32 #include "loopback-net-device.h"
33 #include "ipv6-l3-protocol.h"
34 #include "ipv6-interface.h"
35 #include "ipv6-raw-socket-impl.h"
37 #include "ipv6-extension-demux.h"
38 #include "ipv6-extension.h"
39 #include "ipv6-extension-header.h"
40 #include "ipv6-option-demux.h"
41 #include "ipv6-option.h"
42 #include "icmpv6-l4-protocol.h"
43 #include "ndisc-cache.h"
44 
45 namespace ns3 {
46 
47 NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
48 
49 NS_LOG_COMPONENT_DEFINE ("Ipv6L3Protocol");
50 
51 const uint16_t Ipv6L3Protocol::PROT_NUMBER = 0x86DD;
52 
54 {
55  static TypeId tid = TypeId ("ns3::Ipv6L3Protocol")
56  .SetParent<Ipv6> ()
57  .AddConstructor<Ipv6L3Protocol> ()
58  .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
59  UintegerValue (64),
60  MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTtl),
61  MakeUintegerChecker<uint8_t> ())
62  .AddAttribute ("InterfaceList", "The set of IPv6 interfaces associated to this IPv6 stack.",
65  MakeObjectVectorChecker<Ipv6Interface> ())
66  .AddAttribute ("SendIcmpv6Redirect", "Send the ICMPv6 Redirect when appropriate.",
67  BooleanValue (true),
68  MakeBooleanAccessor (&Ipv6L3Protocol::SetSendIcmpv6Redirect,
70  MakeBooleanChecker ())
71  .AddTraceSource ("Tx", "Send IPv6 packet to outgoing interface.",
73  .AddTraceSource ("Rx", "Receive IPv6 packet from incoming interface.",
75  .AddTraceSource ("Drop", "Drop IPv6 packet",
77  ;
78  return tid;
79 }
80 
82  : m_nInterfaces (0)
83 {
85 }
86 
88 {
90 }
91 
93 {
95 
96  /* clear protocol and interface list */
97  for (L4List_t::iterator it = m_protocols.begin (); it != m_protocols.end (); ++it)
98  {
99  *it = 0;
100  }
101  m_protocols.clear ();
102 
103  /* remove interfaces */
104  for (Ipv6InterfaceList::iterator it = m_interfaces.begin (); it != m_interfaces.end (); ++it)
105  {
106  *it = 0;
107  }
108  m_interfaces.clear ();
109 
110  /* remove raw sockets */
111  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
112  {
113  *it = 0;
114  }
115  m_sockets.clear ();
116 
117  /* remove list of prefix */
118  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
119  {
120  (*it)->StopValidTimer ();
121  (*it)->StopPreferredTimer ();
122  (*it) = 0;
123  }
124  m_prefixes.clear ();
125 
126  m_node = 0;
127  m_routingProtocol = 0;
129 }
130 
132 {
133  NS_LOG_FUNCTION (this << routingProtocol);
134  m_routingProtocol = routingProtocol;
135  m_routingProtocol->SetIpv6 (this);
136 }
137 
139 {
141  return m_routingProtocol;
142 }
143 
145 {
146  NS_LOG_FUNCTION (this << device);
147  Ptr<Node> node = GetObject<Node> ();
148  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
149 
151  interface->SetNode (m_node);
152  interface->SetDevice (device);
153  interface->SetForwarding (m_ipForward);
154  return AddIpv6Interface (interface);
155 }
156 
158 {
159  NS_LOG_FUNCTION (this << interface);
160  uint32_t index = m_nInterfaces;
161 
162  m_interfaces.push_back (interface);
163  m_nInterfaces++;
164  return index;
165 }
166 
168 {
169  NS_LOG_FUNCTION (this << index);
170  uint32_t tmp = 0;
171 
172  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
173  {
174  if (index == tmp)
175  {
176  return *it;
177  }
178  tmp++;
179  }
180  return 0;
181 }
182 
184 {
186  return m_nInterfaces;
187 }
188 
190 {
191  NS_LOG_FUNCTION (this << address);
192  int32_t index = 0;
193 
194  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
195  {
196  uint32_t j = 0;
197  uint32_t max = (*it)->GetNAddresses ();
198 
199  for (j = 0; j < max; j++)
200  {
201  if ((*it)->GetAddress (j).GetAddress () == address)
202  {
203  return index;
204  }
205  }
206  index++;
207  }
208  return -1;
209 }
210 
212 {
213  NS_LOG_FUNCTION (this << address << mask);
214  int32_t index = 0;
215 
216  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
217  {
218  uint32_t j = 0;
219  for (j = 0; j < (*it)->GetNAddresses (); j++)
220  {
221  if ((*it)->GetAddress (j).GetAddress ().CombinePrefix (mask) == address.CombinePrefix (mask))
222  {
223  return index;
224  }
225  }
226  index++;
227  }
228  return -1;
229 }
230 
232 {
233  NS_LOG_FUNCTION (this << i);
234  return GetInterface (i)->GetDevice ();
235 }
236 
238 {
239  NS_LOG_FUNCTION (this << device);
240  int32_t index = 0;
241 
242  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
243  {
244  if ((*it)->GetDevice () == device)
245  {
246  return index;
247  }
248  index++;
249  }
250  return -1;
251 }
252 
253 void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter)
254 {
255  NS_LOG_FUNCTION (this << interface << network << mask << (uint32_t)flags << validTime << preferredTime);
256  Ipv6InterfaceAddress address;
257 
258  Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
259 
260  if (flags & (1 << 6)) /* auto flag */
261  {
262  /* XXX : add other L2 address case */
263  if (Mac48Address::IsMatchingType (addr))
264  {
266  }
267  else
268  {
269  NS_FATAL_ERROR ("Unknown method to make autoconfigured address for this kind of device.");
270  return;
271  }
272 
273  /* see if we have already the prefix */
274  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
275  {
276  if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
277  {
278  (*it)->StopPreferredTimer ();
279  (*it)->StopValidTimer ();
280  (*it)->StartPreferredTimer ();
281  return;
282  }
283  }
284 
285  /* no prefix found, add autoconfigured address and the prefix */
286  NS_LOG_INFO ("Autoconfigured address is :" << address.GetAddress ());
287  AddAddress (interface, address);
288 
289  /* add default router
290  * if a previous default route exists, the new ones is simply added
291  */
292  GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
293 
294  Ptr<Ipv6AutoconfiguredPrefix> aPrefix = CreateObject<Ipv6AutoconfiguredPrefix> (m_node, interface, network, mask, preferredTime, validTime, defaultRouter);
295  aPrefix->StartPreferredTimer ();
296 
297  m_prefixes.push_back (aPrefix);
298  }
299 }
300 
301 void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter)
302 {
303  NS_LOG_FUNCTION (this << interface << network << mask);
304  Ptr<Ipv6Interface> iface = GetInterface (interface);
305  Address addr = iface->GetDevice ()->GetAddress ();
306  uint32_t max = iface->GetNAddresses ();
307  uint32_t i = 0;
309 
310  for (i = 0; i < max; i++)
311  {
312  if (iface->GetAddress (i).GetAddress () == toFound)
313  {
314  RemoveAddress (interface, i);
315  break;
316  }
317  }
318 
319  /* remove from list of autoconfigured address */
320  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
321  {
322  if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
323  {
324  *it = 0;
325  m_prefixes.erase (it);
326  break;
327  }
328  }
329 
330  GetRoutingProtocol ()->NotifyRemoveRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
331 }
332 
334 {
335  NS_LOG_FUNCTION (this << i << address);
336  Ptr<Ipv6Interface> interface = GetInterface (i);
337  bool ret = interface->AddAddress (address);
338 
339  if (m_routingProtocol != 0)
340  {
341  m_routingProtocol->NotifyAddAddress (i, address);
342  }
343  return ret;
344 }
345 
346 uint32_t Ipv6L3Protocol::GetNAddresses (uint32_t i) const
347 {
348  NS_LOG_FUNCTION (this << i);
349  Ptr<Ipv6Interface> interface = GetInterface (i);
350  return interface->GetNAddresses ();
351 }
352 
353 Ipv6InterfaceAddress Ipv6L3Protocol::GetAddress (uint32_t i, uint32_t addressIndex) const
354 {
355  NS_LOG_FUNCTION (this << i << addressIndex);
356  Ptr<Ipv6Interface> interface = GetInterface (i);
357  return interface->GetAddress (addressIndex);
358 }
359 
360 bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
361 {
362  NS_LOG_FUNCTION (this << i << addressIndex);
363  Ptr<Ipv6Interface> interface = GetInterface (i);
364  Ipv6InterfaceAddress address = interface->RemoveAddress (addressIndex);
365 
366  if (address != Ipv6InterfaceAddress ())
367  {
368  if (m_routingProtocol != 0)
369  {
371  }
372  return true;
373  }
374  return false;
375 }
376 
377 void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
378 {
379  NS_LOG_FUNCTION (this << i << metric);
380  Ptr<Ipv6Interface> interface = GetInterface (i);
381  interface->SetMetric (metric);
382 }
383 
384 uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
385 {
386  NS_LOG_FUNCTION (this << i);
387  Ptr<Ipv6Interface> interface = GetInterface (i);
388  return interface->GetMetric ();
389 }
390 
391 uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const
392 {
393  NS_LOG_FUNCTION (this << i);
394  Ptr<Ipv6Interface> interface = GetInterface (i);
395  return interface->GetDevice ()->GetMtu ();
396 }
397 
398 bool Ipv6L3Protocol::IsUp (uint32_t i) const
399 {
400  NS_LOG_FUNCTION (this << i);
401  Ptr<Ipv6Interface> interface = GetInterface (i);
402  return interface->IsUp ();
403 }
404 
405 void Ipv6L3Protocol::SetUp (uint32_t i)
406 {
407  NS_LOG_FUNCTION (this << i);
408  Ptr<Ipv6Interface> interface = GetInterface (i);
409 
410  interface->SetUp ();
411 
412  if (m_routingProtocol != 0)
413  {
415  }
416 }
417 
418 void Ipv6L3Protocol::SetDown (uint32_t i)
419 {
420  NS_LOG_FUNCTION (this << i);
421  Ptr<Ipv6Interface> interface = GetInterface (i);
422 
423  interface->SetDown ();
424 
425  if (m_routingProtocol != 0)
426  {
428  }
429 }
430 
432 {
434  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
435  Ptr<LoopbackNetDevice> device = 0;
436  uint32_t i = 0;
437 
438  /* see if we have already an loopback NetDevice */
439  for (i = 0; i < m_node->GetNDevices (); i++)
440  {
441  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
442  {
443  break;
444  }
445  }
446 
447  if (device == 0)
448  {
449  device = CreateObject<LoopbackNetDevice> ();
450  m_node->AddDevice (device);
451  }
452 
453  interface->SetDevice (device);
454  interface->SetNode (m_node);
456  interface->AddAddress (ifaceAddr);
457  uint32_t index = AddIpv6Interface (interface);
458  Ptr<Node> node = GetObject<Node> ();
460  interface->SetUp ();
461 
462  if (m_routingProtocol != 0)
463  {
465  }
466 }
467 
468 bool Ipv6L3Protocol::IsForwarding (uint32_t i) const
469 {
470  NS_LOG_FUNCTION (this << i);
471  Ptr<Ipv6Interface> interface = GetInterface (i);
472 
473  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
474  return interface->IsForwarding ();
475 }
476 
477 void Ipv6L3Protocol::SetForwarding (uint32_t i, bool val)
478 {
479  NS_LOG_FUNCTION (this << i << val);
480  Ptr<Ipv6Interface> interface = GetInterface (i);
481  interface->SetForwarding (val);
482 }
483 
484 void Ipv6L3Protocol::SetIpForward (bool forward)
485 {
486  NS_LOG_FUNCTION (this << forward);
487  m_ipForward = forward;
488 
489  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
490  {
491  (*it)->SetForwarding (forward);
492  }
493 }
494 
496 {
498  return m_ipForward;
499 }
500 
501 void Ipv6L3Protocol::SetSendIcmpv6Redirect (bool sendIcmpv6Redirect)
502 {
503  NS_LOG_FUNCTION (this << sendIcmpv6Redirect);
504  m_sendIcmpv6Redirect = sendIcmpv6Redirect;
505 }
506 
508 {
510  return m_sendIcmpv6Redirect;
511 }
512 
514 {
516 
517  if (m_node == 0)
518  {
519  Ptr<Node> node = this->GetObject<Node> ();
520  // verify that it's a valid node and that
521  // the node has not been set before
522  if (node != 0)
523  {
524  this->SetNode (node);
525  }
526  }
528 }
529 
531 {
532  NS_LOG_FUNCTION (this << node);
533  m_node = node;
534  /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
535  SetupLoopback ();
536 }
537 
539 {
540  NS_LOG_FUNCTION (this << protocol);
541  m_protocols.push_back (protocol);
542 }
543 
545 {
546  NS_LOG_FUNCTION (this << protocol);
547  m_protocols.remove (protocol);
548 }
549 
551 {
552  NS_LOG_FUNCTION (this << protocolNumber);
553 
554  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
555  {
556  if ((*i)->GetProtocolNumber () == protocolNumber)
557  {
558  return *i;
559  }
560  }
561  return 0;
562 }
563 
565 {
567  Ptr<Ipv6RawSocketImpl> sock = CreateObject<Ipv6RawSocketImpl> ();
568  sock->SetNode (m_node);
569  m_sockets.push_back (sock);
570  return sock;
571 }
572 
574 {
575  NS_LOG_FUNCTION (this << socket);
576 
577  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
578  {
579  if ((*it) == socket)
580  {
581  m_sockets.erase (it);
582  return;
583  }
584  }
585 }
586 
588 {
591 
592  if (protocol)
593  {
594  return protocol->GetObject<Icmpv6L4Protocol> ();
595  }
596  else
597  {
598  return 0;
599  }
600 }
601 
603 {
604  NS_LOG_FUNCTION (this << ttl);
605  m_defaultTtl = ttl;
606 }
607 
608 void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route)
609 {
610  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
611  Ipv6Header hdr;
612  uint8_t ttl = m_defaultTtl;
613  SocketIpTtlTag tag;
614  bool found = packet->RemovePacketTag (tag);
615 
616  if (found)
617  {
618  ttl = tag.GetTtl ();
619  }
620 
621  /* Handle 3 cases:
622  * 1) Packet is passed in with a route entry
623  * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same network)
624  * 3) route is NULL (e.g., a raw socket call or ICMPv6)
625  */
626 
627  /* 1) */
628  if (route && route->GetGateway () != Ipv6Address::GetZero ())
629  {
630  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: passed in with a route");
631  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
632  SendRealOut (route, packet, hdr);
633  return;
634  }
635 
636  /* 2) */
637  if (route && route->GetGateway () == Ipv6Address::GetZero ())
638  {
639  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: probably sent to machine on same IPv6 network");
640  /* NS_FATAL_ERROR ("This case is not yet implemented"); */
641  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
642  SendRealOut (route, packet, hdr);
643  return;
644  }
645 
646  /* 3) */
647  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
649  Ptr<NetDevice> oif (0);
650  Ptr<Ipv6Route> newRoute = 0;
651 
652  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
653 
654  //for link-local traffic, we need to determine the interface
655  if (source.IsLinkLocal ()
656  || destination.IsLinkLocal ()
657  || destination.IsAllNodesMulticast ()
658  || destination.IsAllRoutersMulticast ()
659  || destination.IsAllHostsMulticast ()
660  || destination.IsSolicitedMulticast ())
661  {
662  int32_t index = GetInterfaceForAddress (source);
663  NS_ASSERT (index >= 0);
664  oif = GetNetDevice (index);
665  }
666 
667  newRoute = m_routingProtocol->RouteOutput (packet, hdr, oif, err);
668 
669  if (newRoute)
670  {
671  SendRealOut (newRoute, packet, hdr);
672  }
673  else
674  {
675  NS_LOG_WARN ("No route to host, drop!");
677  }
678 }
679 
680 void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
681 {
682  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
683  NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
684  uint32_t interface = 0;
685  Ptr<Packet> packet = p->Copy ();
686  Ptr<Ipv6Interface> ipv6Interface = 0;
687 
688  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
689  {
690  ipv6Interface = *it;
691 
692  if (ipv6Interface->GetDevice () == device)
693  {
694  if (ipv6Interface->IsUp ())
695  {
696  m_rxTrace (packet, m_node->GetObject<Ipv6> (), interface);
697  break;
698  }
699  else
700  {
701  NS_LOG_LOGIC ("Dropping received packet-- interface is down");
702  Ipv6Header hdr;
703  packet->RemoveHeader (hdr);
704  m_dropTrace (hdr, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
705  return;
706  }
707  }
708  interface++;
709  }
710 
711  Ipv6Header hdr;
712  packet->RemoveHeader (hdr);
713 
714  // Trim any residual frame padding from underlying devices
715  if (hdr.GetPayloadLength () < packet->GetSize ())
716  {
717  packet->RemoveAtEnd (packet->GetSize () - hdr.GetPayloadLength ());
718  }
719 
720  /* forward up to IPv6 raw sockets */
721  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
722  {
723  Ptr<Ipv6RawSocketImpl> socket = *it;
724  socket->ForwardUp (packet, hdr, device);
725  }
726 
728  Ptr<Ipv6Extension> ipv6Extension = 0;
729  uint8_t nextHeader = hdr.GetNextHeader ();
730  bool isDropped = false;
731 
732  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
733  {
734  ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
735 
736  if (ipv6Extension)
737  {
738  ipv6Extension->Process (packet, 0, hdr, hdr.GetDestinationAddress (), (uint8_t *)0, isDropped);
739  }
740 
741  if (isDropped)
742  {
743  return;
744  }
745  }
746 
747  if (!m_routingProtocol->RouteInput (packet, hdr, device,
752  {
753  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
754  m_dropTrace (hdr, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv6> (), interface);
755  }
756 }
757 
759 {
760  NS_LOG_FUNCTION (this << route << packet << ipHeader);
761 
762  if (!route)
763  {
764  NS_LOG_LOGIC ("No route to host, drop!.");
765  return;
766  }
767 
768  Ptr<NetDevice> dev = route->GetOutputDevice ();
769  int32_t interface = GetInterfaceForDevice (dev);
770  NS_ASSERT (interface >= 0);
771 
772  Ptr<Ipv6Interface> outInterface = GetInterface (interface);
773  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
774 
775  // Check packet size
776  std::list<Ptr<Packet> > fragments;
777 
778  if (packet->GetSize () > (size_t)(dev->GetMtu () + 40)) /* 40 => size of IPv6 header */
779  {
780  // Router => drop
781  if (m_ipForward)
782  {
783  Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
784  if ( icmpv6 )
785  {
786  packet->AddHeader(ipHeader);
787  icmpv6->SendErrorTooBig (packet, ipHeader.GetSourceAddress (), dev->GetMtu ());
788  }
789  return;
790  }
791 
793 
794  packet->AddHeader (ipHeader);
795 
796  // To get specific method GetFragments from Ipv6ExtensionFragmentation
797  Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
798  ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments);
799  }
800 
801  if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ()))
802  {
803  if (outInterface->IsUp ())
804  {
805  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
806 
807  if (fragments.size () != 0)
808  {
809  std::ostringstream oss;
810 
811  /* IPv6 header is already added in fragments */
812  for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
813  {
814  m_txTrace (*it, m_node->GetObject<Ipv6> (), interface);
815  outInterface->Send (*it, route->GetGateway ());
816  }
817  }
818  else
819  {
820  packet->AddHeader (ipHeader);
821  m_txTrace (packet, m_node->GetObject<Ipv6> (), interface);
822  outInterface->Send (packet, route->GetGateway ());
823  }
824  }
825  else
826  {
827  NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
828  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
829  }
830  }
831  else
832  {
833  if (outInterface->IsUp ())
834  {
835  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestinationAddress ());
836 
837  if (fragments.size () != 0)
838  {
839  std::ostringstream oss;
840 
841  /* IPv6 header is already added in fragments */
842  for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
843  {
844  m_txTrace (*it, m_node->GetObject<Ipv6> (), interface);
845  outInterface->Send (*it, ipHeader.GetDestinationAddress ());
846  }
847  }
848  else
849  {
850  packet->AddHeader (ipHeader);
851  m_txTrace (packet, m_node->GetObject<Ipv6> (), interface);
852  outInterface->Send (packet, ipHeader.GetDestinationAddress ());
853  }
854  }
855  else
856  {
857  NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestinationAddress ());
858  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
859  }
860  }
861 }
862 
864 {
865  NS_LOG_FUNCTION (this << rtentry << p << header);
866  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
867 
868  // Forwarding
869  Ipv6Header ipHeader = header;
870  Ptr<Packet> packet = p->Copy ();
871  ipHeader.SetHopLimit (ipHeader.GetHopLimit () - 1);
872 
873  if (ipHeader.GetSourceAddress ().IsLinkLocal ())
874  {
875  /* no forward for link-local address */
876  return;
877  }
878 
879  if (ipHeader.GetHopLimit () == 0)
880  {
881  NS_LOG_WARN ("TTL exceeded. Drop.");
882  m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), 0);
883  // Do not reply to ICMPv6 or to multicast IPv6 address
884  if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER
885  && ipHeader.GetDestinationAddress ().IsMulticast () == false)
886  {
887  packet->AddHeader (ipHeader);
888  GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT);
889  }
890  return;
891  }
892 
893  /* ICMPv6 Redirect */
894 
895  /* if we forward to a machine on the same network as the source,
896  * we send him an ICMPv6 redirect message to notify him that a short route
897  * exists.
898  */
899 
900  if (m_sendIcmpv6Redirect &&
901  ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64)))
902  || (rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64)))))
903  {
904  NS_LOG_LOGIC ("ICMPv6 redirect!");
905  Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
906  Address hardwareTarget;
907  Ipv6Address dst = header.GetDestinationAddress ();
908  Ipv6Address src = header.GetSourceAddress ();
909  Ipv6Address target = rtentry->GetGateway ();
910  Ptr<Packet> copy = p->Copy ();
911 
912  if (target.IsAny ())
913  {
914  target = dst;
915  }
916 
917  copy->AddHeader (header);
918 
919  if (icmpv6->Lookup (target, rtentry->GetOutputDevice (), 0, &hardwareTarget))
920  {
921  icmpv6->SendRedirection (copy, src, target, dst, hardwareTarget);
922  }
923  else
924  {
925  icmpv6->SendRedirection (copy, src, target, dst, Address ());
926  }
927  }
928 
929  SendRealOut (rtentry, packet, ipHeader);
930 }
931 
933 {
934  NS_LOG_FUNCTION (this << mrtentry << p << header);
935  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
936 
937  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
938  std::map<uint32_t, uint32_t>::iterator mapIter;
939 
940  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
941  {
942  uint32_t interfaceId = mapIter->first;
943  //uint32_t outputTtl = mapIter->second; // Unused for now
944  Ptr<Packet> packet = p->Copy ();
945  Ipv6Header h = header;
946  h.SetHopLimit (header.GetHopLimit () - 1);
947  if (h.GetHopLimit () == 0)
948  {
949  NS_LOG_WARN ("TTL exceeded. Drop.");
950  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), interfaceId);
951  return;
952  }
953  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
954  Ptr<Ipv6Route> rtentry = Create<Ipv6Route> ();
955  rtentry->SetSource (h.GetSourceAddress ());
956  rtentry->SetDestination (h.GetDestinationAddress ());
957  rtentry->SetGateway (Ipv6Address::GetAny ());
958  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
959  SendRealOut (rtentry, packet, h);
960  continue;
961  }
962 }
963 
964 void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& ip, uint32_t iif)
965 {
966  NS_LOG_FUNCTION (this << packet << ip << iif);
967  Ptr<Packet> p = packet->Copy ();
968  Ptr<IpL4Protocol> protocol = 0;
970  Ptr<Ipv6Extension> ipv6Extension = 0;
971  Ipv6Address src = ip.GetSourceAddress ();
973  uint8_t nextHeader = ip.GetNextHeader ();
974  uint8_t nextHeaderPosition = 0;
975  bool isDropped = false;
976 
977  /* process hop-by-hop extension first if exists */
978  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
979  {
980  uint8_t buf[2];
981  p->CopyData (buf, sizeof(buf));
982  nextHeader = buf[0];
983  nextHeaderPosition = buf[1];
984  NS_ASSERT_MSG (nextHeader != Ipv6Header::IPV6_EXT_HOP_BY_HOP, "Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, aborting");
985  NS_ASSERT_MSG (nextHeaderPosition != 0, "Zero-size IPv6 Option Header, aborting");
986  }
987 
988  /* process all the extensions found and the layer 4 protocol */
989  do
990  {
991  /* it return 0 for non-extension (i.e. layer 4 protocol) */
992  ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
993 
994  if (ipv6Extension)
995  {
996  uint8_t nextHeaderStep = 0;
997  uint8_t curHeader = nextHeader;
998  nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, isDropped);
999  nextHeaderPosition += nextHeaderStep;
1000 
1001  if (isDropped)
1002  {
1003  return;
1004  }
1005  NS_ASSERT_MSG (nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
1006  "Zero-size IPv6 Option Header, aborting" << *packet );
1007  }
1008  else
1009  {
1010  protocol = GetProtocol (nextHeader);
1011  // For ICMPv6 Error packets
1012  Ptr<Packet> malformedPacket = packet->Copy ();
1013  malformedPacket->AddHeader (ip);
1014 
1015  if (!protocol)
1016  {
1017  NS_LOG_LOGIC ("Unknown Next Header. Drop!");
1018 
1019  if (nextHeaderPosition == 0)
1020  {
1021  GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, 40);
1022  }
1023  else
1024  {
1025  GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, ip.GetSerializedSize () + nextHeaderPosition);
1026  }
1028  break;
1029  }
1030  else
1031  {
1032  p->RemoveAtStart (nextHeaderPosition);
1033  /* protocol->Receive (p, src, dst, incomingInterface); */
1034 
1035  /* L4 protocol */
1036  Ptr<Packet> copy = p->Copy ();
1037  enum IpL4Protocol::RxStatus status = protocol->Receive (p, src, dst, GetInterface (iif));
1038 
1039  switch (status)
1040  {
1041  case IpL4Protocol::RX_OK:
1042  break;
1044  break;
1046  break;
1048  if (ip.GetDestinationAddress ().IsMulticast ())
1049  {
1050  /* do not rely on multicast address */
1051  break;
1052  }
1053 
1054  copy->AddHeader (ip);
1055  GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSourceAddress (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
1056  }
1057  }
1058  }
1059  }
1060  while (ipv6Extension);
1061 }
1062 
1064 {
1065  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1066  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1067  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv6> (), 0);
1068 }
1069 
1070 Ipv6Header Ipv6L3Protocol::BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t ttl)
1071 {
1072  NS_LOG_FUNCTION (this << src << dst << (uint32_t)protocol << (uint32_t)payloadSize << (uint32_t)ttl);
1073  Ipv6Header hdr;
1074 
1075  hdr.SetSourceAddress (src);
1076  hdr.SetDestinationAddress (dst);
1077  hdr.SetNextHeader (protocol);
1078  hdr.SetPayloadLength (payloadSize);
1079  hdr.SetHopLimit (ttl);
1080  return hdr;
1081 }
1082 
1084 {
1085  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = CreateObject<Ipv6ExtensionDemux> ();
1086  ipv6ExtensionDemux->SetNode (m_node);
1087 
1088  Ptr<Ipv6ExtensionHopByHop> hopbyhopExtension = CreateObject<Ipv6ExtensionHopByHop> ();
1089  hopbyhopExtension->SetNode (m_node);
1090  Ptr<Ipv6ExtensionDestination> destinationExtension = CreateObject<Ipv6ExtensionDestination> ();
1091  destinationExtension->SetNode (m_node);
1092  Ptr<Ipv6ExtensionFragment> fragmentExtension = CreateObject<Ipv6ExtensionFragment> ();
1093  fragmentExtension->SetNode (m_node);
1094  Ptr<Ipv6ExtensionRouting> routingExtension = CreateObject<Ipv6ExtensionRouting> ();
1095  routingExtension->SetNode (m_node);
1096  // Ptr<Ipv6ExtensionESP> espExtension = CreateObject<Ipv6ExtensionESP> ();
1097  // Ptr<Ipv6ExtensionAH> ahExtension = CreateObject<Ipv6ExtensionAH> ();
1098 
1099  ipv6ExtensionDemux->Insert (hopbyhopExtension);
1100  ipv6ExtensionDemux->Insert (destinationExtension);
1101  ipv6ExtensionDemux->Insert (fragmentExtension);
1102  ipv6ExtensionDemux->Insert (routingExtension);
1103  // ipv6ExtensionDemux->Insert (espExtension);
1104  // ipv6ExtensionDemux->Insert (ahExtension);
1105 
1106  Ptr<Ipv6ExtensionRoutingDemux> routingExtensionDemux = CreateObject<Ipv6ExtensionRoutingDemux> ();
1107  routingExtensionDemux->SetNode (m_node);
1108  Ptr<Ipv6ExtensionLooseRouting> looseRoutingExtension = CreateObject<Ipv6ExtensionLooseRouting> ();
1109  looseRoutingExtension->SetNode (m_node);
1110  routingExtensionDemux->Insert (looseRoutingExtension);
1111 
1112  m_node->AggregateObject (routingExtensionDemux);
1113  m_node->AggregateObject (ipv6ExtensionDemux);
1114 }
1115 
1117 {
1118  Ptr<Ipv6OptionDemux> ipv6OptionDemux = CreateObject<Ipv6OptionDemux> ();
1119  ipv6OptionDemux->SetNode (m_node);
1120 
1121  Ptr<Ipv6OptionPad1> pad1Option = CreateObject<Ipv6OptionPad1> ();
1122  pad1Option->SetNode (m_node);
1123  Ptr<Ipv6OptionPadn> padnOption = CreateObject<Ipv6OptionPadn> ();
1124  padnOption->SetNode (m_node);
1125  Ptr<Ipv6OptionJumbogram> jumbogramOption = CreateObject<Ipv6OptionJumbogram> ();
1126  jumbogramOption->SetNode (m_node);
1127  Ptr<Ipv6OptionRouterAlert> routerAlertOption = CreateObject<Ipv6OptionRouterAlert> ();
1128  routerAlertOption->SetNode (m_node);
1129 
1130  ipv6OptionDemux->Insert (pad1Option);
1131  ipv6OptionDemux->Insert (padnOption);
1132  ipv6OptionDemux->Insert (jumbogramOption);
1133  ipv6OptionDemux->Insert (routerAlertOption);
1134 
1135  m_node->AggregateObject (ipv6OptionDemux);
1136 }
1137 
1138 } /* namespace ns3 */
1139