A Discrete-Event Network Simulator
API
icmpv6-l4-protocol.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2007-2009 Strasbourg University
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19 * David Gross <gdavid.devel@gmail.com>
20 * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
21 * Tommaso Pecorella <tommaso.pecorella@unifi.it>
22 */
23
24#include "ns3/log.h"
25#include "ns3/assert.h"
26#include "ns3/packet.h"
27#include "ns3/node.h"
28#include "ns3/boolean.h"
29#include "ns3/ipv6-routing-protocol.h"
30#include "ns3/ipv6-route.h"
31#include "ns3/pointer.h"
32#include "ns3/string.h"
33#include "ns3/integer.h"
34
35#include "ipv6-l3-protocol.h"
36#include "ipv6-interface.h"
37#include "icmpv6-l4-protocol.h"
38
39namespace ns3 {
40
41NS_LOG_COMPONENT_DEFINE ("Icmpv6L4Protocol");
42
43NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
44
45const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
46
47//const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial interval.
48//const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA transmission.
49//const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final RA transmission.
50//const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min delay between RA.
51//const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; // millisecond - max delay between RA.
52
53//const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
54//const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
55//const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
56
57//const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
58//const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
59
60//const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
61//const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
62
64{
65 static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
67 .SetGroupName ("Internet")
68 .AddConstructor<Icmpv6L4Protocol> ()
69 .AddAttribute ("DAD", "Always do DAD check.",
70 BooleanValue (true),
73 .AddAttribute ("SolicitationJitter", "The jitter in ms a node is allowed to wait before sending any solicitation. Some jitter aims to prevent collisions. By default, the model will wait for a duration in ms defined by a uniform random-variable between 0 and SolicitationJitter",
74 StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
76 MakePointerChecker<RandomVariableStream> ())
77 .AddAttribute ("MaxMulticastSolicit", "Neighbor Discovery node constants: max multicast solicitations.",
78 IntegerValue (3),
80 MakeIntegerChecker<uint8_t> ())
81 .AddAttribute ("MaxUnicastSolicit", "Neighbor Discovery node constants: max unicast solicitations.",
82 IntegerValue (3),
84 MakeIntegerChecker<uint8_t> ())
85 .AddAttribute ("ReachableTime", "Neighbor Discovery node constants: reachable time.",
86 TimeValue (Seconds (30)),
89 .AddAttribute ("RetransmissionTime", "Neighbor Discovery node constants: retransmission timer.",
90 TimeValue (Seconds (1)),
93 .AddAttribute ("DelayFirstProbe", "Neighbor Discovery node constants: delay for the first probe.",
94 TimeValue (Seconds (5)),
97 ;
98 return tid;
99}
100
102{
103 NS_LOG_FUNCTION (this);
105}
106
108 : m_node (0)
109{
110 NS_LOG_FUNCTION (this);
111}
112
114{
115 NS_LOG_FUNCTION (this);
116}
117
119{
120 NS_LOG_FUNCTION (this);
121 for (CacheList::const_iterator it = m_cacheList.begin (); it != m_cacheList.end (); it++)
122 {
123 Ptr<NdiscCache> cache = *it;
124 cache->Dispose ();
125 cache = 0;
126 }
127 m_cacheList.clear ();
129
130 m_node = 0;
132}
133
134int64_t Icmpv6L4Protocol::AssignStreams (int64_t stream)
135{
136 NS_LOG_FUNCTION (this << stream);
138 return 1;
139}
140
142{
143 NS_LOG_FUNCTION (this);
144 if (m_node == 0)
145 {
146 Ptr<Node> node = this->GetObject<Node> ();
147 if (node != 0)
148 {
149 Ptr<Ipv6> ipv6 = this->GetObject<Ipv6> ();
150 if (ipv6 != 0 && m_downTarget.IsNull ())
151 {
152 SetNode (node);
153 ipv6->Insert (this);
155 }
156 }
157 }
159}
160
162{
163 NS_LOG_FUNCTION (this << node);
164 m_node = node;
165}
166
168{
169 NS_LOG_FUNCTION (this);
170 return m_node;
171}
172
174{
176 return PROT_NUMBER;
177}
178
180{
181 NS_LOG_FUNCTION (this);
182 return PROT_NUMBER;
183}
184
186{
187 NS_LOG_FUNCTION (this);
188 return 1;
189}
190
192{
193 NS_LOG_FUNCTION (this);
194 return m_alwaysDad;
195}
196
198{
199 NS_LOG_FUNCTION (this << target << interface);
200 Ipv6Address addr;
202
203 NS_ASSERT (ipv6);
204
205 if (!m_alwaysDad)
206 {
207 return;
208 }
209
213
214 /* update last packet UID */
215 interface->SetNsDadUid (target, p.first->GetUid ());
217}
218
220{
221 NS_LOG_FUNCTION (this << packet << header);
223}
224
226{
227 NS_LOG_FUNCTION (this << packet << header.GetSource () << header.GetDestination () << interface);
228 Ptr<Packet> p = packet->Copy ();
229 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
230
231 /* very ugly! try to find something better in the future */
232 uint8_t type;
233 p->CopyData (&type, sizeof(type));
234
235 switch (type)
236 {
238 if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
239 {
240 HandleRS (p, header.GetSource (), header.GetDestination (), interface);
241 }
242 break;
244 if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
245 {
246 HandleRA (p, header.GetSource (), header.GetDestination (), interface);
247 }
248 break;
250 HandleNS (p, header.GetSource (), header.GetDestination (), interface);
251 break;
253 HandleNA (p, header.GetSource (), header.GetDestination (), interface);
254 break;
256 HandleRedirection (p, header.GetSource (), header.GetDestination (), interface);
257 break;
259 HandleEchoRequest (p, header.GetSource (), header.GetDestination (), interface);
260 break;
262 // EchoReply does not contain any info about L4
263 // so we can not forward it up.
265 break;
267 HandleDestinationUnreachable (p, header.GetSource (), header.GetDestination (), interface);
268 break;
270 HandlePacketTooBig (p, header.GetSource (), header.GetDestination (), interface);
271 break;
273 HandleTimeExceeded (p, header.GetSource (), header.GetDestination (), interface);
274 break;
276 HandleParameterError (p, header.GetSource (), header.GetDestination (), interface);
277 break;
278 default:
279 NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
280 break;
281 }
282
283 return IpL4Protocol::RX_OK;
284}
285
287 uint32_t info, Ipv6Header ipHeader,
288 const uint8_t payload[8])
289{
290 NS_LOG_FUNCTION (this << source << icmp << info << ipHeader << payload);
291
293
295
296 uint8_t nextHeader = ipHeader.GetNextHeader ();
297
298 if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
299 {
300 Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
301 if (l4 != 0)
302 {
303 l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
304 info, ipHeader.GetSource (), ipHeader.GetDestination (), payload);
305 }
306 }
307}
308
310{
311 NS_LOG_FUNCTION (this << packet << src << dst << interface);
312 Icmpv6Echo request;
313 uint8_t* buf = new uint8_t[packet->GetSize ()];
314
315 packet->RemoveHeader (request);
316 /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
317 packet->CopyData (buf, packet->GetSize ());
318 Ptr<Packet> p = Create<Packet> (buf, packet->GetSize ());
319
320 /* if we send message from ff02::* (link-local multicast), we use our link-local address */
321 SendEchoReply (dst.IsMulticast () ? interface->GetLinkLocalAddress ().GetAddress () : dst, src, request.GetId (), request.GetSeq (), p);
322 delete[] buf;
323}
324
326{
327 NS_LOG_FUNCTION (this << packet << src << dst << interface);
328 Ptr<Packet> p = packet->Copy ();
329 Icmpv6RA raHeader;
332 Icmpv6OptionMtu mtuHdr;
334 bool next = true;
335 bool hasLla = false;
336 bool hasMtu = false;
337 Ipv6Address defaultRouter = Ipv6Address::GetZero ();
338
339 p->RemoveHeader (raHeader);
340
341 if (raHeader.GetLifeTime())
342 {
343 defaultRouter = src;
344 }
345
346 while (next == true)
347 {
348 uint8_t type = 0;
349 p->CopyData (&type, sizeof(type));
350
351 switch (type)
352 {
354 p->RemoveHeader (prefixHdr);
355 ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
356 prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), defaultRouter);
357 break;
359 /* take in account the first MTU option */
360 if (!hasMtu)
361 {
362 p->RemoveHeader (mtuHdr);
363 hasMtu = true;
365 /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
366 }
367 break;
369 /* take in account the first LLA option */
370 if (!hasLla)
371 {
372 p->RemoveHeader (llaHdr);
373 ReceiveLLA (llaHdr, src, dst, interface);
374 hasLla = true;
375 }
376 break;
377 default:
378 /* unknown option, quit */
379 next = false;
380 }
381 }
382}
383
385{
386 NS_LOG_FUNCTION (this << lla << src << dst << interface);
387 Address hardwareAddress;
388 NdiscCache::Entry* entry = 0;
389 Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
390
391 /* check if we have this address in our cache */
392 entry = cache->Lookup (src);
393
394 if (!entry)
395 {
396 entry = cache->Add (src);
397 entry->SetRouter (true);
398 entry->SetMacAddress (lla.GetAddress ());
399 entry->MarkReachable ();
400 entry->StartReachableTimer ();
401 }
402 else
403 {
404 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
405 if (entry->IsIncomplete ())
406 {
407 entry->StopNudTimer ();
408 // mark it to reachable
409 waiting = entry->MarkReachable (lla.GetAddress ());
410 entry->StartReachableTimer ();
411 // send out waiting packet
412 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
413 {
414 cache->GetInterface ()->Send (it->first, it->second, src);
415 }
416 entry->ClearWaitingPacket ();
417 }
418 else
419 {
420 if (entry->GetMacAddress () != lla.GetAddress ())
421 {
422 entry->SetMacAddress (lla.GetAddress ());
423 entry->MarkStale ();
424 entry->SetRouter (true);
425 }
426 else
427 {
428 if (!entry->IsReachable () || !entry->IsPermanent ())
429 {
430 entry->StopNudTimer ();
431 waiting = entry->MarkReachable (lla.GetAddress ());
432 if (entry->IsProbe ())
433 {
434 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
435 {
436 cache->GetInterface ()->Send (it->first, it->second, src);
437 }
438 }
439 if (!entry->IsPermanent ())
440 {
441 entry->StartReachableTimer ();
442 }
443 }
444 }
445 }
446 }
447}
448
450{
451 NS_LOG_FUNCTION (this << packet << src << dst << interface);
453 Icmpv6RS rsHeader;
454 packet->RemoveHeader (rsHeader);
455 Address hardwareAddress;
457 NdiscCache::Entry* entry = 0;
458 Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
459
460 if (src != Ipv6Address::GetAny ())
461 {
462 /* XXX search all options following the RS header */
463 /* test if the next option is SourceLinkLayerAddress */
464 uint8_t type;
465 packet->CopyData (&type, sizeof(type));
466
468 {
469 return;
470 }
471 packet->RemoveHeader (lla);
472 NS_LOG_LOGIC ("Cache updated by RS");
473
474 entry = cache->Lookup (src);
475 if (!entry)
476 {
477 entry = cache->Add (src);
478 entry->SetRouter (false);
479 entry->MarkStale (lla.GetAddress ());
480 }
481 else if (entry->GetMacAddress () != lla.GetAddress ())
482 {
483 entry->MarkStale (lla.GetAddress ());
484 }
485 }
486}
487
489{
490 NS_LOG_FUNCTION (this << packet << src << dst << interface);
491 Icmpv6NS nsHeader ("::");
493 uint32_t nb = interface->GetNAddresses ();
494 uint32_t i = 0;
495 bool found = false;
496
497 packet->RemoveHeader (nsHeader);
498
499 Ipv6Address target = nsHeader.GetIpv6Target ();
500
501 for (i = 0; i < nb; i++)
502 {
503 ifaddr = interface->GetAddress (i);
504
505 if (ifaddr.GetAddress () == target)
506 {
507 found = true;
508 break;
509 }
510 }
511
512 if (!found)
513 {
514 NS_LOG_LOGIC ("Not a NS for us");
515 return;
516 }
517
518 if (packet->GetUid () == ifaddr.GetNsDadUid ())
519 {
520 /* don't process our own DAD probe */
521 NS_LOG_LOGIC ("Hey we receive our DAD probe!");
522 return;
523 }
524
525 NdiscCache::Entry* entry = 0;
526 Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
527 uint8_t flags = 0;
528
529 /* search all options following the NS header */
530 Icmpv6OptionLinkLayerAddress sllaoHdr (true);
531
532 bool next = true;
533 bool hasSllao = false;
534
535 while (next == true)
536 {
537 uint8_t type;
538 packet->CopyData (&type, sizeof (type));
539
540 switch (type)
541 {
543 if (!hasSllao)
544 {
545 packet->RemoveHeader (sllaoHdr);
546 hasSllao = true;
547 }
548 break;
549 default:
550 /* unknow option, quit */
551 next = false;
552 }
553 if (packet->GetSize () == 0)
554 {
555 next = false;
556 }
557 }
558
559 Address replyMacAddress;
560
561 if (src != Ipv6Address::GetAny ())
562 {
563 entry = cache->Lookup (src);
564 if (!entry)
565 {
566 if (!hasSllao)
567 {
568 NS_LOG_LOGIC ("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a NCE, discarding.");
569 return;
570 }
571 entry = cache->Add (src);
572 entry->SetRouter (false);
573 entry->MarkStale (sllaoHdr.GetAddress ());
574 replyMacAddress = sllaoHdr.GetAddress ();
575 }
576 else if (hasSllao && (entry->GetMacAddress () != sllaoHdr.GetAddress ()))
577 {
578 entry->MarkStale (sllaoHdr.GetAddress ());
579 replyMacAddress = sllaoHdr.GetAddress ();
580 }
581 else
582 {
583 replyMacAddress = entry->GetMacAddress ();
584 }
585
586 flags = 3; /* S + O flags */
587 }
588 else
589 {
590 /* it's a DAD */
591 flags = 1; /* O flag */
592 replyMacAddress = interface->GetDevice ()->GetMulticast (dst);
593 }
594
595 /* send a NA to src */
597
598 if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
599 {
600 flags += 4; /* R flag */
601 }
602
603 Address hardwareAddress = interface->GetDevice ()->GetAddress ();
605 src.IsAny () ? dst : src, // DAD replies must go to the multicast group it was sent to.
606 &hardwareAddress,
607 flags );
608
609 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not change it beyond what we did already).
610 Ptr<Packet> pkt = p.first;
611 pkt->AddHeader (p.second);
612 interface->GetDevice ()->Send (pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
613}
614
616{
617 NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
618 Ptr<Packet> p = Create<Packet> ();
619 Ipv6Header ipHeader;
620 Icmpv6RS rs;
621
622 NS_LOG_LOGIC ("Forge RS (from " << src << " to " << dst << ")");
623 // RFC 4861:
624 // The link-layer address of the sender MUST NOT be included if the Source Address is the unspecified address.
625 // Otherwise, it SHOULD be included on link layers that have addresses.
626 if (!src.IsAny ())
627 {
628 Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
629 p->AddHeader (llOption);
630 }
631
633 p->AddHeader (rs);
634
635 ipHeader.SetSource (src);
636 ipHeader.SetDestination (dst);
637 ipHeader.SetNextHeader (PROT_NUMBER);
638 ipHeader.SetPayloadLength (p->GetSize ());
639 ipHeader.SetHopLimit (255);
640
641 return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
642}
643
645{
646 NS_LOG_FUNCTION (this << src << dst << id << seq << data);
647 Ptr<Packet> p = data->Copy ();
648 Ipv6Header ipHeader;
649 Icmpv6Echo req (1);
650
651 req.SetId (id);
652 req.SetSeq (seq);
653
655 p->AddHeader (req);
656
657 ipHeader.SetSource (src);
658 ipHeader.SetDestination (dst);
659 ipHeader.SetNextHeader (PROT_NUMBER);
660 ipHeader.SetPayloadLength (p->GetSize ());
661 ipHeader.SetHopLimit (255);
662
663 return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
664}
665
667{
668 NS_LOG_FUNCTION (this << packet << src << dst << interface);
669 Icmpv6NA naHeader;
671
672 packet->RemoveHeader (naHeader);
673 Ipv6Address target = naHeader.GetIpv6Target ();
674
675 Address hardwareAddress;
676 NdiscCache::Entry* entry = 0;
677 Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
678 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
679
680 /* check if we have something in our cache */
681 entry = cache->Lookup (target);
682
683 if (!entry)
684 {
685 /* ouch!! we might be victim of a DAD */
686
688 bool found = false;
689 uint32_t i = 0;
690 uint32_t nb = interface->GetNAddresses ();
691
692 for (i = 0; i < nb; i++)
693 {
694 ifaddr = interface->GetAddress (i);
695 if (ifaddr.GetAddress () == target)
696 {
697 found = true;
698 break;
699 }
700 }
701
702 if (found)
703 {
705 {
706 interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::INVALID);
707 }
708 }
709
710 /* we have not initiated any communication with the target so... discard the NA */
711 return;
712 }
713
714 /* XXX search all options following the NA header */
715 /* Get LLA */
716 uint8_t type;
717 packet->CopyData (&type, sizeof(type));
718
720 {
721 return;
722 }
723 packet->RemoveHeader (lla);
724
725 if (entry->IsIncomplete ())
726 {
727 /* we receive a NA so stop the retransmission timer */
728 entry->StopNudTimer ();
729
730 if (naHeader.GetFlagS ())
731 {
732 /* mark it to reachable */
733 waiting = entry->MarkReachable (lla.GetAddress ());
734 entry->StartReachableTimer ();
735 /* send out waiting packet */
736 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
737 {
738 cache->GetInterface ()->Send (it->first, it->second, src);
739 }
740 entry->ClearWaitingPacket ();
741 }
742 else
743 {
744 entry->MarkStale (lla.GetAddress ());
745 }
746
747 if (naHeader.GetFlagR ())
748 {
749 entry->SetRouter (true);
750 }
751 }
752 else
753 {
754 /* we receive a NA so stop the probe timer or delay timer if any */
755 entry->StopNudTimer ();
756
757 /* if the Flag O is clear and mac address differs from the cache */
758 if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
759 {
760 if (entry->IsReachable ())
761 {
762 entry->MarkStale ();
763 }
764 return;
765 }
766 else
767 {
768 if ((!naHeader.GetFlagO () && lla.GetAddress () == entry->GetMacAddress ()) || naHeader.GetFlagO ()) /* XXX lake "no target link-layer address option supplied" */
769 {
770 entry->SetMacAddress (lla.GetAddress ());
771
772 if (naHeader.GetFlagS ())
773 {
774 if (!entry->IsReachable () || !entry->IsPermanent ())
775 {
776 if (entry->IsProbe ())
777 {
778 waiting = entry->MarkReachable (lla.GetAddress ());
779 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
780 {
781 cache->GetInterface ()->Send (it->first, it->second, src);
782 }
783 entry->ClearWaitingPacket ();
784 }
785 else
786 {
787 entry->MarkReachable (lla.GetAddress ());
788 }
789 }
790 if (!entry->IsPermanent ())
791 {
792 entry->StartReachableTimer ();
793 }
794 }
795 else if (lla.GetAddress () != entry->GetMacAddress ())
796 {
797 entry->MarkStale ();
798 }
799 entry->SetRouter (naHeader.GetFlagR ());
800 }
801 }
802 }
803}
804
806{
807 NS_LOG_FUNCTION (this << packet << src << dst << interface);
808 bool hasLla = false;
809 Ptr<Packet> p = packet->Copy ();
810 Icmpv6OptionLinkLayerAddress llOptionHeader (0);
811
812 Icmpv6Redirection redirectionHeader;
813 p->RemoveHeader (redirectionHeader);
814
815 /* little ugly try to find a better way */
816 uint8_t type;
817 p->CopyData (&type, sizeof(type));
819 {
820 hasLla = true;
821 p->RemoveHeader (llOptionHeader);
822 }
823
824 Icmpv6OptionRedirected redirectedOptionHeader;
825 p->RemoveHeader (redirectedOptionHeader);
826
827 Ipv6Address redirTarget = redirectionHeader.GetTarget ();
828 Ipv6Address redirDestination = redirectionHeader.GetDestination ();
829
830 if (hasLla)
831 {
832 /* update the cache if needed */
833 NdiscCache::Entry* entry = 0;
834 Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
835
836 entry = cache->Lookup (redirTarget);
837 if (!entry)
838 {
839 entry = cache->Add (redirTarget);
840 /* destination and target different => necessarily a router */
841 entry->SetRouter (redirTarget != redirDestination);
842 entry->SetMacAddress (llOptionHeader.GetAddress ());
843 entry->MarkStale ();
844 }
845 else
846 {
847 if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
848 {
849 /* update entry to STALE */
850 if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
851 {
852 entry->SetMacAddress (llOptionHeader.GetAddress ());
853 entry->MarkStale ();
854 }
855 }
856 else
857 {
858 /* stay unchanged */
859 }
860 }
861 }
862
863 /* add redirection in routing table */
864 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
865
866 if (redirTarget == redirDestination)
867 {
868 ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), Ipv6Address ("::"), ipv6->GetInterfaceForAddress (dst));
869 }
870 else
871 {
872 uint32_t ifIndex = ipv6->GetInterfaceForAddress (dst);
873 ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), redirTarget, ifIndex);
874 }
875}
876
878{
879 NS_LOG_FUNCTION (this << *p << src << dst << interface);
880 Ptr<Packet> pkt = p->Copy ();
881
883 pkt->RemoveHeader (unreach);
884
885 Ipv6Header ipHeader;
886 if (pkt->GetSize () > ipHeader.GetSerializedSize ())
887 {
888 pkt->RemoveHeader (ipHeader);
889 uint8_t payload[8];
890 pkt->CopyData (payload, 8);
891 Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
892 }
893}
894
896{
897 NS_LOG_FUNCTION (this << *p << src << dst << interface);
898 Ptr<Packet> pkt = p->Copy ();
899
900 Icmpv6TimeExceeded timeexceeded;
901 pkt->RemoveHeader (timeexceeded);
902
903 Ipv6Header ipHeader;
904 if (pkt->GetSize () > ipHeader.GetSerializedSize ())
905 {
906 Ipv6Header ipHeader;
907 pkt->RemoveHeader (ipHeader);
908 uint8_t payload[8];
909 pkt->CopyData (payload, 8);
910 Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
911 }
912}
913
915{
916 NS_LOG_FUNCTION (this << *p << src << dst << interface);
917 Ptr<Packet> pkt = p->Copy ();
918
919 Icmpv6TooBig tooBig;
920 pkt->RemoveHeader (tooBig);
921
922 Ipv6Header ipHeader;
923 if (pkt->GetSize () > ipHeader.GetSerializedSize ())
924 {
925 pkt->RemoveHeader (ipHeader);
926 uint8_t payload[8];
927 pkt->CopyData (payload, 8);
928
930 ipv6->SetPmtu (ipHeader.GetDestination (), tooBig.GetMtu ());
931
932 Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
933 }
934}
935
937{
938 NS_LOG_FUNCTION (this << *p << src << dst << interface);
939 Ptr<Packet> pkt = p->Copy ();
940
941 Icmpv6ParameterError paramErr;
942 pkt->RemoveHeader (paramErr);
943
944 Ipv6Header ipHeader;
945 if (pkt->GetSize () > ipHeader.GetSerializedSize ())
946 {
947 pkt->RemoveHeader (ipHeader);
948 uint8_t payload[8];
949 pkt->CopyData (payload, 8);
950 Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
951 }
952}
953
955{
956 NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
959 NS_ASSERT (ipv6 != 0);
960
961 tag.SetHopLimit (ttl);
962 packet->AddPacketTag (tag);
963 m_downTarget (packet, src, dst, PROT_NUMBER, 0);
964}
965
967{
968 NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
969 SendMessage (packet, src, dst, ttl);
970}
971
972void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
973{
974 NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
976 NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
977 Ipv6Header header;
980 Ptr<Ipv6Route> route;
981 Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
982
983 header.SetDestination (dst);
984 route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
985
986 if (route != 0)
987 {
988 NS_LOG_LOGIC ("Route exists");
989 tag.SetHopLimit (ttl);
990 packet->AddPacketTag (tag);
991 Ipv6Address src = route->GetSource ();
992
993 icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
994 packet->AddHeader (icmpv6Hdr);
995 m_downTarget (packet, src, dst, PROT_NUMBER, route);
996 }
997 else
998 {
999 NS_LOG_WARN ("drop icmp message");
1000 }
1001}
1002
1003void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1004{
1005 NS_LOG_FUNCTION (this << src << dst << hardwareAddress << static_cast<uint32_t> (flags));
1006 Ptr<Packet> p = Create<Packet> ();
1007 Icmpv6NA na;
1008 Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
1009
1010 NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1011 na.SetIpv6Target (src);
1012
1013 if ((flags & 1))
1014 {
1015 na.SetFlagO (true);
1016 }
1017 if ((flags & 2) && src != Ipv6Address::GetAny ())
1018 {
1019 na.SetFlagS (true);
1020 }
1021 if ((flags & 4))
1022 {
1023 na.SetFlagR (true);
1024 }
1025
1026 p->AddHeader (llOption);
1028 p->AddHeader (na);
1029
1030 SendMessage (p, src, dst, 255);
1031}
1032
1034{
1035 NS_LOG_FUNCTION (this << src << dst << id << seq << data);
1036 Ptr<Packet> p = data->Copy ();
1037 Icmpv6Echo reply (0); /* echo reply */
1038
1039 reply.SetId (id);
1040 reply.SetSeq (seq);
1041
1042 reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
1043 p->AddHeader (reply);
1044 SendMessage (p, src, dst, 64);
1045}
1046
1048{
1049 NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1050 Ptr<Packet> p = Create<Packet> ();
1051 /* Ipv6Header ipHeader; */
1052 Icmpv6NS ns (target);
1053 Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1054
1055 /* if the source is unspec, multicast the NA to all-nodes multicast */
1056 if (src == Ipv6Address::GetAny ())
1057 {
1059 }
1060
1061 NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1062
1063 p->AddHeader (llOption);
1065 p->AddHeader (ns);
1066 if (!dst.IsMulticast ())
1067 {
1068 SendMessage (p, src, dst, 255);
1069 }
1070 else
1071 {
1072 NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1074 }
1075}
1076
1078{
1079 NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
1080 Ptr<Packet> p = Create<Packet> ();
1081 Icmpv6RS rs;
1082
1083 // RFC 4861:
1084 // The link-layer address of the sender MUST NOT be included if the Source Address is the unspecified address.
1085 // Otherwise, it SHOULD be included on link layers that have addresses.
1086 if (!src.IsAny ())
1087 {
1088 Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);
1089 p->AddHeader (llOption);
1090 }
1091
1092 NS_LOG_LOGIC ("Send RS (from " << src << " to " << dst << ")");
1093
1095 p->AddHeader (rs);
1096 if (!dst.IsMulticast ())
1097 {
1098 SendMessage (p, src, dst, 255);
1099 }
1100 else
1101 {
1102 NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1104 }
1105}
1106
1108{
1109 NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
1110 uint32_t malformedPacketSize = malformedPacket->GetSize ();
1112 header.SetCode (code);
1113
1114 NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1115
1116 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1117 if (malformedPacketSize <= 1280 - 48)
1118 {
1119 header.SetPacket (malformedPacket);
1120 SendMessage (malformedPacket, dst, header, 255);
1121 }
1122 else
1123 {
1124 Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1125 header.SetPacket (fragment);
1126 SendMessage (fragment, dst, header, 255);
1127 }
1128}
1129
1131{
1132 NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
1133 uint32_t malformedPacketSize = malformedPacket->GetSize ();
1134 Icmpv6TooBig header;
1135 header.SetCode (0);
1136 header.SetMtu (mtu);
1137
1138 NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
1139
1140 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1141 if (malformedPacketSize <= 1280 - 48)
1142 {
1143 header.SetPacket (malformedPacket);
1144 SendMessage (malformedPacket, dst, header, 255);
1145 }
1146 else
1147 {
1148 Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1149 header.SetPacket (fragment);
1150 SendMessage (fragment, dst, header, 255);
1151 }
1152}
1153
1154void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
1155{
1156 NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code));
1157 uint32_t malformedPacketSize = malformedPacket->GetSize ();
1158 Icmpv6TimeExceeded header;
1159 header.SetCode (code);
1160
1161 NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1162
1163 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1164 if (malformedPacketSize <= 1280 - 48)
1165 {
1166 header.SetPacket (malformedPacket);
1167 SendMessage (malformedPacket, dst, header, 255);
1168 }
1169 else
1170 {
1171 Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1172 header.SetPacket (fragment);
1173 SendMessage (fragment, dst, header, 255);
1174 }
1175}
1176
1178{
1179 NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code) << ptr);
1180 uint32_t malformedPacketSize = malformedPacket->GetSize ();
1181 Icmpv6ParameterError header;
1182 header.SetCode (code);
1183 header.SetPtr (ptr);
1184
1185 NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1186
1187 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1188 if (malformedPacketSize <= 1280 - 48 )
1189 {
1190 header.SetPacket (malformedPacket);
1191 SendMessage (malformedPacket, dst, header, 255);
1192 }
1193 else
1194 {
1195 Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1196 header.SetPacket (fragment);
1197 SendMessage (fragment, dst, header, 255);
1198 }
1199}
1200
1201void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
1202{
1203 NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
1204 uint32_t llaSize = 0;
1205 Ptr<Packet> p = Create<Packet> ();
1206 uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
1207 Icmpv6OptionLinkLayerAddress llOption (0);
1208
1209 NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
1210
1211 Icmpv6OptionRedirected redirectedOptionHeader;
1212
1213 if ((redirectedPacketSize % 8) != 0)
1214 {
1215 Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
1216 redirectedPacket->AddAtEnd (pad);
1217 }
1218
1219 if (redirHardwareTarget.GetLength ())
1220 {
1221 llOption.SetAddress (redirHardwareTarget);
1222 llaSize = llOption.GetSerializedSize ();
1223 }
1224
1225 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1226 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1227 {
1228 redirectedOptionHeader.SetPacket (redirectedPacket);
1229 }
1230 else
1231 {
1232 Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
1233 redirectedOptionHeader.SetPacket (fragment);
1234 }
1235
1236 p->AddHeader (redirectedOptionHeader);
1237
1238 if (llaSize)
1239 {
1240 p->AddHeader (llOption);
1241 }
1242
1243 Icmpv6Redirection redirectionHeader;
1244 redirectionHeader.SetTarget (redirTarget);
1245 redirectionHeader.SetDestination (redirDestination);
1246 redirectionHeader.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + redirectionHeader.GetSerializedSize (), PROT_NUMBER);
1247 p->AddHeader (redirectionHeader);
1248
1249 SendMessage (p, src, dst, 64);
1250}
1251
1253{
1254 NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
1255 Ptr<Packet> p = Create<Packet> ();
1256 Ipv6Header ipHeader;
1257 Icmpv6NA na;
1258 Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* we give our mac address in response */
1259
1260 NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
1261
1262 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
1263
1264 p->AddHeader (llOption);
1265 na.SetIpv6Target (src);
1266
1267 if ((flags & 1))
1268 {
1269 na.SetFlagO (true);
1270 }
1271 if ((flags & 2) && src != Ipv6Address::GetAny ())
1272 {
1273 na.SetFlagS (true);
1274 }
1275 if ((flags & 4))
1276 {
1277 na.SetFlagR (true);
1278 }
1279
1281 p->AddHeader (na);
1282
1283 ipHeader.SetSource (src);
1284 ipHeader.SetDestination (dst);
1285 ipHeader.SetNextHeader (PROT_NUMBER);
1286 ipHeader.SetPayloadLength (p->GetSize ());
1287 ipHeader.SetHopLimit (255);
1288
1289 return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1290}
1291
1293{
1294 NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1295 Ptr<Packet> p = Create<Packet> ();
1296 Ipv6Header ipHeader;
1297 Icmpv6NS ns (target);
1298 Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1299
1300 NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1301
1302 p->AddHeader (llOption);
1304 p->AddHeader (ns);
1305
1306 ipHeader.SetSource (src);
1307 ipHeader.SetDestination (dst);
1308 ipHeader.SetNextHeader (PROT_NUMBER);
1309 ipHeader.SetPayloadLength (p->GetSize ());
1310 ipHeader.SetHopLimit (255);
1311
1312 return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1313}
1314
1316{
1317 NS_LOG_FUNCTION (this << device);
1318
1319 for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
1320 {
1321 if ((*i)->GetDevice () == device)
1322 {
1323 return *i;
1324 }
1325 }
1326
1327 NS_ASSERT_MSG (false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1328 /* quiet compiler */
1329 return 0;
1330}
1331
1333{
1334 NS_LOG_FUNCTION (this << device << interface);
1335
1336 Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
1337
1338 cache->SetDevice (device, interface, this);
1340 m_cacheList.push_back (cache);
1341 return cache;
1342}
1343
1344bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1345{
1346 NS_LOG_FUNCTION (this << dst << device << cache << hardwareDestination);
1347
1348 if (!cache)
1349 {
1350 /* try to find the cache */
1351 cache = FindCache (device);
1352 }
1353 if (cache)
1354 {
1355 NdiscCache::Entry* entry = cache->Lookup (dst);
1356 if (entry)
1357 {
1358 if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1359 {
1360 *hardwareDestination = entry->GetMacAddress ();
1361 return true;
1362 }
1363 else if (entry->IsStale ())
1364 {
1365 entry->StartDelayTimer ();
1366 entry->MarkDelay ();
1367 *hardwareDestination = entry->GetMacAddress ();
1368 return true;
1369 }
1370 }
1371 }
1372 return false;
1373}
1374
1375bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1376{
1377 NS_LOG_FUNCTION (this << p << ipHeader << dst << device << cache << hardwareDestination);
1378
1379 if (!cache)
1380 {
1381 /* try to find the cache */
1382 cache = FindCache (device);
1383 }
1384 if (!cache)
1385 {
1386 return false;
1387 }
1388
1389 NdiscCache::Entry* entry = cache->Lookup (dst);
1390 if (entry)
1391 {
1392 if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1393 {
1394 /* XXX check reachability time */
1395 /* send packet */
1396 *hardwareDestination = entry->GetMacAddress ();
1397 return true;
1398 }
1399 else if (entry->IsStale ())
1400 {
1401 /* start delay timer */
1402 entry->StartDelayTimer ();
1403 entry->MarkDelay ();
1404 *hardwareDestination = entry->GetMacAddress ();
1405 return true;
1406 }
1407 else /* INCOMPLETE or PROBE */
1408 {
1409 /* queue packet */
1411 return false;
1412 }
1413 }
1414 else
1415 {
1416 /* we contact this node for the first time
1417 * add it to the cache and send an NS
1418 */
1419 Ipv6Address addr;
1420 NdiscCache::Entry* entry = cache->Add (dst);
1422 entry->SetRouter (false);
1423
1424 if (dst.IsLinkLocal ())
1425 {
1426 addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
1427 }
1428 else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
1429 {
1430 /* try to resolve global address without having global address so return! */
1431 cache->Remove (entry);
1432 return false;
1433 }
1434 else
1435 {
1436 /* find source address that match destination */
1437 addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
1438 }
1439
1440 SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
1441
1442 /* start retransmit timer */
1443 entry->StartRetransmitTimer ();
1444 return false;
1445 }
1446
1447 return false;
1448}
1449
1451{
1452 NS_LOG_FUNCTION (this << interface << addr);
1453
1454 Ipv6InterfaceAddress ifaddr;
1455 bool found = false;
1456 uint32_t i = 0;
1457 uint32_t nb = interface->GetNAddresses ();
1458
1459 for (i = 0; i < nb; i++)
1460 {
1461 ifaddr = interface->GetAddress (i);
1462
1463 if (ifaddr.GetAddress () == addr)
1464 {
1465 found = true;
1466 break;
1467 }
1468 }
1469
1470 if (!found)
1471 {
1472 NS_LOG_LOGIC ("Can not find the address in the interface.");
1473 }
1474
1475 /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
1476 * and we do not set it to PREFERRED
1477 */
1478 if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
1479 {
1480 interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
1481 NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
1482
1483 /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
1484 * (because we will send RS with it)
1485 */
1486 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
1487
1488 if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
1489 {
1490 /* \todo Add random delays before sending RS
1491 * because all nodes start at the same time, there will be many of RS around 1 second of simulation time
1492 */
1493 NS_LOG_LOGIC ("Scheduled a Router Solicitation");
1495 }
1496 else
1497 {
1498 NS_LOG_LOGIC ("Did not schedule a Router Solicitation because the interface is in forwarding mode");
1499 }
1500 }
1501}
1502
1503void
1505{
1506 NS_LOG_FUNCTION (this << &callback);
1507}
1508
1509void
1511{
1512 NS_LOG_FUNCTION (this << &callback);
1513 m_downTarget = callback;
1514}
1515
1518{
1519 NS_LOG_FUNCTION (this);
1521}
1522
1525{
1526 NS_LOG_FUNCTION (this);
1527 return m_downTarget;
1528}
1529
1530uint8_t
1532{
1533 return m_maxMulticastSolicit;
1534}
1535
1536uint8_t
1538{
1539 return m_maxUnicastSolicit;
1540}
1541
1542Time
1544{
1545 return m_reachableTime;
1546}
1547
1548Time
1550{
1551 return m_retransmissionTime;
1552}
1553
1554Time
1556{
1557 return m_delayFirstProbe;
1558}
1559
1560
1561} /* namespace ns3 */
1562
a polymophic address class
Definition: address.h:91
uint8_t GetLength(void) const
Get the length of the underlying address.
Definition: address.cc:75
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
void Nullify(void)
Discard the implementation, set it to null.
Definition: callback.h:1391
ICMPv6 Error Destination Unreachable header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
ICMPv6 Echo message.
void SetId(uint16_t id)
Set the ID of the packet.
uint16_t GetId() const
Get the ID of the packet.
void SetSeq(uint16_t seq)
Set the sequence number.
uint16_t GetSeq() const
Get the sequence number.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
ICMPv6 header.
Definition: icmpv6-header.h:39
uint8_t GetCode() const
Get the code field.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
uint8_t GetType() const
Get the type field.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
void SetCode(uint8_t code)
Set the code field.
@ ICMPV6_ND_NEIGHBOR_ADVERTISEMENT
Definition: icmpv6-header.h:58
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:46
An implementation of the ICMPv6 protocol.
Time GetRetransmissionTime() const
Neighbor Discovery node constants: retransmission timer.
virtual void SetDownTarget(IpL4Protocol::DownTargetCallback cb)
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void Forward(Ipv6Address source, Icmpv6Header icmp, uint32_t info, Ipv6Header ipHeader, const uint8_t payload[8])
Notify an ICMPv6 reception to upper layers (if requested).
void SendErrorTimeExceeded(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Time Exceeded.
void SendErrorTooBig(Ptr< Packet > malformedPacket, Ipv6Address dst, uint32_t mtu)
Send an error Too Big.
uint8_t m_maxMulticastSolicit
Neighbor Discovery node constants: max multicast solicitations.
Time m_reachableTime
Neighbor Discovery node constants: reachable time.
NdiscCache::Ipv6PayloadHeaderPair ForgeEchoRequest(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Forge an Echo Request.
virtual Ptr< NdiscCache > CreateCache(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Create a neighbor cache.
void DelayedSendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Helper function used during delayed solicitation.
Ptr< Node > GetNode()
Get the node.
bool IsAlwaysDad() const
Is the node must do DAD.
void HandlePacketTooBig(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Packet Too Big method.
void SendErrorParameterError(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
Send an error Parameter Error.
void HandleRS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Solicitation method.
void NotifyNewAggregate()
This method is called by AggregateObject and completes the aggregation by setting the node in the ICM...
Time GetDelayFirstProbe() const
Neighbor Discovery node constants : delay for the first probe.
NdiscCache::Ipv6PayloadHeaderPair ForgeNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Forge a Neighbor Advertisement.
virtual void DoDispose()
Dispose this object.
void HandleNA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Advertisement method.
void FunctionDadTimeout(Ipv6Interface *interface, Ipv6Address addr)
Function called when DAD timeout.
uint8_t m_maxUnicastSolicit
Neighbor Discovery node constants: max unicast solicitations.
void SendRedirection(Ptr< Packet > redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
Send an ICMPv6 Redirection.
Ptr< Node > m_node
The node.
IpL4Protocol::DownTargetCallback6 m_downTarget
callback to Ipv6::Send
Ptr< NdiscCache > FindCache(Ptr< NetDevice > device)
Get the cache corresponding to the device.
void DoDAD(Ipv6Address target, Ptr< Ipv6Interface > interface)
Do the Duplication Address Detection (DAD).
virtual void SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb)
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
bool m_alwaysDad
Always do DAD ?
void SendErrorDestinationUnreachable(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Destination Unreachable.
static const uint8_t PROT_NUMBER
ICMPv6 protocol number (58).
virtual void SendNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Send a Neighbor Solicitation.
virtual ~Icmpv6L4Protocol()
Destructor.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Time m_retransmissionTime
Neighbor Discovery node constants: retransmission timer.
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6(void) const
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
uint8_t GetMaxUnicastSolicit() const
Neighbor Discovery node constants: max unicast solicitations.
void HandleTimeExceeded(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Time Exceeded method.
bool Lookup(Ipv6Address dst, Ptr< NetDevice > device, Ptr< NdiscCache > cache, Address *hardwareDestination)
Lookup in the ND cache for the IPv6 address.
void HandleRedirection(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Redirection method.
void HandleEchoRequest(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Echo Request method.
virtual int GetVersion() const
Get the version of the protocol.
void HandleDestinationUnreachable(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Destination Unreachable method.
Ptr< RandomVariableStream > m_solicitationJitter
Random jitter before sending solicitations.
void SendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Send a packet via ICMPv6, note that packet already contains ICMPv6 header.
Time m_delayFirstProbe
Neighbor Discovery node constants: delay for the first probe.
void HandleNS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Solicitation method.
virtual int GetProtocolNumber() const
Get the protocol number.
void ReceiveLLA(Icmpv6OptionLinkLayerAddress lla, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Link layer address option processing.
void SendEchoReply(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Send a Echo Reply.
NdiscCache::Ipv6PayloadHeaderPair ForgeRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Forge a Router Solicitation.
NdiscCache::Ipv6PayloadHeaderPair ForgeNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Forge a Neighbor Solicitation.
void HandleParameterError(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Parameter Error method.
void SendNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Send a Neighbor Adverstisement.
virtual IpL4Protocol::DownTargetCallback GetDownTarget(void) const
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
static TypeId GetTypeId()
Get the type ID.
Time GetReachableTime() const
Neighbor Discovery node constants: reachable time.
virtual enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > interface)
Receive method.
void HandleRA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
CacheList m_cacheList
A list of cache by device.
uint8_t GetMaxMulticastSolicit() const
Neighbor Discovery node constants: max multicast solicitations.
void SetNode(Ptr< Node > node)
Set the node.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
ICMPv6 Neighbor Advertisement header.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
bool GetFlagS() const
Get the S flag.
void SetFlagS(bool s)
Set the S flag.
void SetIpv6Target(Ipv6Address target)
Set the IPv6 target field.
void SetFlagR(bool r)
Set the R flag.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
bool GetFlagR() const
Get the R flag.
bool GetFlagO() const
Get the O flag.
void SetFlagO(bool o)
Set the O flag.
ICMPv6 Neighbor Solicitation header.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
ICMPv6 MTU option.
ICMPv6 Option Prefix Information.
ICMPv6 redirected option.
void SetPacket(Ptr< Packet > packet)
Set the redirected packet.
ICMPv6 Error Parameter Error header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
void SetPtr(uint32_t ptr)
Set the pointer field.
ICMPv6 Router Advertisement header.
uint16_t GetLifeTime() const
Get the node Life time (Neighbor Discovery).
ICMPv6 Router Solicitation header.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
ICMPv6 Redirection header.
Ipv6Address GetTarget() const
Get the IPv6 target address.
void SetDestination(Ipv6Address destination)
Set the IPv6 destination address.
Ipv6Address GetDestination() const
Get the IPv6 destination address.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void SetTarget(Ipv6Address target)
Set the IPv6 target address.
ICMPv6 Error Time Exceeded header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
ICMPv6 Error Too Big header.
void SetMtu(uint32_t mtu)
Set the MTU.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
uint32_t GetMtu() const
Get the MTU field.
Hold a signed integer type.
Definition: integer.h:44
L4 Protocol abstract base class.
virtual void ReceiveIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, Ipv4Address payloadSource, Ipv4Address payloadDestination, const uint8_t payload[8])
Called from lower-level layers to send the ICMP packet up in the stack.
RxStatus
Rx status codes.
Packet header for IPv4.
Definition: ipv4-header.h:34
Describes an IPv6 address.
Definition: ipv6-address.h:50
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
bool IsAny() const
If the IPv6 address is the "Any" address.
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
Packet header for IPv6.
Definition: ipv6-header.h:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:115
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Ipv6Address GetSource(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:105
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:163
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:85
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
Ipv6Address GetDestination(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:125
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
virtual void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route)=0
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers.
IPv6 address associated with an interface.
Ipv6Address GetAddress() const
Get the IPv6 address.
uint32_t GetNsDadUid() const
Get the latest DAD probe packet UID.
Ipv6InterfaceAddress::State_e GetState() const
Get the address state.
@ TENTATIVE_OPTIMISTIC
Address is tentative but we are optimistic so we can send packet even if DAD is not yet finished.
@ INVALID
Invalid state (after a DAD failed)
@ TENTATIVE
Address is tentative, no packet can be sent unless DAD finished.
The IPv6 representation of a network interface.
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
Ipv6InterfaceAddress GetAddressMatchingDestination(Ipv6Address dst)
Get an address which is in the same network prefix as destination.
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
void SetNsDadUid(Ipv6Address address, uint32_t uid)
Update NS DAD packet UID of an interface address.
void Send(Ptr< Packet > p, const Ipv6Header &hdr, Ipv6Address dest)
Send a packet through this interface.
uint32_t GetNAddresses(void) const
Get number of addresses on this IPv6 interface.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
IPv6 layer implementation.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:456
A record that holds information about a NdiscCache entry.
Definition: ndisc-cache.h:161
bool IsPermanent() const
Is the entry PERMANENT.
Definition: ndisc-cache.cc:587
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:264
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:536
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:424
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:593
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:466
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:510
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:575
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:569
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:479
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:499
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:557
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:599
bool IsProbe() const
Is the entry PROBE.
Definition: ndisc-cache.cc:581
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:544
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:239
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:251
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:563
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
Definition: ndisc-cache.cc:492
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface, Ptr< Icmpv6L4Protocol > icmpv6)
Set the device and interface.
Definition: ndisc-cache.cc:73
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: ndisc-cache.h:153
virtual NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:126
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:153
void Remove(NdiscCache::Entry *entry)
Delete an entry.
Definition: ndisc-cache.cc:137
virtual NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:93
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:87
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:81
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
virtual Address GetAddress(void) const =0
virtual Address GetMulticast(Ipv4Address multicastGroup) const =0
Make and return a MAC multicast address using the provided multicast group.
virtual void AddLinkChangeCallback(Callback< void > callback)=0
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1165
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:665
Hold variables of type string.
Definition: string.h:41
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:45
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:536
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
uint8_t data[writeSize]