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 #include "ns3/traffic-control-layer.h"
34 
35 #include "loopback-net-device.h"
36 #include "ipv6-l3-protocol.h"
37 #include "ipv6-interface.h"
38 #include "ipv6-raw-socket-impl.h"
39 #include "ipv6-autoconfigured-prefix.h"
40 #include "ipv6-extension-demux.h"
41 #include "ipv6-extension.h"
42 #include "ipv6-extension-header.h"
43 #include "ipv6-option-demux.h"
44 #include "ipv6-option.h"
45 #include "icmpv6-l4-protocol.h"
46 #include "ndisc-cache.h"
47 #include "ipv6-raw-socket-factory-impl.h"
48 
49 /// Minimum IPv6 MTU, as defined by \RFC{2460}
50 #define IPV6_MIN_MTU 1280
51 
52 namespace ns3 {
53 
54 NS_LOG_COMPONENT_DEFINE ("Ipv6L3Protocol");
55 
56 NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
57 
58 const uint16_t Ipv6L3Protocol::PROT_NUMBER = 0x86DD;
59 
GetTypeId()60 TypeId Ipv6L3Protocol::GetTypeId ()
61 {
62   static TypeId tid = TypeId ("ns3::Ipv6L3Protocol")
63     .SetParent<Ipv6> ()
64     .SetGroupName ("Internet")
65     .AddConstructor<Ipv6L3Protocol> ()
66     .AddAttribute ("DefaultTtl",
67                    "The TTL value set by default on all "
68                    "outgoing packets generated on this node.",
69                    UintegerValue (64),
70                    MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTtl),
71                    MakeUintegerChecker<uint8_t> ())
72     .AddAttribute ("DefaultTclass",
73                    "The TCLASS value set by default on all "
74                    "outgoing packets generated on this node.",
75                    UintegerValue (0),
76                    MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTclass),
77                    MakeUintegerChecker<uint8_t> ())
78     .AddAttribute ("InterfaceList",
79                    "The set of IPv6 interfaces associated to this IPv6 stack.",
80                    ObjectVectorValue (),
81                    MakeObjectVectorAccessor (&Ipv6L3Protocol::m_interfaces),
82                    MakeObjectVectorChecker<Ipv6Interface> ())
83     .AddAttribute ("SendIcmpv6Redirect",
84                    "Send the ICMPv6 Redirect when appropriate.",
85                    BooleanValue (true),
86                    MakeBooleanAccessor (&Ipv6L3Protocol::SetSendIcmpv6Redirect,
87                                         &Ipv6L3Protocol::GetSendIcmpv6Redirect),
88                    MakeBooleanChecker ())
89     .AddAttribute ("StrongEndSystemModel",
90                    "Reject packets for an address not configured on the interface they're coming from (RFC1222).",
91                    BooleanValue (true),
92                    MakeBooleanAccessor (&Ipv6L3Protocol::m_strongEndSystemModel),
93                    MakeBooleanChecker ())
94     .AddTraceSource ("Tx",
95                      "Send IPv6 packet to outgoing interface.",
96                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_txTrace),
97                      "ns3::Ipv6L3Protocol::TxRxTracedCallback")
98     .AddTraceSource ("Rx",
99                      "Receive IPv6 packet from incoming interface.",
100                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_rxTrace),
101                      "ns3::Ipv6L3Protocol::TxRxTracedCallback")
102     .AddTraceSource ("Drop",
103                      "Drop IPv6 packet",
104                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_dropTrace),
105                      "ns3::Ipv6L3Protocol::DropTracedCallback")
106 
107     .AddTraceSource ("SendOutgoing",
108                      "A newly-generated packet by this node is "
109                      "about to be queued for transmission",
110                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_sendOutgoingTrace),
111                      "ns3::Ipv6L3Protocol::SentTracedCallback")
112     .AddTraceSource ("UnicastForward",
113                      "A unicast IPv6 packet was received by this node "
114                      "and is being forwarded to another node",
115                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_unicastForwardTrace),
116                      "ns3::Ipv6L3Protocol::SentTracedCallback")
117     .AddTraceSource ("LocalDeliver",
118                      "An IPv6 packet was received by/for this node, "
119                      "and it is being forward up the stack",
120                      MakeTraceSourceAccessor (&Ipv6L3Protocol::m_localDeliverTrace),
121                      "ns3::Ipv6L3Protocol::SentTracedCallback")
122   ;
123   return tid;
124 }
125 
Ipv6L3Protocol()126 Ipv6L3Protocol::Ipv6L3Protocol ()
127   : m_nInterfaces (0)
128 {
129   NS_LOG_FUNCTION (this);
130   m_pmtuCache = CreateObject<Ipv6PmtuCache> ();
131 
132   Ptr<Ipv6RawSocketFactoryImpl> rawFactoryImpl = CreateObject<Ipv6RawSocketFactoryImpl> ();
133   AggregateObject (rawFactoryImpl);
134 }
135 
~Ipv6L3Protocol()136 Ipv6L3Protocol::~Ipv6L3Protocol ()
137 {
138   NS_LOG_FUNCTION (this);
139 }
140 
DoDispose()141 void Ipv6L3Protocol::DoDispose ()
142 {
143   NS_LOG_FUNCTION (this);
144 
145   /* clear protocol and interface list */
146   for (L4List_t::iterator it = m_protocols.begin (); it != m_protocols.end (); ++it)
147     {
148       it->second = 0;
149     }
150   m_protocols.clear ();
151 
152   /* remove interfaces */
153   for (Ipv6InterfaceList::iterator it = m_interfaces.begin (); it != m_interfaces.end (); ++it)
154     {
155       *it = 0;
156     }
157   m_interfaces.clear ();
158   m_reverseInterfacesContainer.clear ();
159 
160   /* remove raw sockets */
161   for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
162     {
163       *it = 0;
164     }
165   m_sockets.clear ();
166 
167   /* remove list of prefix */
168   for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
169     {
170       (*it)->StopValidTimer ();
171       (*it)->StopPreferredTimer ();
172       (*it) = 0;
173     }
174   m_prefixes.clear ();
175 
176   m_node = 0;
177   m_routingProtocol = 0;
178   m_pmtuCache = 0;
179   Object::DoDispose ();
180 }
181 
SetRoutingProtocol(Ptr<Ipv6RoutingProtocol> routingProtocol)182 void Ipv6L3Protocol::SetRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol)
183 {
184   NS_LOG_FUNCTION (this << routingProtocol);
185   m_routingProtocol = routingProtocol;
186   m_routingProtocol->SetIpv6 (this);
187 }
188 
GetRoutingProtocol() const189 Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const
190 {
191   NS_LOG_FUNCTION (this);
192   return m_routingProtocol;
193 }
194 
AddInterface(Ptr<NetDevice> device)195 uint32_t Ipv6L3Protocol::AddInterface (Ptr<NetDevice> device)
196 {
197   NS_LOG_FUNCTION (this << device);
198   Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
199 
200   Ptr<TrafficControlLayer> tc = m_node->GetObject<TrafficControlLayer> ();
201 
202   NS_ASSERT (tc != 0);
203 
204   m_node->RegisterProtocolHandler (MakeCallback (&TrafficControlLayer::Receive, tc),
205                                    Ipv6L3Protocol::PROT_NUMBER, device);
206 
207   tc->RegisterProtocolHandler (MakeCallback (&Ipv6L3Protocol::Receive, this),
208                                Ipv6L3Protocol::PROT_NUMBER, device);
209 
210   interface->SetNode (m_node);
211   interface->SetDevice (device);
212   interface->SetTrafficControl (tc);
213   interface->SetForwarding (m_ipForward);
214   return AddIpv6Interface (interface);
215 }
216 
AddIpv6Interface(Ptr<Ipv6Interface> interface)217 uint32_t Ipv6L3Protocol::AddIpv6Interface (Ptr<Ipv6Interface> interface)
218 {
219   NS_LOG_FUNCTION (this << interface);
220   uint32_t index = m_nInterfaces;
221 
222   m_interfaces.push_back (interface);
223   m_reverseInterfacesContainer[interface->GetDevice ()] = index;
224   m_nInterfaces++;
225   return index;
226 }
227 
GetInterface(uint32_t index) const228 Ptr<Ipv6Interface> Ipv6L3Protocol::GetInterface (uint32_t index) const
229 {
230   NS_LOG_FUNCTION (this << index);
231 
232   if (index < m_interfaces.size ())
233     {
234       return m_interfaces[index];
235     }
236   return 0;
237 }
238 
GetNInterfaces() const239 uint32_t Ipv6L3Protocol::GetNInterfaces () const
240 {
241   NS_LOG_FUNCTION (this);
242   return m_nInterfaces;
243 }
244 
GetInterfaceForAddress(Ipv6Address address) const245 int32_t Ipv6L3Protocol::GetInterfaceForAddress (Ipv6Address address) const
246 {
247   NS_LOG_FUNCTION (this << address);
248   int32_t index = 0;
249 
250   for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
251     {
252       uint32_t j = 0;
253       uint32_t max = (*it)->GetNAddresses ();
254 
255       for (j = 0; j < max; j++)
256         {
257           if ((*it)->GetAddress (j).GetAddress () == address)
258             {
259               return index;
260             }
261         }
262       index++;
263     }
264   return -1;
265 }
266 
GetInterfaceForPrefix(Ipv6Address address,Ipv6Prefix mask) const267 int32_t Ipv6L3Protocol::GetInterfaceForPrefix (Ipv6Address address, Ipv6Prefix mask) const
268 {
269   NS_LOG_FUNCTION (this << address << mask);
270   int32_t index = 0;
271 
272   for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
273     {
274       uint32_t j = 0;
275       for (j = 0; j < (*it)->GetNAddresses (); j++)
276         {
277           if ((*it)->GetAddress (j).GetAddress ().CombinePrefix (mask) == address.CombinePrefix (mask))
278             {
279               return index;
280             }
281         }
282       index++;
283     }
284   return -1;
285 }
286 
GetNetDevice(uint32_t i)287 Ptr<NetDevice> Ipv6L3Protocol::GetNetDevice (uint32_t i)
288 {
289   NS_LOG_FUNCTION (this << i);
290   return GetInterface (i)->GetDevice ();
291 }
292 
GetInterfaceForDevice(Ptr<const NetDevice> device) const293 int32_t Ipv6L3Protocol::GetInterfaceForDevice (Ptr<const NetDevice> device) const
294 {
295   NS_LOG_FUNCTION (this << device);
296 
297   Ipv6InterfaceReverseContainer::const_iterator iter = m_reverseInterfacesContainer.find (device);
298   if (iter != m_reverseInterfacesContainer.end ())
299     {
300       return (*iter).second;
301     }
302 
303   return -1;
304 }
305 
AddAutoconfiguredAddress(uint32_t interface,Ipv6Address network,Ipv6Prefix mask,uint8_t flags,uint32_t validTime,uint32_t preferredTime,Ipv6Address defaultRouter)306 void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter)
307 {
308   NS_LOG_FUNCTION (this << interface << network << mask << (uint32_t)flags << validTime << preferredTime);
309   Ipv6InterfaceAddress address;
310 
311   Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
312 
313   if (!defaultRouter.IsAny())
314     {
315       GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
316     }
317 
318   bool onLink = false;
319   if (flags & Icmpv6OptionPrefixInformation::ONLINK)
320     {
321       onLink = true;
322     }
323 
324   if (flags & Icmpv6OptionPrefixInformation::AUTADDRCONF) /* auto flag */
325     {
326       address = Ipv6Address::MakeAutoconfiguredAddress (addr, network);
327       address.SetOnLink (onLink);
328 
329       /* see if we have already the prefix */
330       for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
331         {
332           if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
333             {
334               (*it)->StopPreferredTimer ();
335               (*it)->StopValidTimer ();
336               (*it)->StartPreferredTimer ();
337               return;
338             }
339         }
340 
341       /* no prefix found, add autoconfigured address and the prefix */
342       NS_LOG_INFO ("Autoconfigured address is :" << address.GetAddress ());
343       AddAddress (interface, address, onLink);
344 
345       Ptr<Ipv6AutoconfiguredPrefix> aPrefix = CreateObject<Ipv6AutoconfiguredPrefix> (m_node, interface, network, mask, preferredTime, validTime, defaultRouter);
346       aPrefix->StartPreferredTimer ();
347 
348       m_prefixes.push_back (aPrefix);
349     }
350 
351   if (onLink) /* on-link flag */
352     {
353       /* add default router
354        * if a previous default route exists, the new ones is simply added
355        */
356       m_routingProtocol->NotifyAddRoute (network, mask, Ipv6Address::GetAny (), interface);
357     }
358 }
359 
RemoveAutoconfiguredAddress(uint32_t interface,Ipv6Address network,Ipv6Prefix mask,Ipv6Address defaultRouter)360 void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter)
361 {
362   NS_LOG_FUNCTION (this << interface << network << mask);
363   Ptr<Ipv6Interface> iface = GetInterface (interface);
364   Address addr = iface->GetDevice ()->GetAddress ();
365 
366   Ipv6Address addressToFind = Ipv6Address::MakeAutoconfiguredAddress (addr, network);
367 
368   for (uint32_t i = 0; i < iface->GetNAddresses (); i++)
369     {
370       if (iface->GetAddress (i).GetAddress () == addressToFind)
371         {
372           RemoveAddress (interface, i);
373           break;
374         }
375     }
376 
377   /* remove from list of autoconfigured address */
378   for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin (); it != m_prefixes.end (); ++it)
379     {
380       if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
381         {
382           *it = 0;
383           m_prefixes.erase (it);
384           break;
385         }
386     }
387 
388   GetRoutingProtocol ()->NotifyRemoveRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
389 }
390 
AddAddress(uint32_t i,Ipv6InterfaceAddress address,bool addOnLinkRoute)391 bool Ipv6L3Protocol::AddAddress (uint32_t i, Ipv6InterfaceAddress address, bool addOnLinkRoute)
392 {
393   NS_LOG_FUNCTION (this << i << address);
394   Ptr<Ipv6Interface> interface = GetInterface (i);
395   address.SetOnLink (addOnLinkRoute);
396   bool ret = interface->AddAddress (address);
397 
398   if (m_routingProtocol != 0)
399     {
400       m_routingProtocol->NotifyAddAddress (i, address);
401     }
402 
403   if (addOnLinkRoute)
404     {
405       Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
406       Ipv6Prefix networkMask = address.GetPrefix ();
407       GetRoutingProtocol ()->NotifyAddRoute (networkAddress, networkMask, Ipv6Address::GetZero (), i);
408     }
409   return ret;
410 }
411 
GetNAddresses(uint32_t i) const412 uint32_t Ipv6L3Protocol::GetNAddresses (uint32_t i) const
413 {
414   NS_LOG_FUNCTION (this << i);
415   Ptr<Ipv6Interface> interface = GetInterface (i);
416   return interface->GetNAddresses ();
417 }
418 
GetAddress(uint32_t i,uint32_t addressIndex) const419 Ipv6InterfaceAddress Ipv6L3Protocol::GetAddress (uint32_t i, uint32_t addressIndex) const
420 {
421   NS_LOG_FUNCTION (this << i << addressIndex);
422   Ptr<Ipv6Interface> interface = GetInterface (i);
423   return interface->GetAddress (addressIndex);
424 }
425 
RemoveAddress(uint32_t i,uint32_t addressIndex)426 bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
427 {
428   NS_LOG_FUNCTION (this << i << addressIndex);
429   Ptr<Ipv6Interface> interface = GetInterface (i);
430   Ipv6InterfaceAddress address = interface->RemoveAddress (addressIndex);
431 
432   if (address != Ipv6InterfaceAddress ())
433     {
434       if (m_routingProtocol != 0)
435         {
436           m_routingProtocol->NotifyRemoveAddress (i, address);
437         }
438       return true;
439     }
440   return false;
441 }
442 
443 bool
RemoveAddress(uint32_t i,Ipv6Address address)444 Ipv6L3Protocol::RemoveAddress (uint32_t i, Ipv6Address address)
445 {
446   NS_LOG_FUNCTION (this << i << address);
447 
448   if (address == Ipv6Address::GetLoopback())
449     {
450       NS_LOG_WARN ("Cannot remove loopback address.");
451       return false;
452     }
453   Ptr<Ipv6Interface> interface = GetInterface (i);
454   Ipv6InterfaceAddress ifAddr = interface->RemoveAddress (address);
455   if (ifAddr != Ipv6InterfaceAddress ())
456   {
457     if (m_routingProtocol != 0)
458     {
459       m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
460     }
461     return true;
462   }
463   return false;
464 }
465 
SetMetric(uint32_t i,uint16_t metric)466 void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
467 {
468   NS_LOG_FUNCTION (this << i << metric);
469   Ptr<Ipv6Interface> interface = GetInterface (i);
470   interface->SetMetric (metric);
471 }
472 
GetMetric(uint32_t i) const473 uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
474 {
475   NS_LOG_FUNCTION (this << i);
476   Ptr<Ipv6Interface> interface = GetInterface (i);
477   return interface->GetMetric ();
478 }
479 
GetMtu(uint32_t i) const480 uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const
481 {
482   NS_LOG_FUNCTION (this << i);
483 
484   // RFC 1981, if PMTU is disabled, return the minimum MTU
485   if (!m_mtuDiscover)
486     {
487       return IPV6_MIN_MTU;
488     }
489 
490   Ptr<Ipv6Interface> interface = GetInterface (i);
491   return interface->GetDevice ()->GetMtu ();
492 }
493 
SetPmtu(Ipv6Address dst,uint32_t pmtu)494 void Ipv6L3Protocol::SetPmtu (Ipv6Address dst, uint32_t pmtu)
495 {
496   NS_LOG_FUNCTION (this << dst << int(pmtu));
497   m_pmtuCache->SetPmtu (dst, pmtu);
498 }
499 
500 
IsUp(uint32_t i) const501 bool Ipv6L3Protocol::IsUp (uint32_t i) const
502 {
503   NS_LOG_FUNCTION (this << i);
504   Ptr<Ipv6Interface> interface = GetInterface (i);
505   return interface->IsUp ();
506 }
507 
SetUp(uint32_t i)508 void Ipv6L3Protocol::SetUp (uint32_t i)
509 {
510   NS_LOG_FUNCTION (this << i);
511   Ptr<Ipv6Interface> interface = GetInterface (i);
512 
513   // RFC 2460, Section 5, pg. 24:
514   //  IPv6 requires that every link in the internet have an MTU of 1280
515   //  octets or greater.  On any link that cannot convey a 1280-octet
516   //  packet in one piece, link-specific fragmentation and reassembly must
517   //  be provided at a layer below IPv6.
518   if (interface->GetDevice ()->GetMtu () >= 1280)
519     {
520       interface->SetUp ();
521 
522       if (m_routingProtocol != 0)
523         {
524           m_routingProtocol->NotifyInterfaceUp (i);
525         }
526     }
527   else
528     {
529       NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv6. Reason: not respecting minimum IPv6 MTU (1280 octets)");
530     }
531 }
532 
SetDown(uint32_t i)533 void Ipv6L3Protocol::SetDown (uint32_t i)
534 {
535   NS_LOG_FUNCTION (this << i);
536   Ptr<Ipv6Interface> interface = GetInterface (i);
537 
538   interface->SetDown ();
539 
540   if (m_routingProtocol != 0)
541     {
542       m_routingProtocol->NotifyInterfaceDown (i);
543     }
544 }
545 
SetupLoopback()546 void Ipv6L3Protocol::SetupLoopback ()
547 {
548   NS_LOG_FUNCTION (this);
549   Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
550   Ptr<LoopbackNetDevice> device = 0;
551   uint32_t i = 0;
552 
553   /* see if we have already an loopback NetDevice */
554   for (i = 0; i < m_node->GetNDevices (); i++)
555     {
556       if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
557         {
558           break;
559         }
560     }
561 
562   if (device == 0)
563     {
564       device = CreateObject<LoopbackNetDevice> ();
565       m_node->AddDevice (device);
566     }
567 
568   interface->SetDevice (device);
569   interface->SetNode (m_node);
570   Ipv6InterfaceAddress ifaceAddr = Ipv6InterfaceAddress (Ipv6Address::GetLoopback (), Ipv6Prefix (128));
571   interface->AddAddress (ifaceAddr);
572   uint32_t index = AddIpv6Interface (interface);
573   Ptr<Node> node = GetObject<Node> ();
574   node->RegisterProtocolHandler (MakeCallback (&Ipv6L3Protocol::Receive, this), Ipv6L3Protocol::PROT_NUMBER, device);
575   interface->SetUp ();
576 
577   if (m_routingProtocol != 0)
578     {
579       m_routingProtocol->NotifyInterfaceUp (index);
580     }
581 }
582 
IsForwarding(uint32_t i) const583 bool Ipv6L3Protocol::IsForwarding (uint32_t i) const
584 {
585   NS_LOG_FUNCTION (this << i);
586   Ptr<Ipv6Interface> interface = GetInterface (i);
587 
588   NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
589   return interface->IsForwarding ();
590 }
591 
SetForwarding(uint32_t i,bool val)592 void Ipv6L3Protocol::SetForwarding (uint32_t i, bool val)
593 {
594   NS_LOG_FUNCTION (this << i << val);
595   Ptr<Ipv6Interface> interface = GetInterface (i);
596   interface->SetForwarding (val);
597 }
598 
SourceAddressSelection(uint32_t interface,Ipv6Address dest)599 Ipv6Address Ipv6L3Protocol::SourceAddressSelection (uint32_t interface, Ipv6Address dest)
600 {
601   NS_LOG_FUNCTION (this << interface << dest);
602   Ipv6Address ret;
603 
604   if (dest.IsLinkLocal () || dest.IsLinkLocalMulticast ())
605     {
606       for (uint32_t i = 0; i < GetNAddresses (interface); i++)
607         {
608           Ipv6InterfaceAddress test = GetAddress (interface, i);
609           if (test.GetScope () == Ipv6InterfaceAddress::LINKLOCAL)
610             {
611               return test.GetAddress ();
612             }
613         }
614       NS_ASSERT_MSG (false, "No link-local address found on interface " << interface);
615     }
616 
617   for (uint32_t i = 0; i < GetNAddresses (interface); i++)
618     {
619       Ipv6InterfaceAddress test = GetAddress (interface, i);
620 
621       if (test.GetScope () == Ipv6InterfaceAddress::GLOBAL)
622         {
623           if (test.IsInSameSubnet (dest))
624             {
625               return test.GetAddress ();
626             }
627           else
628             {
629               ret = test.GetAddress ();
630             }
631         }
632     }
633 
634   // no specific match found. Use a global address (any useful is fine).
635   return ret;
636 }
637 
SetIpForward(bool forward)638 void Ipv6L3Protocol::SetIpForward (bool forward)
639 {
640   NS_LOG_FUNCTION (this << forward);
641   m_ipForward = forward;
642 
643   for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
644     {
645       (*it)->SetForwarding (forward);
646     }
647 }
648 
GetIpForward() const649 bool Ipv6L3Protocol::GetIpForward () const
650 {
651   NS_LOG_FUNCTION (this);
652   return m_ipForward;
653 }
654 
SetMtuDiscover(bool mtuDiscover)655 void Ipv6L3Protocol::SetMtuDiscover (bool mtuDiscover)
656 {
657   NS_LOG_FUNCTION (this << int(mtuDiscover));
658   m_mtuDiscover = mtuDiscover;
659 }
660 
GetMtuDiscover() const661 bool Ipv6L3Protocol::GetMtuDiscover () const
662 {
663   NS_LOG_FUNCTION (this);
664   return m_mtuDiscover;
665 }
666 
SetSendIcmpv6Redirect(bool sendIcmpv6Redirect)667 void Ipv6L3Protocol::SetSendIcmpv6Redirect (bool sendIcmpv6Redirect)
668 {
669   NS_LOG_FUNCTION (this << sendIcmpv6Redirect);
670   m_sendIcmpv6Redirect = sendIcmpv6Redirect;
671 }
672 
GetSendIcmpv6Redirect() const673 bool Ipv6L3Protocol::GetSendIcmpv6Redirect () const
674 {
675   NS_LOG_FUNCTION (this);
676   return m_sendIcmpv6Redirect;
677 }
678 
NotifyNewAggregate()679 void Ipv6L3Protocol::NotifyNewAggregate ()
680 {
681   NS_LOG_FUNCTION (this);
682 
683   if (m_node == 0)
684     {
685       Ptr<Node> node = this->GetObject<Node> ();
686       // verify that it's a valid node and that
687       // the node has not been set before
688       if (node != 0)
689         {
690           this->SetNode (node);
691         }
692     }
693 
694   Ipv6::NotifyNewAggregate ();
695 }
696 
SetNode(Ptr<Node> node)697 void Ipv6L3Protocol::SetNode (Ptr<Node> node)
698 {
699   NS_LOG_FUNCTION (this << node);
700   m_node = node;
701   /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
702   SetupLoopback ();
703 }
704 
Insert(Ptr<IpL4Protocol> protocol)705 void Ipv6L3Protocol::Insert (Ptr<IpL4Protocol> protocol)
706 {
707   NS_LOG_FUNCTION (this << protocol);
708   L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
709   if (m_protocols.find (key) != m_protocols.end ())
710     {
711       NS_LOG_WARN ("Overwriting default protocol " << int(protocol->GetProtocolNumber ()));
712     }
713   m_protocols[key] = protocol;
714 }
715 
Insert(Ptr<IpL4Protocol> protocol,uint32_t interfaceIndex)716 void Ipv6L3Protocol::Insert (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
717 {
718   NS_LOG_FUNCTION (this << protocol << interfaceIndex);
719 
720   L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
721   if (m_protocols.find (key) != m_protocols.end ())
722     {
723       NS_LOG_WARN ("Overwriting protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
724     }
725   m_protocols[key] = protocol;
726 }
727 
Remove(Ptr<IpL4Protocol> protocol)728 void Ipv6L3Protocol::Remove (Ptr<IpL4Protocol> protocol)
729 {
730   NS_LOG_FUNCTION (this << protocol);
731 
732   L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
733   L4List_t::iterator iter = m_protocols.find (key);
734   if (iter == m_protocols.end ())
735     {
736       NS_LOG_WARN ("Trying to remove an non-existent default protocol " << int(protocol->GetProtocolNumber ()));
737     }
738   else
739     {
740       m_protocols.erase (key);
741     }
742 }
743 
Remove(Ptr<IpL4Protocol> protocol,uint32_t interfaceIndex)744 void Ipv6L3Protocol::Remove (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
745 {
746   NS_LOG_FUNCTION (this << protocol << interfaceIndex);
747 
748   L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
749   L4List_t::iterator iter = m_protocols.find (key);
750   if (iter == m_protocols.end ())
751     {
752       NS_LOG_WARN ("Trying to remove an non-existent protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
753     }
754   else
755     {
756       m_protocols.erase (key);
757     }
758 }
759 
GetProtocol(int protocolNumber) const760 Ptr<IpL4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
761 {
762   NS_LOG_FUNCTION (this << protocolNumber);
763 
764   return GetProtocol (protocolNumber, -1);
765 }
766 
GetProtocol(int protocolNumber,int32_t interfaceIndex) const767 Ptr<IpL4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber, int32_t interfaceIndex) const
768 {
769   NS_LOG_FUNCTION (this << protocolNumber << interfaceIndex);
770 
771   L4ListKey_t key;
772   L4List_t::const_iterator i;
773   if (interfaceIndex >= 0)
774     {
775       // try the interface-specific protocol.
776       key = std::make_pair (protocolNumber, interfaceIndex);
777       i = m_protocols.find (key);
778       if (i != m_protocols.end ())
779         {
780           return i->second;
781         }
782     }
783   // try the generic protocol.
784   key = std::make_pair (protocolNumber, -1);
785   i = m_protocols.find (key);
786   if (i != m_protocols.end ())
787     {
788       return i->second;
789     }
790 
791   return 0;
792 }
793 
CreateRawSocket()794 Ptr<Socket> Ipv6L3Protocol::CreateRawSocket ()
795 {
796   NS_LOG_FUNCTION (this);
797   Ptr<Ipv6RawSocketImpl> sock = CreateObject<Ipv6RawSocketImpl> ();
798   sock->SetNode (m_node);
799   m_sockets.push_back (sock);
800   return sock;
801 }
802 
DeleteRawSocket(Ptr<Socket> socket)803 void Ipv6L3Protocol::DeleteRawSocket (Ptr<Socket> socket)
804 {
805   NS_LOG_FUNCTION (this << socket);
806 
807   for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
808     {
809       if ((*it) == socket)
810         {
811           m_sockets.erase (it);
812           return;
813         }
814     }
815 }
816 
GetIcmpv6() const817 Ptr<Icmpv6L4Protocol> Ipv6L3Protocol::GetIcmpv6 () const
818 {
819   NS_LOG_FUNCTION (this);
820   Ptr<IpL4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
821 
822   if (protocol)
823     {
824       return protocol->GetObject<Icmpv6L4Protocol> ();
825     }
826   else
827     {
828       return 0;
829     }
830 }
831 
SetDefaultTtl(uint8_t ttl)832 void Ipv6L3Protocol::SetDefaultTtl (uint8_t ttl)
833 {
834   NS_LOG_FUNCTION (this << ttl);
835   m_defaultTtl = ttl;
836 }
837 
SetDefaultTclass(uint8_t tclass)838 void Ipv6L3Protocol::SetDefaultTclass (uint8_t tclass)
839 {
840   NS_LOG_FUNCTION (this << tclass);
841   m_defaultTclass = tclass;
842 }
843 
Send(Ptr<Packet> packet,Ipv6Address source,Ipv6Address destination,uint8_t protocol,Ptr<Ipv6Route> route)844 void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route)
845 {
846   NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
847   Ipv6Header hdr;
848   uint8_t ttl = m_defaultTtl;
849   SocketIpv6HopLimitTag tag;
850   bool found = packet->RemovePacketTag (tag);
851 
852   if (found)
853     {
854       ttl = tag.GetHopLimit ();
855     }
856 
857   SocketIpv6TclassTag tclassTag;
858   uint8_t tclass = m_defaultTclass;
859   found = packet->RemovePacketTag (tclassTag);
860 
861   if (found)
862     {
863       tclass = tclassTag.GetTclass ();
864     }
865 
866   /* Handle 3 cases:
867    * 1) Packet is passed in with a route entry
868    * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same network)
869    * 3) route is NULL (e.g., a raw socket call or ICMPv6)
870    */
871 
872   /* 1) */
873   if (route && route->GetGateway () != Ipv6Address::GetZero ())
874     {
875       NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: passed in with a route");
876       hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
877       int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
878       m_sendOutgoingTrace (hdr, packet, interface);
879       SendRealOut (route, packet, hdr);
880       return;
881     }
882 
883   /* 2) */
884   if (route && route->GetGateway () == Ipv6Address::GetZero ())
885     {
886       NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 2: probably sent to machine on same IPv6 network");
887       hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
888       int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
889       m_sendOutgoingTrace (hdr, packet, interface);
890       SendRealOut (route, packet, hdr);
891       return;
892     }
893 
894   /* 3) */
895   NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
896   Socket::SocketErrno err;
897   Ptr<NetDevice> oif (0);
898   Ptr<Ipv6Route> newRoute = 0;
899 
900   hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass);
901 
902   //for link-local traffic, we need to determine the interface
903   if (source.IsLinkLocal ()
904       || destination.IsLinkLocal ()
905       || destination.IsLinkLocalMulticast ())
906     {
907       int32_t index = GetInterfaceForAddress (source);
908       NS_ASSERT_MSG (index >= 0, "Can not find an outgoing interface for a packet with src " << source << " and dst " << destination);
909       oif = GetNetDevice (index);
910     }
911 
912   newRoute = m_routingProtocol->RouteOutput (packet, hdr, oif, err);
913 
914   if (newRoute)
915     {
916       int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
917       m_sendOutgoingTrace (hdr, packet, interface);
918       SendRealOut (newRoute, packet, hdr);
919     }
920   else
921     {
922       NS_LOG_WARN ("No route to host, drop!");
923       m_dropTrace (hdr, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv6> (), GetInterfaceForDevice (oif));
924     }
925 }
926 
Receive(Ptr<NetDevice> device,Ptr<const Packet> p,uint16_t protocol,const Address & from,const Address & to,NetDevice::PacketType packetType)927 void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
928 {
929   NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
930   NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
931 
932   NS_ASSERT_MSG (GetInterfaceForDevice(device) != -1, "Received a packet from an interface that is not known to IPv6");
933   uint32_t interface = GetInterfaceForDevice(device);
934 
935   Ptr<Ipv6Interface> ipv6Interface = m_interfaces[interface];
936   Ptr<Packet> packet = p->Copy ();
937 
938   if (ipv6Interface->IsUp ())
939     {
940       m_rxTrace (packet, m_node->GetObject<Ipv6> (), interface);
941     }
942   else
943     {
944       NS_LOG_LOGIC ("Dropping received packet-- interface is down");
945       Ipv6Header hdr;
946       packet->RemoveHeader (hdr);
947       m_dropTrace (hdr, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
948       return;
949     }
950 
951   Ipv6Header hdr;
952   packet->RemoveHeader (hdr);
953 
954   // Trim any residual frame padding from underlying devices
955   if (hdr.GetPayloadLength () < packet->GetSize ())
956     {
957       packet->RemoveAtEnd (packet->GetSize () - hdr.GetPayloadLength ());
958     }
959 
960   // the packet is valid, we update the NDISC cache entry (if present)
961   Ptr<NdiscCache> ndiscCache = ipv6Interface->GetNdiscCache ();
962   if (ndiscCache)
963     {
964       // case one, it's a a direct routing.
965       NdiscCache::Entry *entry = ndiscCache->Lookup (hdr.GetSource ());
966       if (entry)
967         {
968           entry->UpdateReachableTimer ();
969         }
970       else
971         {
972           // It's not in the direct routing, so it's the router, and it could have multiple IP addresses.
973           // In doubt, update all of them.
974           // Note: it's a confirmed behavior for Linux routers.
975           std::list<NdiscCache::Entry *> entryList = ndiscCache->LookupInverse (from);
976           std::list<NdiscCache::Entry *>::iterator iter;
977           for (iter = entryList.begin (); iter != entryList.end (); iter ++)
978             {
979               (*iter)->UpdateReachableTimer ();
980             }
981         }
982     }
983 
984 
985 
986   /* forward up to IPv6 raw sockets */
987   for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
988     {
989       Ptr<Ipv6RawSocketImpl> socket = *it;
990       socket->ForwardUp (packet, hdr, device);
991     }
992 
993   Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
994   Ptr<Ipv6Extension> ipv6Extension = 0;
995   uint8_t nextHeader = hdr.GetNextHeader ();
996   bool stopProcessing = false;
997   bool isDropped = false;
998   DropReason dropReason;
999 
1000   if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1001     {
1002       ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
1003 
1004       if (ipv6Extension)
1005         {
1006           ipv6Extension->Process (packet, 0, hdr, hdr.GetDestination (), (uint8_t *)0, stopProcessing, isDropped, dropReason);
1007         }
1008 
1009       if (isDropped)
1010         {
1011           m_dropTrace (hdr, packet, dropReason, m_node->GetObject<Ipv6> (), interface);
1012         }
1013 
1014       if (stopProcessing)
1015         {
1016           return;
1017         }
1018     }
1019 
1020   if (hdr.GetDestination ().IsAllNodesMulticast ())
1021     {
1022       LocalDeliver (packet, hdr, interface);
1023       return;
1024     }
1025   else if (hdr.GetDestination ().IsAllRoutersMulticast() && ipv6Interface->IsForwarding ())
1026     {
1027       LocalDeliver (packet, hdr, interface);
1028       return;
1029     }
1030   else if (hdr.GetDestination ().IsMulticast ())
1031     {
1032       bool isSolicited = ipv6Interface->IsSolicitedMulticastAddress (hdr.GetDestination ());
1033       bool isRegisteredOnInterface = IsRegisteredMulticastAddress (hdr.GetDestination (), interface);
1034       bool isRegisteredGlobally = IsRegisteredMulticastAddress (hdr.GetDestination ());
1035       if (isSolicited || isRegisteredGlobally || isRegisteredOnInterface)
1036         {
1037           LocalDeliver (packet, hdr, interface);
1038           // do not return, the packet could be handled by a routing protocol
1039         }
1040     }
1041 
1042 
1043   for (uint32_t j = 0; j < GetNInterfaces (); j++)
1044     {
1045       if (j == interface || !m_strongEndSystemModel)
1046         {
1047           for (uint32_t i = 0; i < GetNAddresses (j); i++)
1048             {
1049               Ipv6InterfaceAddress iaddr = GetAddress (j, i);
1050               Ipv6Address addr = iaddr.GetAddress ();
1051               if (addr == hdr.GetDestination ())
1052                 {
1053                   if (j == interface)
1054                     {
1055                       NS_LOG_LOGIC ("For me (destination " << addr << " match)");
1056                     }
1057                   else
1058                     {
1059                       NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << hdr.GetDestination ());
1060                     }
1061                   LocalDeliver (packet, hdr, interface);
1062                   return;
1063                 }
1064               NS_LOG_LOGIC ("Address " << addr << " not a match");
1065             }
1066         }
1067     }
1068 
1069   if (!m_routingProtocol->RouteInput (packet, hdr, device,
1070                                       MakeCallback (&Ipv6L3Protocol::IpForward, this),
1071                                       MakeCallback (&Ipv6L3Protocol::IpMulticastForward, this),
1072                                       MakeCallback (&Ipv6L3Protocol::LocalDeliver, this),
1073                                       MakeCallback (&Ipv6L3Protocol::RouteInputError, this)))
1074     {
1075       NS_LOG_WARN ("No route found for forwarding packet.  Drop.");
1076       // Drop trace and ICMPs are courtesy of RouteInputError
1077     }
1078 }
1079 
1080 void
CallTxTrace(const Ipv6Header & ipHeader,Ptr<Packet> packet,Ptr<Ipv6> ipv6,uint32_t interface)1081 Ipv6L3Protocol::CallTxTrace (const Ipv6Header & ipHeader, Ptr<Packet> packet,
1082                                     Ptr<Ipv6> ipv6, uint32_t interface)
1083 {
1084   Ptr<Packet> packetCopy = packet->Copy ();
1085   packetCopy->AddHeader (ipHeader);
1086   m_txTrace (packetCopy, ipv6, interface);
1087 }
1088 
SendRealOut(Ptr<Ipv6Route> route,Ptr<Packet> packet,Ipv6Header const & ipHeader)1089 void Ipv6L3Protocol::SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6Header const& ipHeader)
1090 {
1091   NS_LOG_FUNCTION (this << route << packet << ipHeader);
1092 
1093   if (!route)
1094     {
1095       NS_LOG_LOGIC ("No route to host, drop!.");
1096       return;
1097     }
1098 
1099   Ptr<NetDevice> dev = route->GetOutputDevice ();
1100   int32_t interface = GetInterfaceForDevice (dev);
1101   NS_ASSERT (interface >= 0);
1102 
1103   Ptr<Ipv6Interface> outInterface = GetInterface (interface);
1104   NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
1105 
1106   // Check packet size
1107   std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair> fragments;
1108 
1109   // Check if we have a Path MTU stored. If so, use it. Else, use the link MTU.
1110   size_t targetMtu = (size_t)(m_pmtuCache->GetPmtu (ipHeader.GetDestination()));
1111   if (targetMtu == 0)
1112     {
1113       targetMtu = dev->GetMtu ();
1114     }
1115 
1116   if (packet->GetSize () > targetMtu + 40) /* 40 => size of IPv6 header */
1117     {
1118       // Router => drop
1119 
1120       bool fromMe = false;
1121       for (uint32_t i=0; i<GetNInterfaces(); i++ )
1122         {
1123           for (uint32_t j=0; j<GetNAddresses(i); j++ )
1124             {
1125               if (GetAddress(i,j).GetAddress() == ipHeader.GetSource())
1126                 {
1127                   fromMe = true;
1128                   break;
1129                 }
1130             }
1131         }
1132       if (!fromMe)
1133         {
1134           Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
1135           if ( icmpv6 )
1136             {
1137               packet->AddHeader(ipHeader);
1138               icmpv6->SendErrorTooBig (packet, ipHeader.GetSource (), dev->GetMtu ());
1139             }
1140           return;
1141         }
1142 
1143       Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
1144 
1145       // To get specific method GetFragments from Ipv6ExtensionFragmentation
1146       Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
1147       NS_ASSERT (ipv6Fragment != 0);
1148       ipv6Fragment->GetFragments (packet, ipHeader, targetMtu, fragments);
1149     }
1150 
1151   if (route->GetGateway () != Ipv6Address::GetAny ())
1152     {
1153       if (outInterface->IsUp ())
1154         {
1155           NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
1156 
1157           if (fragments.size () != 0)
1158             {
1159               std::ostringstream oss;
1160 
1161               for (std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair>::const_iterator it = fragments.begin (); it != fragments.end (); it++)
1162                 {
1163                   CallTxTrace (it->second, it->first, m_node->GetObject<Ipv6> (), interface);
1164                   outInterface->Send (it->first, it->second, route->GetGateway ());
1165                 }
1166             }
1167           else
1168             {
1169               CallTxTrace (ipHeader, packet, m_node->GetObject<Ipv6> (), interface);
1170               outInterface->Send (packet, ipHeader, route->GetGateway ());
1171             }
1172         }
1173       else
1174         {
1175           NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
1176           m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
1177         }
1178     }
1179   else
1180     {
1181       if (outInterface->IsUp ())
1182         {
1183           NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
1184 
1185           if (fragments.size () != 0)
1186             {
1187               std::ostringstream oss;
1188 
1189               for (std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair>::const_iterator it = fragments.begin (); it != fragments.end (); it++)
1190                 {
1191                   CallTxTrace (it->second, it->first, m_node->GetObject<Ipv6> (), interface);
1192                   outInterface->Send (it->first, it->second, ipHeader.GetDestination ());
1193                 }
1194             }
1195           else
1196             {
1197               CallTxTrace (ipHeader, packet, m_node->GetObject<Ipv6> (), interface);
1198               outInterface->Send (packet, ipHeader, ipHeader.GetDestination ());
1199             }
1200         }
1201       else
1202         {
1203           NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
1204           m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv6> (), interface);
1205         }
1206     }
1207 }
1208 
IpForward(Ptr<const NetDevice> idev,Ptr<Ipv6Route> rtentry,Ptr<const Packet> p,const Ipv6Header & header)1209 void Ipv6L3Protocol::IpForward (Ptr<const NetDevice> idev, Ptr<Ipv6Route> rtentry, Ptr<const Packet> p, const Ipv6Header& header)
1210 {
1211   NS_LOG_FUNCTION (this << rtentry << p << header);
1212   NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
1213 
1214   // Drop RFC 3849 packets: 2001:db8::/32
1215   if (header.GetDestination().IsDocumentation ())
1216     {
1217       NS_LOG_WARN ("Received a packet for 2001:db8::/32 (documentation class).  Drop.");
1218       m_dropTrace (header, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv6> (), 0);
1219       return;
1220     }
1221 
1222   // Forwarding
1223   Ipv6Header ipHeader = header;
1224   Ptr<Packet> packet = p->Copy ();
1225   ipHeader.SetHopLimit (ipHeader.GetHopLimit () - 1);
1226 
1227   if (ipHeader.GetSource ().IsLinkLocal ())
1228     {
1229       /* no forward for link-local address */
1230       return;
1231     }
1232 
1233   if (ipHeader.GetHopLimit () == 0)
1234     {
1235       NS_LOG_WARN ("TTL exceeded.  Drop.");
1236       m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), 0);
1237       // Do not reply to multicast IPv6 address
1238       if (ipHeader.GetDestination ().IsMulticast () == false)
1239         {
1240           packet->AddHeader (ipHeader);
1241           GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSource (), Icmpv6Header::ICMPV6_HOPLIMIT);
1242         }
1243       return;
1244     }
1245 
1246   /* ICMPv6 Redirect */
1247 
1248   /* if we forward to a machine on the same network as the source,
1249    * we send him an ICMPv6 redirect message to notify him that a short route
1250    * exists.
1251    */
1252 
1253   /* Theoretically we should also check if the redirect target is on the same network
1254    * as the source node. On the other hand, we are sure that the router we're redirecting to
1255    * used a link-local address. As a consequence, they MUST be on the same network, the link-local net.
1256    */
1257 
1258   if (m_sendIcmpv6Redirect && (rtentry->GetOutputDevice ()==idev))
1259     {
1260       NS_LOG_LOGIC ("ICMPv6 redirect!");
1261       Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
1262       Address hardwareTarget;
1263       Ipv6Address dst = header.GetDestination ();
1264       Ipv6Address src = header.GetSource ();
1265       Ipv6Address target = rtentry->GetGateway ();
1266       Ptr<Packet> copy = p->Copy ();
1267 
1268       if (target.IsAny ())
1269         {
1270           target = dst;
1271         }
1272 
1273       copy->AddHeader (header);
1274       Ipv6Address linkLocal = GetInterface (GetInterfaceForDevice (rtentry->GetOutputDevice ()))->GetLinkLocalAddress ().GetAddress ();
1275 
1276       if (icmpv6->Lookup (target, rtentry->GetOutputDevice (), 0, &hardwareTarget))
1277         {
1278           icmpv6->SendRedirection (copy, linkLocal, src, target, dst, hardwareTarget);
1279         }
1280       else
1281         {
1282           icmpv6->SendRedirection (copy, linkLocal, src, target, dst, Address ());
1283         }
1284     }
1285   // in case the packet still has a priority tag attached, remove it
1286   SocketPriorityTag priorityTag;
1287   packet->RemovePacketTag (priorityTag);
1288   int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
1289   m_unicastForwardTrace (ipHeader, packet, interface);
1290   SendRealOut (rtentry, packet, ipHeader);
1291 }
1292 
IpMulticastForward(Ptr<const NetDevice> idev,Ptr<Ipv6MulticastRoute> mrtentry,Ptr<const Packet> p,const Ipv6Header & header)1293 void Ipv6L3Protocol::IpMulticastForward (Ptr<const NetDevice> idev, Ptr<Ipv6MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv6Header& header)
1294 {
1295   NS_LOG_FUNCTION (this << mrtentry << p << header);
1296   NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
1297 
1298   std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
1299   std::map<uint32_t, uint32_t>::iterator mapIter;
1300 
1301   for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
1302     {
1303       uint32_t interfaceId = mapIter->first;
1304       //uint32_t outputTtl = mapIter->second;  // Unused for now
1305       Ptr<Packet> packet = p->Copy ();
1306       Ipv6Header h = header;
1307       h.SetHopLimit (header.GetHopLimit () - 1);
1308       if (h.GetHopLimit () == 0)
1309         {
1310           NS_LOG_WARN ("TTL exceeded.  Drop.");
1311           m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), interfaceId);
1312           return;
1313         }
1314       NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
1315       Ptr<Ipv6Route> rtentry = Create<Ipv6Route> ();
1316       rtentry->SetSource (h.GetSource ());
1317       rtentry->SetDestination (h.GetDestination ());
1318       rtentry->SetGateway (Ipv6Address::GetAny ());
1319       rtentry->SetOutputDevice (GetNetDevice (interfaceId));
1320       SendRealOut (rtentry, packet, h);
1321       continue;
1322     }
1323 }
1324 
LocalDeliver(Ptr<const Packet> packet,Ipv6Header const & ip,uint32_t iif)1325 void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& ip, uint32_t iif)
1326 {
1327   NS_LOG_FUNCTION (this << packet << ip << iif);
1328   Ptr<Packet> p = packet->Copy ();
1329   Ptr<IpL4Protocol> protocol = 0;
1330   Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
1331   Ptr<Ipv6Extension> ipv6Extension = 0;
1332   Ipv6Address src = ip.GetSource ();
1333   Ipv6Address dst = ip.GetDestination ();
1334   uint8_t nextHeader = ip.GetNextHeader ();
1335   uint8_t nextHeaderPosition = 0;
1336   bool isDropped = false;
1337   bool stopProcessing = false;
1338   DropReason dropReason;
1339 
1340   // check for a malformed hop-by-hop extension
1341   // this is a common case when forging IPv6 raw packets
1342   if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1343     {
1344       uint8_t buf;
1345       p->CopyData (&buf, 1);
1346       if (buf == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1347         {
1348           NS_LOG_WARN("Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, dropping packet");
1349           return;
1350         }
1351     }
1352 
1353   /* process all the extensions found and the layer 4 protocol */
1354   do
1355     {
1356       /* it return 0 for non-extension (i.e. layer 4 protocol) */
1357       ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
1358 
1359       if (ipv6Extension)
1360         {
1361           uint8_t nextHeaderStep = 0;
1362           uint8_t curHeader = nextHeader;
1363           nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, stopProcessing, isDropped, dropReason);
1364           nextHeaderPosition += nextHeaderStep;
1365 
1366           if (isDropped)
1367             {
1368               m_dropTrace (ip, packet, dropReason, m_node->GetObject<Ipv6> (), iif);
1369             }
1370 
1371           if (stopProcessing)
1372             {
1373               return;
1374             }
1375           NS_ASSERT_MSG (nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
1376                          "Zero-size IPv6 Option Header, aborting" << *packet );
1377         }
1378       else
1379         {
1380           protocol = GetProtocol (nextHeader, iif);
1381 
1382           if (!protocol)
1383             {
1384               NS_LOG_LOGIC ("Unknown Next Header. Drop!");
1385 
1386               // For ICMPv6 Error packets
1387               Ptr<Packet> malformedPacket  = packet->Copy ();
1388               malformedPacket->AddHeader (ip);
1389 
1390               if (nextHeaderPosition == 0)
1391                 {
1392                   GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, 40);
1393                 }
1394               else
1395                 {
1396                   GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, ip.GetSerializedSize () + nextHeaderPosition);
1397                 }
1398               m_dropTrace (ip, p, DROP_UNKNOWN_PROTOCOL, m_node->GetObject<Ipv6> (), iif);
1399               break;
1400             }
1401           else
1402             {
1403               p->RemoveAtStart (nextHeaderPosition);
1404               /* protocol->Receive (p, src, dst, incomingInterface); */
1405 
1406               /* L4 protocol */
1407               Ptr<Packet> copy = p->Copy ();
1408 
1409               m_localDeliverTrace (ip, p, iif);
1410 
1411               enum IpL4Protocol::RxStatus status = protocol->Receive (p, ip, GetInterface (iif));
1412 
1413               switch (status)
1414                 {
1415                 case IpL4Protocol::RX_OK:
1416                   break;
1417                 case IpL4Protocol::RX_CSUM_FAILED:
1418                   break;
1419                 case IpL4Protocol::RX_ENDPOINT_CLOSED:
1420                   break;
1421                 case IpL4Protocol::RX_ENDPOINT_UNREACH:
1422                   if (ip.GetDestination ().IsMulticast ())
1423                     {
1424                       /* do not rely on multicast address */
1425                       break;
1426                     }
1427 
1428                   copy->AddHeader (ip);
1429                   GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSource (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
1430                 }
1431             }
1432         }
1433     }
1434   while (ipv6Extension);
1435 }
1436 
RouteInputError(Ptr<const Packet> p,const Ipv6Header & ipHeader,Socket::SocketErrno sockErrno)1437 void Ipv6L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno)
1438 {
1439   NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1440   NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1441 
1442   m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv6> (), 0);
1443 
1444   if (!ipHeader.GetDestination ().IsMulticast ())
1445     {
1446       Ptr<Packet> packet = p->Copy ();
1447       packet->AddHeader (ipHeader);
1448       GetIcmpv6 ()->SendErrorDestinationUnreachable (packet, ipHeader.GetSource (), Icmpv6Header::ICMPV6_NO_ROUTE);
1449     }
1450 }
1451 
BuildHeader(Ipv6Address src,Ipv6Address dst,uint8_t protocol,uint16_t payloadSize,uint8_t ttl,uint8_t tclass)1452 Ipv6Header Ipv6L3Protocol::BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t ttl, uint8_t tclass)
1453 {
1454   NS_LOG_FUNCTION (this << src << dst << (uint32_t)protocol << (uint32_t)payloadSize << (uint32_t)ttl << (uint32_t)tclass);
1455   Ipv6Header hdr;
1456 
1457   hdr.SetSource (src);
1458   hdr.SetDestination (dst);
1459   hdr.SetNextHeader (protocol);
1460   hdr.SetPayloadLength (payloadSize);
1461   hdr.SetHopLimit (ttl);
1462   hdr.SetTrafficClass (tclass);
1463   return hdr;
1464 }
1465 
RegisterExtensions()1466 void Ipv6L3Protocol::RegisterExtensions ()
1467 {
1468   Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = CreateObject<Ipv6ExtensionDemux> ();
1469   ipv6ExtensionDemux->SetNode (m_node);
1470 
1471   Ptr<Ipv6ExtensionHopByHop> hopbyhopExtension = CreateObject<Ipv6ExtensionHopByHop> ();
1472   hopbyhopExtension->SetNode (m_node);
1473   Ptr<Ipv6ExtensionDestination> destinationExtension = CreateObject<Ipv6ExtensionDestination> ();
1474   destinationExtension->SetNode (m_node);
1475   Ptr<Ipv6ExtensionFragment> fragmentExtension = CreateObject<Ipv6ExtensionFragment> ();
1476   fragmentExtension->SetNode (m_node);
1477   Ptr<Ipv6ExtensionRouting> routingExtension = CreateObject<Ipv6ExtensionRouting> ();
1478   routingExtension->SetNode (m_node);
1479   // Ptr<Ipv6ExtensionESP> espExtension = CreateObject<Ipv6ExtensionESP> ();
1480   // Ptr<Ipv6ExtensionAH> ahExtension = CreateObject<Ipv6ExtensionAH> ();
1481 
1482   ipv6ExtensionDemux->Insert (hopbyhopExtension);
1483   ipv6ExtensionDemux->Insert (destinationExtension);
1484   ipv6ExtensionDemux->Insert (fragmentExtension);
1485   ipv6ExtensionDemux->Insert (routingExtension);
1486   // ipv6ExtensionDemux->Insert (espExtension);
1487   // ipv6ExtensionDemux->Insert (ahExtension);
1488 
1489   Ptr<Ipv6ExtensionRoutingDemux> routingExtensionDemux = CreateObject<Ipv6ExtensionRoutingDemux> ();
1490   routingExtensionDemux->SetNode (m_node);
1491   Ptr<Ipv6ExtensionLooseRouting> looseRoutingExtension = CreateObject<Ipv6ExtensionLooseRouting> ();
1492   looseRoutingExtension->SetNode (m_node);
1493   routingExtensionDemux->Insert (looseRoutingExtension);
1494 
1495   m_node->AggregateObject (routingExtensionDemux);
1496   m_node->AggregateObject (ipv6ExtensionDemux);
1497 }
1498 
RegisterOptions()1499 void Ipv6L3Protocol::RegisterOptions ()
1500 {
1501   Ptr<Ipv6OptionDemux> ipv6OptionDemux = CreateObject<Ipv6OptionDemux> ();
1502   ipv6OptionDemux->SetNode (m_node);
1503 
1504   Ptr<Ipv6OptionPad1> pad1Option = CreateObject<Ipv6OptionPad1> ();
1505   pad1Option->SetNode (m_node);
1506   Ptr<Ipv6OptionPadn> padnOption = CreateObject<Ipv6OptionPadn> ();
1507   padnOption->SetNode (m_node);
1508   Ptr<Ipv6OptionJumbogram> jumbogramOption = CreateObject<Ipv6OptionJumbogram> ();
1509   jumbogramOption->SetNode (m_node);
1510   Ptr<Ipv6OptionRouterAlert> routerAlertOption = CreateObject<Ipv6OptionRouterAlert> ();
1511   routerAlertOption->SetNode (m_node);
1512 
1513   ipv6OptionDemux->Insert (pad1Option);
1514   ipv6OptionDemux->Insert (padnOption);
1515   ipv6OptionDemux->Insert (jumbogramOption);
1516   ipv6OptionDemux->Insert (routerAlertOption);
1517 
1518   m_node->AggregateObject (ipv6OptionDemux);
1519 }
1520 
ReportDrop(Ipv6Header ipHeader,Ptr<Packet> p,DropReason dropReason)1521 void Ipv6L3Protocol::ReportDrop (Ipv6Header ipHeader, Ptr<Packet> p, DropReason dropReason)
1522 {
1523   m_dropTrace (ipHeader, p, dropReason, m_node->GetObject<Ipv6> (), 0);
1524 }
1525 
AddMulticastAddress(Ipv6Address address,uint32_t interface)1526 void Ipv6L3Protocol::AddMulticastAddress (Ipv6Address address, uint32_t interface)
1527 {
1528   NS_LOG_FUNCTION (address << interface);
1529 
1530   if (!address.IsMulticast ())
1531     {
1532       NS_LOG_WARN ("Not adding a non-multicast address " << address);
1533       return;
1534     }
1535 
1536   Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface);
1537   m_multicastAddresses[key]++;
1538 }
1539 
AddMulticastAddress(Ipv6Address address)1540 void Ipv6L3Protocol::AddMulticastAddress (Ipv6Address address)
1541 {
1542   NS_LOG_FUNCTION (address);
1543 
1544   if (!address.IsMulticast ())
1545     {
1546       NS_LOG_WARN ("Not adding a non-multicast address " << address);
1547       return;
1548     }
1549 
1550   m_multicastAddressesNoInterface[address]++;
1551 }
1552 
RemoveMulticastAddress(Ipv6Address address,uint32_t interface)1553 void Ipv6L3Protocol::RemoveMulticastAddress (Ipv6Address address, uint32_t interface)
1554 {
1555   NS_LOG_FUNCTION (address << interface);
1556 
1557   Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface);
1558 
1559   m_multicastAddresses[key]--;
1560   if (m_multicastAddresses[key] == 0)
1561     {
1562       m_multicastAddresses.erase (key);
1563     }
1564 }
1565 
RemoveMulticastAddress(Ipv6Address address)1566 void Ipv6L3Protocol::RemoveMulticastAddress (Ipv6Address address)
1567 {
1568   NS_LOG_FUNCTION (address);
1569 
1570   m_multicastAddressesNoInterface[address]--;
1571   if (m_multicastAddressesNoInterface[address] == 0)
1572     {
1573       m_multicastAddressesNoInterface.erase (address);
1574     }
1575 }
1576 
IsRegisteredMulticastAddress(Ipv6Address address,uint32_t interface) const1577 bool Ipv6L3Protocol::IsRegisteredMulticastAddress (Ipv6Address address, uint32_t interface) const
1578 {
1579   NS_LOG_FUNCTION (address << interface);
1580 
1581   Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface);
1582   Ipv6RegisteredMulticastAddressCIter_t iter = m_multicastAddresses.find (key);
1583 
1584   if (iter == m_multicastAddresses.end ())
1585     {
1586       return false;
1587     }
1588   return true;
1589 }
1590 
IsRegisteredMulticastAddress(Ipv6Address address) const1591 bool Ipv6L3Protocol::IsRegisteredMulticastAddress (Ipv6Address address) const
1592 {
1593   NS_LOG_FUNCTION (address);
1594 
1595   Ipv6RegisteredMulticastAddressNoInterfaceCIter_t iter = m_multicastAddressesNoInterface.find (address);
1596 
1597   if (iter == m_multicastAddressesNoInterface.end ())
1598     {
1599       return false;
1600     }
1601   return true;
1602 }
1603 
ReachabilityHint(uint32_t ipInterfaceIndex,Ipv6Address address)1604 bool Ipv6L3Protocol::ReachabilityHint (uint32_t ipInterfaceIndex, Ipv6Address address)
1605 {
1606   if (ipInterfaceIndex >= m_interfaces.size ())
1607     {
1608       return false;
1609     }
1610 
1611   Ptr<NdiscCache> ndiscCache = m_interfaces[ipInterfaceIndex]->GetNdiscCache ();
1612   if (!ndiscCache)
1613     {
1614       return false;
1615     }
1616 
1617   NdiscCache::Entry* entry = ndiscCache->Lookup (address);
1618   if (!entry || entry->IsIncomplete ())
1619     {
1620       return false;
1621     }
1622 
1623 
1624   if (entry->IsReachable ())
1625     {
1626       entry->UpdateReachableTimer ();
1627     }
1628   else if (entry->IsPermanent ())
1629     {
1630       return true;
1631     }
1632   else if (entry->IsProbe ())
1633     {
1634       // we just confirm the entry's MAC address to get the waiting packets (if any)
1635       std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting = entry->MarkReachable (entry->GetMacAddress ());
1636       for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
1637         {
1638           ndiscCache->GetInterface ()->Send (it->first, it->second, it->second.GetSource ());
1639         }
1640       entry->ClearWaitingPacket ();
1641       entry->StartReachableTimer ();
1642     }
1643   else // STALE OR DELAY
1644     {
1645       entry->MarkReachable ();
1646       entry->StartReachableTimer ();
1647     }
1648 
1649 
1650   return true;
1651 }
1652 
1653 } /* namespace ns3 */
1654 
1655