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