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 #include "ns3/mac16-address.h"
32 #include "ns3/mac64-address.h"
33 
34 #include "loopback-net-device.h"
35 #include "ipv6-l3-protocol.h"
36 #include "ipv6-interface.h"
37 #include "ipv6-raw-socket-impl.h"
39 #include "ipv6-extension-demux.h"
40 #include "ipv6-extension.h"
41 #include "ipv6-extension-header.h"
42 #include "ipv6-option-demux.h"
43 #include "ipv6-option.h"
44 #include "icmpv6-l4-protocol.h"
45 #include "ndisc-cache.h"
46 
48 #define IPV6_MIN_MTU 1280
49 
50 namespace ns3 {
51 
52 NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
53 
54 NS_LOG_COMPONENT_DEFINE ("Ipv6L3Protocol");
55 
56 const uint16_t Ipv6L3Protocol::PROT_NUMBER = 0x86DD;
57 
59 {
60  static TypeId tid = TypeId ("ns3::Ipv6L3Protocol")
61  .SetParent<Ipv6> ()
62  .AddConstructor<Ipv6L3Protocol> ()
63  .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
64  UintegerValue (64),
65  MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTtl),
66  MakeUintegerChecker<uint8_t> ())
67  .AddAttribute ("DefaultTclass", "The TCLASS value set by default on all outgoing packets generated on this node.",
68  UintegerValue (0),
69  MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTclass),
70  MakeUintegerChecker<uint8_t> ())
71  .AddAttribute ("InterfaceList", "The set of IPv6 interfaces associated to this IPv6 stack.",
74  MakeObjectVectorChecker<Ipv6Interface> ())
75  .AddAttribute ("SendIcmpv6Redirect", "Send the ICMPv6 Redirect when appropriate.",
76  BooleanValue (true),
77  MakeBooleanAccessor (&Ipv6L3Protocol::SetSendIcmpv6Redirect,
79  MakeBooleanChecker ())
80  .AddTraceSource ("Tx", "Send IPv6 packet to outgoing interface.",
82  .AddTraceSource ("Rx", "Receive IPv6 packet from incoming interface.",
84  .AddTraceSource ("Drop", "Drop IPv6 packet",
86  ;
87  return tid;
88 }
89 
91  : m_nInterfaces (0)
92 {
94  m_pmtuCache = CreateObject<Ipv6PmtuCache> ();
95 }
96 
98 {
100 }
101 
103 {
105 
106  /* clear protocol and interface list */
107  for (L4List_t::iterator it = m_protocols.begin (); it != m_protocols.end (); ++it)
108  {
109  *it = 0;
110  }
111  m_protocols.clear ();
112 
113  /* remove interfaces */
114  for (Ipv6InterfaceList::iterator it = m_interfaces.begin (); it != m_interfaces.end (); ++it)
115  {
116  *it = 0;
117  }
118  m_interfaces.clear ();
119 
120  /* remove raw sockets */
121  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
122  {
123  *it = 0;
124  }
125  m_sockets.clear ();
126 
127  /* remove list of prefix */
128  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
129  {
130  (*it)->StopValidTimer ();
131  (*it)->StopPreferredTimer ();
132  (*it) = 0;
133  }
134  m_prefixes.clear ();
135 
136  m_node = 0;
137  m_routingProtocol = 0;
138  m_pmtuCache = 0;
140 }
141 
143 {
144  NS_LOG_FUNCTION (this << routingProtocol);
145  m_routingProtocol = routingProtocol;
146  m_routingProtocol->SetIpv6 (this);
147 }
148 
150 {
152  return m_routingProtocol;
153 }
154 
156 {
157  NS_LOG_FUNCTION (this << device);
158  Ptr<Node> node = GetObject<Node> ();
159  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
160 
162  interface->SetNode (m_node);
163  interface->SetDevice (device);
164  interface->SetForwarding (m_ipForward);
165  return AddIpv6Interface (interface);
166 }
167 
169 {
170  NS_LOG_FUNCTION (this << interface);
171  uint32_t index = m_nInterfaces;
172 
173  m_interfaces.push_back (interface);
174  m_nInterfaces++;
175  return index;
176 }
177 
179 {
180  NS_LOG_FUNCTION (this << index);
181  uint32_t tmp = 0;
182 
183  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
184  {
185  if (index == tmp)
186  {
187  return *it;
188  }
189  tmp++;
190  }
191  return 0;
192 }
193 
195 {
197  return m_nInterfaces;
198 }
199 
201 {
202  NS_LOG_FUNCTION (this << address);
203  int32_t index = 0;
204 
205  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
206  {
207  uint32_t j = 0;
208  uint32_t max = (*it)->GetNAddresses ();
209 
210  for (j = 0; j < max; j++)
211  {
212  if ((*it)->GetAddress (j).GetAddress () == address)
213  {
214  return index;
215  }
216  }
217  index++;
218  }
219  return -1;
220 }
221 
223 {
224  NS_LOG_FUNCTION (this << address << mask);
225  int32_t index = 0;
226 
227  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
228  {
229  uint32_t j = 0;
230  for (j = 0; j < (*it)->GetNAddresses (); j++)
231  {
232  if ((*it)->GetAddress (j).GetAddress ().CombinePrefix (mask) == address.CombinePrefix (mask))
233  {
234  return index;
235  }
236  }
237  index++;
238  }
239  return -1;
240 }
241 
243 {
244  NS_LOG_FUNCTION (this << i);
245  return GetInterface (i)->GetDevice ();
246 }
247 
249 {
250  NS_LOG_FUNCTION (this << device);
251  int32_t index = 0;
252 
253  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
254  {
255  if ((*it)->GetDevice () == device)
256  {
257  return index;
258  }
259  index++;
260  }
261  return -1;
262 }
263 
264 void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter)
265 {
266  NS_LOG_FUNCTION (this << interface << network << mask << (uint32_t)flags << validTime << preferredTime);
268 
269  Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
270 
271  if (flags & (1 << 6)) /* auto flag */
272  {
273  // In case of new MacAddress types, remember to change Ipv6L3Protocol::RemoveAutoconfiguredAddress as well
274  if (Mac64Address::IsMatchingType (addr))
275  {
277  }
278  else if (Mac48Address::IsMatchingType (addr))
279  {
281  }
282  else if (Mac16Address::IsMatchingType (addr))
283  {
285  }
286  else
287  {
288  NS_FATAL_ERROR ("Unknown method to make autoconfigured address for this kind of device.");
289  return;
290  }
291 
292  /* see if we have already the prefix */
293  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
294  {
295  if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
296  {
297  (*it)->StopPreferredTimer ();
298  (*it)->StopValidTimer ();
299  (*it)->StartPreferredTimer ();
300  return;
301  }
302  }
303 
304  /* no prefix found, add autoconfigured address and the prefix */
305  NS_LOG_INFO ("Autoconfigured address is :" << address.GetAddress ());
306  AddAddress (interface, address);
307 
308  /* add default router
309  * if a previous default route exists, the new ones is simply added
310  */
311  if (!defaultRouter.IsAny())
312  {
313  GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
314  }
315 
316  Ptr<Ipv6AutoconfiguredPrefix> aPrefix = CreateObject<Ipv6AutoconfiguredPrefix> (m_node, interface, network, mask, preferredTime, validTime, defaultRouter);
317  aPrefix->StartPreferredTimer ();
318 
319  m_prefixes.push_back (aPrefix);
320  }
321 }
322 
323 void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter)
324 {
325  NS_LOG_FUNCTION (this << interface << network << mask);
326  Ptr<Ipv6Interface> iface = GetInterface (interface);
327  Address addr = iface->GetDevice ()->GetAddress ();
328  uint32_t max = iface->GetNAddresses ();
329  uint32_t i = 0;
330  Ipv6Address toFound;
331 
332  if (Mac64Address::IsMatchingType (addr))
333  {
335  }
336  else if (Mac48Address::IsMatchingType (addr))
337  {
339  }
340  else if (Mac16Address::IsMatchingType (addr))
341  {
343  }
344  else
345  {
346  NS_FATAL_ERROR ("Unknown method to make autoconfigured address for this kind of device.");
347  return;
348  }
349 
350  for (i = 0; i < max; i++)
351  {
352  if (iface->GetAddress (i).GetAddress () == toFound)
353  {
354  RemoveAddress (interface, i);
355  break;
356  }
357  }
358 
359  /* remove from list of autoconfigured address */
360  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
361  {
362  if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
363  {
364  *it = 0;
365  m_prefixes.erase (it);
366  break;
367  }
368  }
369 
370  GetRoutingProtocol ()->NotifyRemoveRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
371 }
372 
374 {
375  NS_LOG_FUNCTION (this << i << address);
376  Ptr<Ipv6Interface> interface = GetInterface (i);
377  bool ret = interface->AddAddress (address);
378 
379  if (m_routingProtocol != 0)
380  {
381  m_routingProtocol->NotifyAddAddress (i, address);
382  }
383  return ret;
384 }
385 
386 uint32_t Ipv6L3Protocol::GetNAddresses (uint32_t i) const
387 {
388  NS_LOG_FUNCTION (this << i);
389  Ptr<Ipv6Interface> interface = GetInterface (i);
390  return interface->GetNAddresses ();
391 }
392 
393 Ipv6InterfaceAddress Ipv6L3Protocol::GetAddress (uint32_t i, uint32_t addressIndex) const
394 {
395  NS_LOG_FUNCTION (this << i << addressIndex);
396  Ptr<Ipv6Interface> interface = GetInterface (i);
397  return interface->GetAddress (addressIndex);
398 }
399 
400 bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
401 {
402  NS_LOG_FUNCTION (this << i << addressIndex);
403  Ptr<Ipv6Interface> interface = GetInterface (i);
404  Ipv6InterfaceAddress address = interface->RemoveAddress (addressIndex);
405 
406  if (address != Ipv6InterfaceAddress ())
407  {
408  if (m_routingProtocol != 0)
409  {
411  }
412  return true;
413  }
414  return false;
415 }
416 
417 bool
419 {
420  NS_LOG_FUNCTION (this << i << address);
421 
422  if (address == Ipv6Address::GetLoopback())
423  {
424  NS_LOG_WARN ("Cannot remove loopback address.");
425  return false;
426  }
427  Ptr<Ipv6Interface> interface = GetInterface (i);
428  Ipv6InterfaceAddress ifAddr = interface->RemoveAddress (address);
429  if (ifAddr != Ipv6InterfaceAddress ())
430  {
431  if (m_routingProtocol != 0)
432  {
434  }
435  return true;
436  }
437  return false;
438 }
439 
440 void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
441 {
442  NS_LOG_FUNCTION (this << i << metric);
443  Ptr<Ipv6Interface> interface = GetInterface (i);
444  interface->SetMetric (metric);
445 }
446 
447 uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
448 {
449  NS_LOG_FUNCTION (this << i);
450  Ptr<Ipv6Interface> interface = GetInterface (i);
451  return interface->GetMetric ();
452 }
453 
454 uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const
455 {
456  NS_LOG_FUNCTION (this << i);
457 
458  // RFC 1981, if PMTU is disabled, return the minimum MTU
459  if (!m_mtuDiscover)
460  {
461  return IPV6_MIN_MTU;
462  }
463 
464  Ptr<Ipv6Interface> interface = GetInterface (i);
465  return interface->GetDevice ()->GetMtu ();
466 }
467 
468 void Ipv6L3Protocol::SetPmtu (Ipv6Address dst, uint32_t pmtu)
469 {
470  NS_LOG_FUNCTION (this << dst << int(pmtu));
471  m_pmtuCache->SetPmtu (dst, pmtu);
472 }
473 
474 
475 bool Ipv6L3Protocol::IsUp (uint32_t i) const
476 {
477  NS_LOG_FUNCTION (this << i);
478  Ptr<Ipv6Interface> interface = GetInterface (i);
479  return interface->IsUp ();
480 }
481 
482 void Ipv6L3Protocol::SetUp (uint32_t i)
483 {
484  NS_LOG_FUNCTION (this << i);
485  Ptr<Ipv6Interface> interface = GetInterface (i);
486 
487  interface->SetUp ();
488 
489  if (m_routingProtocol != 0)
490  {
492  }
493 }
494 
495 void Ipv6L3Protocol::SetDown (uint32_t i)
496 {
497  NS_LOG_FUNCTION (this << i);
498  Ptr<Ipv6Interface> interface = GetInterface (i);
499 
500  interface->SetDown ();
501 
502  if (m_routingProtocol != 0)
503  {
505  }
506 }
507 
509 {
511  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
512  Ptr<LoopbackNetDevice> device = 0;
513  uint32_t i = 0;
514 
515  /* see if we have already an loopback NetDevice */
516  for (i = 0; i < m_node->GetNDevices (); i++)
517  {
518  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
519  {
520  break;
521  }
522  }
523 
524  if (device == 0)
525  {
526  device = CreateObject<LoopbackNetDevice> ();
527  m_node->AddDevice (device);
528  }
529 
530  interface->SetDevice (device);
531  interface->SetNode (m_node);
533  interface->AddAddress (ifaceAddr);
534  uint32_t index = AddIpv6Interface (interface);
535  Ptr<Node> node = GetObject<Node> ();
537  interface->SetUp ();
538 
539  if (m_routingProtocol != 0)
540  {
542  }
543 }
544 
545 bool Ipv6L3Protocol::IsForwarding (uint32_t i) const
546 {
547  NS_LOG_FUNCTION (this << i);
548  Ptr<Ipv6Interface> interface = GetInterface (i);
549 
550  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
551  return interface->IsForwarding ();
552 }
553 
554 void Ipv6L3Protocol::SetForwarding (uint32_t i, bool val)
555 {
556  NS_LOG_FUNCTION (this << i << val);
557  Ptr<Ipv6Interface> interface = GetInterface (i);
558  interface->SetForwarding (val);
559 }
560 
561 void Ipv6L3Protocol::SetIpForward (bool forward)
562 {
563  NS_LOG_FUNCTION (this << forward);
564  m_ipForward = forward;
565 
566  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
567  {
568  (*it)->SetForwarding (forward);
569  }
570 }
571 
573 {
575  return m_ipForward;
576 }
577 
578 void Ipv6L3Protocol::SetMtuDiscover (bool mtuDiscover)
579 {
580  NS_LOG_FUNCTION (this << int(mtuDiscover));
581  m_mtuDiscover = mtuDiscover;
582 }
583 
585 {
586  NS_LOG_FUNCTION (this);
587  return m_mtuDiscover;
588 }
589 
590 void Ipv6L3Protocol::SetSendIcmpv6Redirect (bool sendIcmpv6Redirect)
591 {
592  NS_LOG_FUNCTION (this << sendIcmpv6Redirect);
593  m_sendIcmpv6Redirect = sendIcmpv6Redirect;
594 }
595 
597 {
599  return m_sendIcmpv6Redirect;
600 }
601 
603 {
605 
606  if (m_node == 0)
607  {
608  Ptr<Node> node = this->GetObject<Node> ();
609  // verify that it's a valid node and that
610  // the node has not been set before
611  if (node != 0)
612  {
613  this->SetNode (node);
614  }
615  }
617 }
618 
620 {
621  NS_LOG_FUNCTION (this << node);
622  m_node = node;
623  /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
624  SetupLoopback ();
625 }
626 
628 {
629  NS_LOG_FUNCTION (this << protocol);
630  m_protocols.push_back (protocol);
631 }
632 
634 {
635  NS_LOG_FUNCTION (this << protocol);
636  m_protocols.remove (protocol);
637 }
638 
640 {
641  NS_LOG_FUNCTION (this << protocolNumber);
642 
643  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
644  {
645  if ((*i)->GetProtocolNumber () == protocolNumber)
646  {
647  return *i;
648  }
649  }
650  return 0;
651 }
652 
654 {
656  Ptr<Ipv6RawSocketImpl> sock = CreateObject<Ipv6RawSocketImpl> ();
657  sock->SetNode (m_node);
658  m_sockets.push_back (sock);
659  return sock;
660 }
661 
663 {
664  NS_LOG_FUNCTION (this << socket);
665 
666  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
667  {
668  if ((*it) == socket)
669  {
670  m_sockets.erase (it);
671  return;
672  }
673  }
674 }
675 
677 {
680 
681  if (protocol)
682  {
683  return protocol->GetObject<Icmpv6L4Protocol> ();
684  }
685  else
686  {
687  return 0;
688  }
689 }
690 
692 {
693  NS_LOG_FUNCTION (this << ttl);
694  m_defaultTtl = ttl;
695 }
696 
697 void Ipv6L3Protocol::SetDefaultTclass (uint8_t tclass)
698 {
699  NS_LOG_FUNCTION (this << tclass);
700  m_defaultTclass = tclass;
701 }
702 
703 void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route)
704 {
705  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
706  Ipv6Header hdr;
707  uint8_t ttl = m_defaultTtl;
709  bool found = packet->RemovePacketTag (tag);
710 
711  if (found)
712  {
713  ttl = tag.GetHopLimit ();
714  }
715 
716  SocketIpv6TclassTag tclassTag;
717  uint8_t tclass = m_defaultTclass;
718  found = packet->RemovePacketTag (tclassTag);
719 
720  if (found)
721  {
722  tclass = tclassTag.GetTclass ();
723  }
724 
725  /* Handle 3 cases:
726  * 1) Packet is passed in with a route entry
727  * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same network)
728  * 3) route is NULL (e.g., a raw socket call or ICMPv6)
729  */
730 
731  /* 1) */
732  if (route && route->GetGateway () != Ipv6Address::GetZero ())
733  {
734  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: passed in with a route");
735  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
736  SendRealOut (route, packet, hdr);
737  return;
738  }
739 
740  /* 2) */
741  if (route && route->GetGateway () == Ipv6Address::GetZero ())
742  {
743  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: probably sent to machine on same IPv6 network");
744  /* NS_FATAL_ERROR ("This case is not yet implemented"); */
745  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
746  SendRealOut (route, packet, hdr);
747  return;
748  }
749 
750  /* 3) */
751  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
753  Ptr<NetDevice> oif (0);
754  Ptr<Ipv6Route> newRoute = 0;
755 
756  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
757 
758  //for link-local traffic, we need to determine the interface
759  if (source.IsLinkLocal ()
760  || destination.IsLinkLocal ()
761  || destination.IsAllNodesMulticast ()
762  || destination.IsAllRoutersMulticast ()
763  || destination.IsAllHostsMulticast ()
764  || destination.IsSolicitedMulticast ())
765  {
766  int32_t index = GetInterfaceForAddress (source);
767  NS_ASSERT (index >= 0);
768  oif = GetNetDevice (index);
769  }
770 
771  newRoute = m_routingProtocol->RouteOutput (packet, hdr, oif, err);
772 
773  if (newRoute)
774  {
775  SendRealOut (newRoute, packet, hdr);
776  }
777  else
778  {
779  NS_LOG_WARN ("No route to host, drop!");
781  }
782 }
783 
784 void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
785 {
786  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
787  NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
788  uint32_t interface = 0;
789  Ptr<Packet> packet = p->Copy ();
790  Ptr<Ipv6Interface> ipv6Interface = 0;
791 
792  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
793  {
794  ipv6Interface = *it;
795 
796  if (ipv6Interface->GetDevice () == device)
797  {
798  if (ipv6Interface->IsUp ())
799  {
800  m_rxTrace (packet, m_node->GetObject<Ipv6> (), interface);
801  break;
802  }
803  else
804  {
805  NS_LOG_LOGIC ("Dropping received packet-- interface is down");
806  Ipv6Header hdr;
807  packet->RemoveHeader (hdr);
808  m_dropTrace (hdr, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
809  return;
810  }
811  }
812  interface++;
813  }
814 
815  Ipv6Header hdr;
816  packet->RemoveHeader (hdr);
817 
818  // Trim any residual frame padding from underlying devices
819  if (hdr.GetPayloadLength () < packet->GetSize ())
820  {
821  packet->RemoveAtEnd (packet->GetSize () - hdr.GetPayloadLength ());
822  }
823 
824  /* forward up to IPv6 raw sockets */
825  for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
826  {
827  Ptr<Ipv6RawSocketImpl> socket = *it;
828  socket->ForwardUp (packet, hdr, device);
829  }
830 
832  Ptr<Ipv6Extension> ipv6Extension = 0;
833  uint8_t nextHeader = hdr.GetNextHeader ();
834  bool isDropped = false;
835 
836  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
837  {
838  ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
839 
840  if (ipv6Extension)
841  {
842  ipv6Extension->Process (packet, 0, hdr, hdr.GetDestinationAddress (), (uint8_t *)0, isDropped);
843  }
844 
845  if (isDropped)
846  {
847  return;
848  }
849  }
850 
851  if (!m_routingProtocol->RouteInput (packet, hdr, device,
856  {
857  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
858  m_dropTrace (hdr, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv6> (), interface);
859  }
860 }
861 
863 {
864  NS_LOG_FUNCTION (this << route << packet << ipHeader);
865 
866  if (!route)
867  {
868  NS_LOG_LOGIC ("No route to host, drop!.");
869  return;
870  }
871 
872  Ptr<NetDevice> dev = route->GetOutputDevice ();
873  int32_t interface = GetInterfaceForDevice (dev);
874  NS_ASSERT (interface >= 0);
875 
876  Ptr<Ipv6Interface> outInterface = GetInterface (interface);
877  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
878 
879  // Check packet size
880  std::list<Ptr<Packet> > fragments;
881 
882  // Check if we have a Path MTU stored. If so, use it. Else, use the link MTU.
883  size_t targetMtu = (size_t)(m_pmtuCache->GetPmtu (ipHeader.GetDestinationAddress()));
884  if (targetMtu == 0)
885  {
886  targetMtu = dev->GetMtu ();
887  }
888 
889  if (packet->GetSize () > targetMtu + 40) /* 40 => size of IPv6 header */
890  {
891  // Router => drop
892 
893  bool fromMe = false;
894  for (uint32_t i=0; i<GetNInterfaces(); i++ )
895  {
896  for (uint32_t j=0; j<GetNAddresses(i); j++ )
897  {
898  if (GetAddress(i,j).GetAddress() == ipHeader.GetSourceAddress())
899  {
900  fromMe = true;
901  break;
902  }
903  }
904  }
905  if (!fromMe)
906  {
907  Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
908  if ( icmpv6 )
909  {
910  packet->AddHeader(ipHeader);
911  icmpv6->SendErrorTooBig (packet, ipHeader.GetSourceAddress (), dev->GetMtu ());
912  }
913  return;
914  }
915 
917 
918  packet->AddHeader (ipHeader);
919 
920  // To get specific method GetFragments from Ipv6ExtensionFragmentation
921  Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
922  NS_ASSERT (ipv6Fragment != 0);
923  ipv6Fragment->GetFragments (packet, targetMtu, fragments);
924  }
925 
926  if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ()))
927  {
928  if (outInterface->IsUp ())
929  {
930  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
931 
932  if (fragments.size () != 0)
933  {
934  std::ostringstream oss;
935 
936  /* IPv6 header is already added in fragments */
937  for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
938  {
939  m_txTrace (*it, m_node->GetObject<Ipv6> (), interface);
940  outInterface->Send (*it, route->GetGateway ());
941  }
942  }
943  else
944  {
945  packet->AddHeader (ipHeader);
946  m_txTrace (packet, m_node->GetObject<Ipv6> (), interface);
947  outInterface->Send (packet, route->GetGateway ());
948  }
949  }
950  else
951  {
952  NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
953  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
954  }
955  }
956  else
957  {
958  if (outInterface->IsUp ())
959  {
960  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestinationAddress ());
961 
962  if (fragments.size () != 0)
963  {
964  std::ostringstream oss;
965 
966  /* IPv6 header is already added in fragments */
967  for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
968  {
969  m_txTrace (*it, m_node->GetObject<Ipv6> (), interface);
970  outInterface->Send (*it, ipHeader.GetDestinationAddress ());
971  }
972  }
973  else
974  {
975  packet->AddHeader (ipHeader);
976  m_txTrace (packet, m_node->GetObject<Ipv6> (), interface);
977  outInterface->Send (packet, ipHeader.GetDestinationAddress ());
978  }
979  }
980  else
981  {
982  NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestinationAddress ());
983  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
984  }
985  }
986 }
987 
989 {
990  NS_LOG_FUNCTION (this << rtentry << p << header);
991  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
992 
993  // Drop RFC 3849 packets: 2001:db8::/32
994  if (header.GetDestinationAddress().IsDocumentation())
995  {
996  NS_LOG_WARN ("Received a packet for 2001:db8::/32 (documentation class). Drop.");
997  m_dropTrace (header, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv6> (), 0);
998  return;
999  }
1000 
1001  // Forwarding
1002  Ipv6Header ipHeader = header;
1003  Ptr<Packet> packet = p->Copy ();
1004  ipHeader.SetHopLimit (ipHeader.GetHopLimit () - 1);
1005 
1006  if (ipHeader.GetSourceAddress ().IsLinkLocal ())
1007  {
1008  /* no forward for link-local address */
1009  return;
1010  }
1011 
1012  if (ipHeader.GetHopLimit () == 0)
1013  {
1014  NS_LOG_WARN ("TTL exceeded. Drop.");
1015  m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), 0);
1016  // Do not reply to ICMPv6 or to multicast IPv6 address
1017  if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER
1018  && ipHeader.GetDestinationAddress ().IsMulticast () == false)
1019  {
1020  packet->AddHeader (ipHeader);
1021  GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT);
1022  }
1023  return;
1024  }
1025 
1026  /* ICMPv6 Redirect */
1027 
1028  /* if we forward to a machine on the same network as the source,
1029  * we send him an ICMPv6 redirect message to notify him that a short route
1030  * exists.
1031  */
1032 
1033  /* Theoretically we should also check if the redirect target is on the same network
1034  * as the source node. On the other hand, we are sure that the router we're redirecting to
1035  * used a link-local address. As a consequence, they MUST be on the same network, the link-local net.
1036  */
1037 
1038  if (m_sendIcmpv6Redirect && (rtentry->GetOutputDevice ()==idev))
1039  {
1040  NS_LOG_LOGIC ("ICMPv6 redirect!");
1041  Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
1042  Address hardwareTarget;
1043  Ipv6Address dst = header.GetDestinationAddress ();
1044  Ipv6Address src = header.GetSourceAddress ();
1045  Ipv6Address target = rtentry->GetGateway ();
1046  Ptr<Packet> copy = p->Copy ();
1047 
1048  if (target.IsAny ())
1049  {
1050  target = dst;
1051  }
1052 
1053  copy->AddHeader (header);
1054  Ipv6Address linkLocal = GetInterface (GetInterfaceForDevice (rtentry->GetOutputDevice ()))->GetLinkLocalAddress ().GetAddress ();
1055 
1056  if (icmpv6->Lookup (target, rtentry->GetOutputDevice (), 0, &hardwareTarget))
1057  {
1058  icmpv6->SendRedirection (copy, linkLocal, src, target, dst, hardwareTarget);
1059  }
1060  else
1061  {
1062  icmpv6->SendRedirection (copy, linkLocal, src, target, dst, Address ());
1063  }
1064  }
1065 
1066  SendRealOut (rtentry, packet, ipHeader);
1067 }
1068 
1070 {
1071  NS_LOG_FUNCTION (this << mrtentry << p << header);
1072  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
1073 
1074  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
1075  std::map<uint32_t, uint32_t>::iterator mapIter;
1076 
1077  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
1078  {
1079  uint32_t interfaceId = mapIter->first;
1080  //uint32_t outputTtl = mapIter->second; // Unused for now
1081  Ptr<Packet> packet = p->Copy ();
1082  Ipv6Header h = header;
1083  h.SetHopLimit (header.GetHopLimit () - 1);
1084  if (h.GetHopLimit () == 0)
1085  {
1086  NS_LOG_WARN ("TTL exceeded. Drop.");
1087  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), interfaceId);
1088  return;
1089  }
1090  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
1091  Ptr<Ipv6Route> rtentry = Create<Ipv6Route> ();
1092  rtentry->SetSource (h.GetSourceAddress ());
1093  rtentry->SetDestination (h.GetDestinationAddress ());
1094  rtentry->SetGateway (Ipv6Address::GetAny ());
1095  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
1096  SendRealOut (rtentry, packet, h);
1097  continue;
1098  }
1099 }
1100 
1101 void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& ip, uint32_t iif)
1102 {
1103  NS_LOG_FUNCTION (this << packet << ip << iif);
1104  Ptr<Packet> p = packet->Copy ();
1105  Ptr<IpL4Protocol> protocol = 0;
1106  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
1107  Ptr<Ipv6Extension> ipv6Extension = 0;
1108  Ipv6Address src = ip.GetSourceAddress ();
1109  Ipv6Address dst = ip.GetDestinationAddress ();
1110  uint8_t nextHeader = ip.GetNextHeader ();
1111  uint8_t nextHeaderPosition = 0;
1112  bool isDropped = false;
1113 
1114  // check for a malformed hop-by-hop extension
1115  // this is a common case when forging IPv6 raw packets
1116  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1117  {
1118  uint8_t buf;
1119  p->CopyData (&buf, 1);
1121  {
1122  NS_LOG_WARN("Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, dropping packet");
1123  return;
1124  }
1125  }
1126 
1127  /* process all the extensions found and the layer 4 protocol */
1128  do
1129  {
1130  /* it return 0 for non-extension (i.e. layer 4 protocol) */
1131  ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
1132 
1133  if (ipv6Extension)
1134  {
1135  uint8_t nextHeaderStep = 0;
1136  uint8_t curHeader = nextHeader;
1137  nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, isDropped);
1138  nextHeaderPosition += nextHeaderStep;
1139 
1140  if (isDropped)
1141  {
1142  return;
1143  }
1144  NS_ASSERT_MSG (nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
1145  "Zero-size IPv6 Option Header, aborting" << *packet );
1146  }
1147  else
1148  {
1149  protocol = GetProtocol (nextHeader);
1150  // For ICMPv6 Error packets
1151  Ptr<Packet> malformedPacket = packet->Copy ();
1152  malformedPacket->AddHeader (ip);
1153 
1154  if (!protocol)
1155  {
1156  NS_LOG_LOGIC ("Unknown Next Header. Drop!");
1157 
1158  if (nextHeaderPosition == 0)
1159  {
1160  GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, 40);
1161  }
1162  else
1163  {
1164  GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, ip.GetSerializedSize () + nextHeaderPosition);
1165  }
1167  break;
1168  }
1169  else
1170  {
1171  p->RemoveAtStart (nextHeaderPosition);
1172  /* protocol->Receive (p, src, dst, incomingInterface); */
1173 
1174  /* L4 protocol */
1175  Ptr<Packet> copy = p->Copy ();
1176  enum IpL4Protocol::RxStatus status = protocol->Receive (p, ip, GetInterface (iif));
1177 
1178  switch (status)
1179  {
1180  case IpL4Protocol::RX_OK:
1181  break;
1183  break;
1185  break;
1187  if (ip.GetDestinationAddress ().IsMulticast ())
1188  {
1189  /* do not rely on multicast address */
1190  break;
1191  }
1192 
1193  copy->AddHeader (ip);
1194  GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSourceAddress (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
1195  }
1196  }
1197  }
1198  }
1199  while (ipv6Extension);
1200 }
1201 
1203 {
1204  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1205  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1206  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv6> (), 0);
1207 }
1208 
1209 Ipv6Header Ipv6L3Protocol::BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t ttl, uint8_t tclass)
1210 {
1211  NS_LOG_FUNCTION (this << src << dst << (uint32_t)protocol << (uint32_t)payloadSize << (uint32_t)ttl << (uint32_t)tclass);
1212  Ipv6Header hdr;
1213 
1214  hdr.SetSourceAddress (src);
1215  hdr.SetDestinationAddress (dst);
1216  hdr.SetNextHeader (protocol);
1217  hdr.SetPayloadLength (payloadSize);
1218  hdr.SetHopLimit (ttl);
1219  hdr.SetTrafficClass (tclass);
1220  return hdr;
1221 }
1222 
1224 {
1225  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = CreateObject<Ipv6ExtensionDemux> ();
1226  ipv6ExtensionDemux->SetNode (m_node);
1227 
1228  Ptr<Ipv6ExtensionHopByHop> hopbyhopExtension = CreateObject<Ipv6ExtensionHopByHop> ();
1229  hopbyhopExtension->SetNode (m_node);
1230  Ptr<Ipv6ExtensionDestination> destinationExtension = CreateObject<Ipv6ExtensionDestination> ();
1231  destinationExtension->SetNode (m_node);
1232  Ptr<Ipv6ExtensionFragment> fragmentExtension = CreateObject<Ipv6ExtensionFragment> ();
1233  fragmentExtension->SetNode (m_node);
1234  Ptr<Ipv6ExtensionRouting> routingExtension = CreateObject<Ipv6ExtensionRouting> ();
1235  routingExtension->SetNode (m_node);
1236  // Ptr<Ipv6ExtensionESP> espExtension = CreateObject<Ipv6ExtensionESP> ();
1237  // Ptr<Ipv6ExtensionAH> ahExtension = CreateObject<Ipv6ExtensionAH> ();
1238 
1239  ipv6ExtensionDemux->Insert (hopbyhopExtension);
1240  ipv6ExtensionDemux->Insert (destinationExtension);
1241  ipv6ExtensionDemux->Insert (fragmentExtension);
1242  ipv6ExtensionDemux->Insert (routingExtension);
1243  // ipv6ExtensionDemux->Insert (espExtension);
1244  // ipv6ExtensionDemux->Insert (ahExtension);
1245 
1246  Ptr<Ipv6ExtensionRoutingDemux> routingExtensionDemux = CreateObject<Ipv6ExtensionRoutingDemux> ();
1247  routingExtensionDemux->SetNode (m_node);
1248  Ptr<Ipv6ExtensionLooseRouting> looseRoutingExtension = CreateObject<Ipv6ExtensionLooseRouting> ();
1249  looseRoutingExtension->SetNode (m_node);
1250  routingExtensionDemux->Insert (looseRoutingExtension);
1251 
1252  m_node->AggregateObject (routingExtensionDemux);
1253  m_node->AggregateObject (ipv6ExtensionDemux);
1254 }
1255 
1257 {
1258  Ptr<Ipv6OptionDemux> ipv6OptionDemux = CreateObject<Ipv6OptionDemux> ();
1259  ipv6OptionDemux->SetNode (m_node);
1260 
1261  Ptr<Ipv6OptionPad1> pad1Option = CreateObject<Ipv6OptionPad1> ();
1262  pad1Option->SetNode (m_node);
1263  Ptr<Ipv6OptionPadn> padnOption = CreateObject<Ipv6OptionPadn> ();
1264  padnOption->SetNode (m_node);
1265  Ptr<Ipv6OptionJumbogram> jumbogramOption = CreateObject<Ipv6OptionJumbogram> ();
1266  jumbogramOption->SetNode (m_node);
1267  Ptr<Ipv6OptionRouterAlert> routerAlertOption = CreateObject<Ipv6OptionRouterAlert> ();
1268  routerAlertOption->SetNode (m_node);
1269 
1270  ipv6OptionDemux->Insert (pad1Option);
1271  ipv6OptionDemux->Insert (padnOption);
1272  ipv6OptionDemux->Insert (jumbogramOption);
1273  ipv6OptionDemux->Insert (routerAlertOption);
1274 
1275  m_node->AggregateObject (ipv6OptionDemux);
1276 }
1277 
1278 } /* namespace ns3 */
1279