A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
sixlowpan-net-device.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Universita' di Firenze, Italy
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18 * Michele Muccio <michelemuccio@virgilio.it>
19 */
20
22
23#include "sixlowpan-header.h"
24
25#include "ns3/boolean.h"
26#include "ns3/channel.h"
27#include "ns3/ipv6-extension-header.h"
28#include "ns3/ipv6-l3-protocol.h"
29#include "ns3/log.h"
30#include "ns3/mac16-address.h"
31#include "ns3/mac48-address.h"
32#include "ns3/mac64-address.h"
33#include "ns3/node.h"
34#include "ns3/packet.h"
35#include "ns3/pointer.h"
36#include "ns3/simulator.h"
37#include "ns3/string.h"
38#include "ns3/udp-header.h"
39#include "ns3/udp-l4-protocol.h"
40#include "ns3/uinteger.h"
41
42#include <algorithm>
43
44NS_LOG_COMPONENT_DEFINE("SixLowPanNetDevice");
45
46namespace ns3
47{
48
49NS_OBJECT_ENSURE_REGISTERED(SixLowPanNetDevice);
50
51TypeId
53{
54 static TypeId tid =
55 TypeId("ns3::SixLowPanNetDevice")
57 .SetGroupName("SixLowPan")
58 .AddConstructor<SixLowPanNetDevice>()
59 .AddAttribute("Rfc6282",
60 "Use RFC6282 (IPHC) if true, RFC4944 (HC1) otherwise.",
61 BooleanValue(true),
64 .AddAttribute("OmitUdpChecksum",
65 "Omit the UDP checksum in IPHC compression.",
66 BooleanValue(true),
69 .AddAttribute(
70 "FragmentReassemblyListSize",
71 "The maximum size of the reassembly buffer (in packets). Zero meaning infinite.",
74 MakeUintegerChecker<uint16_t>())
75 .AddAttribute(
76 "FragmentExpirationTimeout",
77 "When this timeout expires, the fragments will be cleared from the buffer.",
78 TimeValue(Seconds(60)),
81 .AddAttribute("CompressionThreshold",
82 "The minimum MAC layer payload size.",
83 UintegerValue(0x0),
85 MakeUintegerChecker<uint32_t>())
86 .AddAttribute("ForceEtherType",
87 "Force a specific EtherType in L2 frames.",
88 BooleanValue(false),
91 .AddAttribute("EtherType",
92 "The specific EtherType to be used in L2 frames.",
93 UintegerValue(0xFFFF),
95 MakeUintegerChecker<uint16_t>())
96 .AddAttribute("UseMeshUnder",
97 "Use a mesh-under routing protocol.",
98 BooleanValue(false),
101 .AddAttribute("MeshUnderRadius",
102 "Hops Left to use in mesh-under.",
103 UintegerValue(10),
105 MakeUintegerChecker<uint8_t>())
106 .AddAttribute("MeshCacheLength",
107 "Length of the cache for each source.",
108 UintegerValue(10),
110 MakeUintegerChecker<uint16_t>())
111 .AddAttribute("MeshUnderJitter",
112 "The jitter in ms a node uses to forward mesh-under packets - used to "
113 "prevent collisions",
114 StringValue("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
116 MakePointerChecker<RandomVariableStream>())
117 .AddTraceSource("Tx",
118 "Send - packet (including 6LoWPAN header), "
119 "SixLoWPanNetDevice Ptr, interface index.",
121 "ns3::SixLowPanNetDevice::RxTxTracedCallback")
122 .AddTraceSource("Rx",
123 "Receive - packet (including 6LoWPAN header), "
124 "SixLoWPanNetDevice Ptr, interface index.",
126 "ns3::SixLowPanNetDevice::RxTxTracedCallback")
127 .AddTraceSource("Drop",
128 "Drop - DropReason, packet (including 6LoWPAN header), "
129 "SixLoWPanNetDevice Ptr, interface index.",
131 "ns3::SixLowPanNetDevice::DropTracedCallback");
132 return tid;
133}
134
136 : m_node(nullptr),
137 m_netDevice(nullptr),
138 m_ifIndex(0)
139{
140 NS_LOG_FUNCTION(this);
141 m_netDevice = nullptr;
142 m_rng = CreateObject<UniformRandomVariable>();
143 m_bc0Serial = 0;
144}
145
148{
149 NS_LOG_FUNCTION(this);
150 return m_netDevice;
151}
152
153void
155{
156 NS_LOG_FUNCTION(this << device);
157 m_netDevice = device;
158
159 NS_LOG_DEBUG("RegisterProtocolHandler for " << device->GetInstanceTypeId().GetName());
160
161 uint16_t protocolType = 0;
163 {
164 protocolType = m_etherType;
165 }
167 protocolType,
168 device,
169 false);
170}
171
172int64_t
174{
175 NS_LOG_FUNCTION(this << stream);
176 m_rng->SetStream(stream);
177 m_meshUnderJitter->SetStream(stream + 1);
178 return 2;
179}
180
181void
183{
184 NS_LOG_FUNCTION(this);
185
186 m_netDevice = nullptr;
187 m_node = nullptr;
188
189 m_timeoutEventList.clear();
191 {
193 }
194
195 for (auto iter = m_fragments.begin(); iter != m_fragments.end(); iter++)
196 {
197 iter->second = nullptr;
198 }
199 m_fragments.clear();
200
202}
203
204void
206 Ptr<const Packet> packet,
207 uint16_t protocol,
208 const Address& src,
209 const Address& dst,
210 PacketType packetType)
211{
212 NS_LOG_FUNCTION(this << incomingPort << packet << protocol << src << dst);
213
214 uint8_t dispatchRawVal = 0;
216 Ptr<Packet> copyPkt = packet->Copy();
217
218 m_rxTrace(copyPkt, this, GetIfIndex());
219
220 copyPkt->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
221 dispatchVal = SixLowPanDispatch::GetDispatchType(dispatchRawVal);
222 bool isPktDecompressed = false;
223 bool fragmented = false;
224
225 NS_LOG_DEBUG("Packet received: " << *copyPkt);
226 NS_LOG_DEBUG("Packet length: " << copyPkt->GetSize());
227 NS_LOG_DEBUG("Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal));
228
229 SixLowPanMesh meshHdr;
230 SixLowPanBc0 bc0Hdr;
231 bool hasMesh = false;
232 bool hasBc0 = false;
233
234 if (dispatchVal == SixLowPanDispatch::LOWPAN_MESH)
235 {
236 hasMesh = true;
237 copyPkt->RemoveHeader(meshHdr);
238 copyPkt->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
239 dispatchVal = SixLowPanDispatch::GetDispatchType(dispatchRawVal);
240 }
241 if (dispatchVal == SixLowPanDispatch::LOWPAN_BC0)
242 {
243 hasBc0 = true;
244 copyPkt->RemoveHeader(bc0Hdr);
245 copyPkt->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
246 dispatchVal = SixLowPanDispatch::GetDispatchType(dispatchRawVal);
247 }
248
249 if (hasMesh)
250 {
251 if (!hasBc0)
252 {
253 NS_LOG_LOGIC("Dropped packet - we only support mesh if it is paired with a BC0");
255 return;
256 }
257
258 if (find(m_seenPkts[meshHdr.GetOriginator()].begin(),
259 m_seenPkts[meshHdr.GetOriginator()].end(),
260 bc0Hdr.GetSequenceNumber()) != m_seenPkts[meshHdr.GetOriginator()].end())
261 {
262 NS_LOG_LOGIC("We have already seen this, no further processing.");
263 return;
264 }
265
266 m_seenPkts[meshHdr.GetOriginator()].push_back(bc0Hdr.GetSequenceNumber());
267 if (m_seenPkts[meshHdr.GetOriginator()].size() > m_meshCacheLength)
268 {
269 m_seenPkts[meshHdr.GetOriginator()].pop_front();
270 }
271
273 "SixLowPan mesh-under flooding can not currently handle extended address "
274 "final destinations: "
275 << meshHdr.GetFinalDst());
277 "SixLowPan mesh-under flooding can not currently handle devices using "
278 "extended addresses: "
279 << m_netDevice->GetAddress());
280
282
283 // See if the packet is for others than me. In case forward it.
284 if (meshHdr.GetFinalDst() != Get16MacFrom48Mac(m_netDevice->GetAddress()) ||
285 finalDst.IsBroadcast() || finalDst.IsMulticast())
286 {
287 uint8_t hopsLeft = meshHdr.GetHopsLeft();
288
289 if (hopsLeft == 0)
290 {
291 NS_LOG_LOGIC("Not forwarding packet -- hop limit reached");
292 }
293 else if (meshHdr.GetOriginator() == Get16MacFrom48Mac(m_netDevice->GetAddress()))
294 {
295 NS_LOG_LOGIC("Not forwarding packet -- I am the originator");
296 }
297 else
298 {
299 meshHdr.SetHopsLeft(hopsLeft - 1);
300 Ptr<Packet> sendPkt = copyPkt->Copy();
301 sendPkt->AddHeader(bc0Hdr);
302 sendPkt->AddHeader(meshHdr);
306 sendPkt,
307 m_netDevice->GetBroadcast(),
308 protocol);
309 }
310
311 if (!finalDst.IsBroadcast() && !finalDst.IsMulticast())
312 {
313 return;
314 }
315 }
316 }
317
318 Address realDst = dst;
319 Address realSrc = src;
320 if (hasMesh)
321 {
322 realSrc = meshHdr.GetOriginator();
323 realDst = meshHdr.GetFinalDst();
324 }
325
326 if (dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1)
327 {
328 isPktDecompressed = ProcessFragment(copyPkt, realSrc, realDst, true);
329 fragmented = true;
330 }
331 else if (dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN)
332 {
333 isPktDecompressed = ProcessFragment(copyPkt, realSrc, realDst, false);
334 fragmented = true;
335 }
336 if (fragmented)
337 {
338 if (!isPktDecompressed)
339 {
340 return;
341 }
342 else
343 {
344 copyPkt->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
345 dispatchVal = SixLowPanDispatch::GetDispatchType(dispatchRawVal);
346 }
347 }
348
349 switch (dispatchVal)
350 {
352 NS_LOG_DEBUG("Packet without compression. Length: " << copyPkt->GetSize());
353 {
354 SixLowPanIpv6 uncompressedHdr;
355 copyPkt->RemoveHeader(uncompressedHdr);
356 isPktDecompressed = true;
357 }
358 break;
360 if (m_useIphc)
361 {
363 return;
364 }
365 DecompressLowPanHc1(copyPkt, realSrc, realDst);
366 isPktDecompressed = true;
367 break;
369 if (!m_useIphc)
370 {
372 return;
373 }
374 if (DecompressLowPanIphc(copyPkt, realSrc, realDst))
375 {
377 }
378 else
379 {
380 isPktDecompressed = true;
381 }
382 break;
383 default:
384 NS_LOG_DEBUG("Unsupported 6LoWPAN encoding: dropping.");
386 break;
387 }
388
389 if (!isPktDecompressed)
390 {
391 return;
392 }
393
394 NS_LOG_DEBUG("Packet decompressed length: " << copyPkt->GetSize());
395 NS_LOG_DEBUG("Packet decompressed received: " << *copyPkt);
396
398 {
400 copyPkt,
402 realSrc,
403 realDst,
404 packetType);
405 }
406
407 m_rxCallback(this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc);
408}
409
410void
412{
413 NS_LOG_FUNCTION(this << index);
414 m_ifIndex = index;
415}
416
419{
420 NS_LOG_FUNCTION(this);
421 return m_ifIndex;
422}
423
426{
427 NS_LOG_FUNCTION(this);
428 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
429
430 return m_netDevice->GetChannel();
431}
432
433void
435{
436 NS_LOG_FUNCTION(this << address);
437 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
438
439 m_netDevice->SetAddress(address);
440}
441
444{
445 NS_LOG_FUNCTION(this);
446 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
447
448 return m_netDevice->GetAddress();
449}
450
451bool
452SixLowPanNetDevice::SetMtu(const uint16_t mtu)
453{
454 NS_LOG_FUNCTION(this << mtu);
455 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
456
457 return m_netDevice->SetMtu(mtu);
458}
459
460uint16_t
462{
463 NS_LOG_FUNCTION(this);
464
465 uint16_t mtu = m_netDevice->GetMtu();
466
467 // RFC 4944, section 4.
468 if (mtu < 1280)
469 {
470 mtu = 1280;
471 }
472 return mtu;
473}
474
475bool
477{
478 NS_LOG_FUNCTION(this);
479 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
480
481 return m_netDevice->IsLinkUp();
482}
483
484void
486{
487 NS_LOG_FUNCTION(this);
488 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
489
490 return m_netDevice->AddLinkChangeCallback(callback);
491}
492
493bool
495{
496 NS_LOG_FUNCTION(this);
497 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
498
499 return m_netDevice->IsBroadcast();
500}
501
504{
505 NS_LOG_FUNCTION(this);
506 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
507
508 return m_netDevice->GetBroadcast();
509}
510
511bool
513{
514 NS_LOG_FUNCTION(this);
515 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
516
517 return m_netDevice->IsMulticast();
518}
519
522{
523 NS_LOG_FUNCTION(this << multicastGroup);
524 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
525
526 return m_netDevice->GetMulticast(multicastGroup);
527}
528
531{
532 NS_LOG_FUNCTION(this << addr);
533 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
534
535 return m_netDevice->GetMulticast(addr);
536}
537
538bool
540{
541 NS_LOG_FUNCTION(this);
542 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
543
544 return m_netDevice->IsPointToPoint();
545}
546
547bool
549{
550 NS_LOG_FUNCTION(this);
551 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
552
553 return m_netDevice->IsBridge();
554}
555
556bool
557SixLowPanNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
558{
559 NS_LOG_FUNCTION(this << *packet << dest << protocolNumber);
560 bool ret = false;
561 Address src;
562
563 ret = DoSend(packet, src, dest, protocolNumber, false);
564 return ret;
565}
566
567bool
569 const Address& src,
570 const Address& dest,
571 uint16_t protocolNumber)
572{
573 NS_LOG_FUNCTION(this << *packet << src << dest << protocolNumber);
574 bool ret = false;
575
576 ret = DoSend(packet, src, dest, protocolNumber, true);
577 return ret;
578}
579
580bool
582 const Address& src,
583 const Address& dest,
584 uint16_t protocolNumber,
585 bool doSendFrom)
586{
587 NS_LOG_FUNCTION(this << *packet << src << dest << protocolNumber << doSendFrom);
588 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
589
590 Ptr<Packet> origPacket = packet->Copy();
591 uint32_t origHdrSize = 0;
592 uint32_t origPacketSize = packet->GetSize();
593 bool ret = false;
594
595 Address destination = dest;
596
597 bool useMesh = m_meshUnder;
598
600 {
601 protocolNumber = m_etherType;
602 }
603
604 if (m_useIphc)
605 {
606 NS_LOG_LOGIC("Compressing packet using IPHC");
607 origHdrSize += CompressLowPanIphc(packet, m_netDevice->GetAddress(), destination);
608 }
609 else
610 {
611 NS_LOG_LOGIC("Compressing packet using HC1");
612 origHdrSize += CompressLowPanHc1(packet, m_netDevice->GetAddress(), destination);
613 }
614
615 uint16_t pktSize = packet->GetSize();
616
617 SixLowPanMesh meshHdr;
618 SixLowPanBc0 bc0Hdr;
619 uint32_t extraHdrSize = 0;
620
621 if (useMesh)
622 {
623 Address source = src;
624 if (!doSendFrom)
625 {
626 source = m_netDevice->GetAddress();
627 }
628
630 {
631 // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
632 source = Get16MacFrom48Mac(source);
633 }
634 if (Mac48Address::IsMatchingType(destination))
635 {
636 // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
637 destination = Get16MacFrom48Mac(destination);
638 }
639
640 meshHdr.SetOriginator(source);
641 meshHdr.SetFinalDst(destination);
643 destination = m_netDevice->GetBroadcast();
644 // We are storing sum of mesh and bc0 header sizes. We will need it if packet is fragmented.
645 extraHdrSize = meshHdr.GetSerializedSize() + bc0Hdr.GetSerializedSize();
646 pktSize += extraHdrSize;
647 }
648
650 {
651 NS_LOG_LOGIC("Compressed packet too short, using uncompressed one");
652 packet = origPacket;
653 SixLowPanIpv6 ipv6UncompressedHdr;
654 packet->AddHeader(ipv6UncompressedHdr);
655 pktSize = packet->GetSize();
656 if (useMesh)
657 {
658 pktSize += meshHdr.GetSerializedSize() + bc0Hdr.GetSerializedSize();
659 }
660 }
661
662 if (pktSize > m_netDevice->GetMtu())
663 {
664 NS_LOG_LOGIC("Fragmentation: Packet size " << packet->GetSize() << " - Mtu "
665 << m_netDevice->GetMtu());
666 // fragment
667 std::list<Ptr<Packet>> fragmentList;
668 DoFragmentation(packet, origPacketSize, origHdrSize, extraHdrSize, fragmentList);
669 bool success = true;
670 for (auto it = fragmentList.begin(); it != fragmentList.end(); it++)
671 {
672 NS_LOG_DEBUG("SixLowPanNetDevice::Send (Fragment) " << **it);
673 m_txTrace(*it, this, GetIfIndex());
674
675 if (useMesh)
676 {
678 (*it)->AddHeader(bc0Hdr);
679 (*it)->AddHeader(meshHdr);
680 }
681 if (doSendFrom)
682 {
683 success &= m_netDevice->SendFrom(*it, src, destination, protocolNumber);
684 }
685 else
686 {
687 success &= m_netDevice->Send(*it, destination, protocolNumber);
688 }
689 }
690 ret = success;
691 }
692 else
693 {
694 m_txTrace(packet, this, GetIfIndex());
695
696 if (useMesh)
697 {
699 packet->AddHeader(bc0Hdr);
700 packet->AddHeader(meshHdr);
701 }
702
703 if (doSendFrom)
704 {
705 NS_LOG_DEBUG("SixLowPanNetDevice::SendFrom " << m_node->GetId() << " " << *packet);
706 ret = m_netDevice->SendFrom(packet, src, destination, protocolNumber);
707 }
708 else
709 {
710 NS_LOG_DEBUG("SixLowPanNetDevice::Send " << m_node->GetId() << " " << *packet);
711 ret = m_netDevice->Send(packet, destination, protocolNumber);
712 }
713 }
714
715 return ret;
716}
717
720{
721 NS_LOG_FUNCTION(this);
722 return m_node;
723}
724
725void
727{
728 NS_LOG_FUNCTION(this << node);
729 m_node = node;
730}
731
732bool
734{
735 NS_LOG_FUNCTION(this);
736 NS_ASSERT_MSG(m_netDevice, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice);
737
738 return m_netDevice->NeedsArp();
739}
740
741void
743{
744 NS_LOG_FUNCTION(this << &cb);
745 m_rxCallback = cb;
746}
747
748void
750{
751 NS_LOG_FUNCTION(this << &cb);
753}
754
755bool
757{
758 NS_LOG_FUNCTION(this);
759 return true;
760}
761
764{
765 NS_LOG_FUNCTION(this << *packet << src << dst);
766
767 Ipv6Header ipHeader;
768 SixLowPanHc1 hc1Header;
769 uint32_t size = 0;
770
771 NS_LOG_DEBUG("Original packet: " << *packet << " Size " << packet->GetSize());
772
773 if (packet->PeekHeader(ipHeader) != 0)
774 {
775 packet->RemoveHeader(ipHeader);
776 size += ipHeader.GetSerializedSize();
777
778 hc1Header.SetHopLimit(ipHeader.GetHopLimit());
779
780 uint8_t bufOne[16];
781 uint8_t bufTwo[16];
782 Ipv6Address srcAddr = ipHeader.GetSource();
783 srcAddr.GetBytes(bufOne);
785
786 NS_LOG_LOGIC("Checking source compression: " << mySrcAddr << " - " << srcAddr);
787
788 mySrcAddr.GetBytes(bufTwo);
789 bool isSrcSrc = (memcmp(bufOne + 8, bufTwo + 8, 8) == 0);
790
791 if (srcAddr.IsLinkLocal() && isSrcSrc)
792 {
794 }
795 else if (srcAddr.IsLinkLocal())
796 {
798 hc1Header.SetSrcInterface(bufOne + 8);
799 }
800 else if (isSrcSrc)
801 {
803 hc1Header.SetSrcPrefix(bufOne);
804 }
805 else
806 {
808 hc1Header.SetSrcInterface(bufOne + 8);
809 hc1Header.SetSrcPrefix(bufOne);
810 }
811
812 Ipv6Address dstAddr = ipHeader.GetDestination();
813 dstAddr.GetBytes(bufOne);
815
816 NS_LOG_LOGIC("Checking destination compression: " << myDstAddr << " - " << dstAddr);
817
818 myDstAddr.GetBytes(bufTwo);
819 bool isDstDst = (memcmp(bufOne + 8, bufTwo + 8, 8) == 0);
820
821 if (dstAddr.IsLinkLocal() && isDstDst)
822 {
824 }
825 else if (dstAddr.IsLinkLocal())
826 {
828 hc1Header.SetDstInterface(bufOne + 8);
829 }
830 else if (isDstDst)
831 {
833 hc1Header.SetDstPrefix(bufOne);
834 }
835 else
836 {
838 hc1Header.SetDstInterface(bufOne + 8);
839 hc1Header.SetDstPrefix(bufOne);
840 }
841
842 if ((ipHeader.GetFlowLabel() == 0) && (ipHeader.GetTrafficClass() == 0))
843 {
844 hc1Header.SetTcflCompression(true);
845 }
846 else
847 {
848 hc1Header.SetTcflCompression(false);
849 hc1Header.SetTrafficClass(ipHeader.GetTrafficClass());
850 hc1Header.SetFlowLabel(ipHeader.GetFlowLabel());
851 }
852
853 uint8_t nextHeader = ipHeader.GetNextHeader();
854 hc1Header.SetNextHeader(nextHeader);
855
856 // \todo implement HC2 compression
857 hc1Header.SetHc2HeaderPresent(false);
858
859 NS_LOG_DEBUG("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize());
860 NS_LOG_DEBUG("HC1 Compression - packet size = " << packet->GetSize());
861
862 packet->AddHeader(hc1Header);
863
864 return size;
865 }
866
867 return 0;
868}
869
870void
872{
873 NS_LOG_FUNCTION(this << *packet << src << dst);
874
875 Ipv6Header ipHeader;
876 SixLowPanHc1 encoding;
877
878 uint32_t ret [[maybe_unused]] = packet->RemoveHeader(encoding);
879 NS_LOG_DEBUG("removed " << ret << " bytes - pkt is " << *packet);
880
881 ipHeader.SetHopLimit(encoding.GetHopLimit());
882
883 switch (encoding.GetSrcCompression())
884 {
885 const uint8_t* interface;
886 const uint8_t* prefix;
887 uint8_t address[16];
888
890 prefix = encoding.GetSrcPrefix();
891 interface = encoding.GetSrcInterface();
892 for (int j = 0; j < 8; j++)
893 {
894 address[j + 8] = interface[j];
895 address[j] = prefix[j];
896 }
897 ipHeader.SetSource(Ipv6Address(address));
898 break;
900 prefix = encoding.GetSrcPrefix();
901 for (int j = 0; j < 8; j++)
902 {
903 address[j + 8] = 0;
904 address[j] = prefix[j];
905 }
907 break;
909 interface = encoding.GetSrcInterface();
910 address[0] = 0xfe;
911 address[1] = 0x80;
912 for (int j = 0; j < 8; j++)
913 {
914 address[j + 8] = interface[j];
915 }
916 ipHeader.SetSource(Ipv6Address(address));
917 break;
920 break;
921 }
922
923 switch (encoding.GetDstCompression())
924 {
925 const uint8_t* interface;
926 const uint8_t* prefix;
927 uint8_t address[16];
928
930 prefix = encoding.GetDstPrefix();
931 interface = encoding.GetDstInterface();
932 for (int j = 0; j < 8; j++)
933 {
934 address[j + 8] = interface[j];
935 address[j] = prefix[j];
936 }
937 ipHeader.SetDestination(Ipv6Address(address));
938 break;
940 prefix = encoding.GetDstPrefix();
941 for (int j = 0; j < 8; j++)
942 {
943 address[j + 8] = 0;
944 address[j] = prefix[j];
945 }
947 break;
949 interface = encoding.GetDstInterface();
950 address[0] = 0xfe;
951 address[1] = 0x80;
952 for (int j = 0; j < 8; j++)
953 {
954 address[j + 8] = interface[j];
955 }
956 ipHeader.SetDestination(Ipv6Address(address));
957 break;
960 break;
961 }
962
963 if (!encoding.IsTcflCompression())
964 {
965 ipHeader.SetFlowLabel(encoding.GetFlowLabel());
966 ipHeader.SetTrafficClass(encoding.GetTrafficClass());
967 }
968 else
969 {
970 ipHeader.SetFlowLabel(0);
971 ipHeader.SetTrafficClass(0);
972 }
973
974 ipHeader.SetNextHeader(encoding.GetNextHeader());
975
976 ipHeader.SetPayloadLength(packet->GetSize());
977
979 encoding.IsHc2HeaderPresent() == false,
980 "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
981
982 packet->AddHeader(ipHeader);
983
984 NS_LOG_DEBUG("Rebuilt packet: " << *packet << " Size " << packet->GetSize());
985}
986
989{
990 NS_LOG_FUNCTION(this << *packet << src << dst);
991
992 Ipv6Header ipHeader;
993 SixLowPanIphc iphcHeader;
994 uint32_t size = 0;
995
996 NS_LOG_DEBUG("Original packet: " << *packet << " Size " << packet->GetSize() << " src: " << src
997 << " dst: " << dst);
998
999 if (packet->PeekHeader(ipHeader) != 0)
1000 {
1001 packet->RemoveHeader(ipHeader);
1002 size += ipHeader.GetSerializedSize();
1003
1004 // Set the TF field
1005 if ((ipHeader.GetFlowLabel() == 0) && (ipHeader.GetTrafficClass() == 0))
1006 {
1007 iphcHeader.SetTf(SixLowPanIphc::TF_ELIDED);
1008 }
1009 else if ((ipHeader.GetFlowLabel() != 0) && (ipHeader.GetTrafficClass() != 0))
1010 {
1011 iphcHeader.SetTf(SixLowPanIphc::TF_FULL);
1012 iphcHeader.SetEcn((ipHeader.GetTrafficClass() & 0xC0) >> 6);
1013 iphcHeader.SetDscp(ipHeader.GetTrafficClass() & 0x3F);
1014 iphcHeader.SetFlowLabel(ipHeader.GetFlowLabel());
1015 }
1016 else if ((ipHeader.GetFlowLabel() == 0) && (ipHeader.GetTrafficClass() != 0))
1017 {
1019 iphcHeader.SetEcn((ipHeader.GetTrafficClass() & 0xC0) >> 6);
1020 iphcHeader.SetDscp(ipHeader.GetTrafficClass() & 0x3F);
1021 }
1022 else
1023 {
1025 iphcHeader.SetEcn((ipHeader.GetTrafficClass() & 0xC0) >> 6);
1026 iphcHeader.SetFlowLabel(ipHeader.GetFlowLabel());
1027 }
1028
1029 // Set the NH field and NextHeader
1030
1031 uint8_t nextHeader = ipHeader.GetNextHeader();
1032 if (CanCompressLowPanNhc(nextHeader))
1033 {
1034 if (nextHeader == Ipv6Header::IPV6_UDP)
1035 {
1036 iphcHeader.SetNh(true);
1037 size += CompressLowPanUdpNhc(packet, m_omitUdpChecksum);
1038 }
1039 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1040 {
1041 iphcHeader.SetNh(true);
1042 size += CompressLowPanIphc(packet, src, dst);
1043 }
1044 else
1045 {
1046 uint32_t sizeNhc = CompressLowPanNhc(packet, nextHeader, src, dst);
1047 // the compression might fail due to Extension header size.
1048 if (sizeNhc)
1049 {
1050 iphcHeader.SetNh(true);
1051 size += sizeNhc;
1052 }
1053 else
1054 {
1055 iphcHeader.SetNh(false);
1056 iphcHeader.SetNextHeader(nextHeader);
1057 }
1058 }
1059 }
1060 else
1061 {
1062 iphcHeader.SetNh(false);
1063 iphcHeader.SetNextHeader(nextHeader);
1064 }
1065
1066 // Set the HLIM field
1067 if (ipHeader.GetHopLimit() == 1)
1068 {
1070 }
1071 else if (ipHeader.GetHopLimit() == 0x40)
1072 {
1074 }
1075 else if (ipHeader.GetHopLimit() == 0xFF)
1076 {
1078 }
1079 else
1080 {
1082 // Set the HopLimit
1083 iphcHeader.SetHopLimit(ipHeader.GetHopLimit());
1084 }
1085
1086 // Set the CID + SAC + DAC fields to their default value
1087 iphcHeader.SetCid(false);
1088 iphcHeader.SetSac(false);
1089 iphcHeader.SetDac(false);
1090
1091 Ipv6Address checker = Ipv6Address("fe80:0000:0000:0000:0000:00ff:fe00:1");
1092 uint8_t unicastAddrCheckerBuf[16];
1093 checker.GetBytes(unicastAddrCheckerBuf);
1094 uint8_t addressBuf[16];
1095
1096 // This is just to limit the scope of some variables.
1097 {
1098 Ipv6Address srcAddr = ipHeader.GetSource();
1099 uint8_t srcContextId;
1100
1101 // The "::" address is compressed as a fake stateful compression.
1102 if (srcAddr == Ipv6Address::GetAny())
1103 {
1104 // No context information is needed.
1105 iphcHeader.SetSam(SixLowPanIphc::HC_INLINE);
1106 iphcHeader.SetSac(true);
1107 }
1108 // Check if the address can be compressed with stateful compression
1109 else if (FindUnicastCompressionContext(srcAddr, srcContextId))
1110 {
1111 // We can do stateful compression.
1112 NS_LOG_LOGIC("Checking stateful source compression: " << srcAddr);
1113
1114 iphcHeader.SetSac(true);
1115 if (srcContextId != 0)
1116 {
1117 // the default context is zero, no need to explicit it if it's zero
1118 iphcHeader.SetSrcContextId(srcContextId);
1119 iphcHeader.SetCid(true);
1120 }
1121
1122 // Note that a context might include parts of the EUI-64 (i.e., be as long as 128
1123 // bits).
1124
1126 src,
1127 m_contextTable[srcContextId].contextPrefix) == srcAddr)
1128 {
1130 }
1131 else
1132 {
1133 Ipv6Address cleanedAddr =
1134 CleanPrefix(srcAddr, m_contextTable[srcContextId].contextPrefix);
1135 uint8_t serializedCleanedAddress[16];
1136 cleanedAddr.Serialize(serializedCleanedAddress);
1137
1138 if (serializedCleanedAddress[8] == 0x00 &&
1139 serializedCleanedAddress[9] == 0x00 &&
1140 serializedCleanedAddress[10] == 0x00 &&
1141 serializedCleanedAddress[11] == 0xff &&
1142 serializedCleanedAddress[12] == 0xfe &&
1143 serializedCleanedAddress[13] == 0x00)
1144 {
1146 iphcHeader.SetSrcInlinePart(serializedCleanedAddress + 14, 2);
1147 }
1148 else
1149 {
1151 iphcHeader.SetSrcInlinePart(serializedCleanedAddress + 8, 8);
1152 }
1153 }
1154 }
1155 else
1156 {
1157 // We must do stateless compression.
1158 NS_LOG_LOGIC("Checking stateless source compression: " << srcAddr);
1159
1160 srcAddr.GetBytes(addressBuf);
1161
1162 uint8_t serializedSrcAddress[16];
1163 srcAddr.Serialize(serializedSrcAddress);
1164
1166 {
1168 }
1169 else if (memcmp(addressBuf, unicastAddrCheckerBuf, 14) == 0)
1170 {
1171 iphcHeader.SetSrcInlinePart(serializedSrcAddress + 14, 2);
1173 }
1174 else if (srcAddr.IsLinkLocal())
1175 {
1176 iphcHeader.SetSrcInlinePart(serializedSrcAddress + 8, 8);
1178 }
1179 else
1180 {
1181 iphcHeader.SetSrcInlinePart(serializedSrcAddress, 16);
1182 iphcHeader.SetSam(SixLowPanIphc::HC_INLINE);
1183 }
1184 }
1185 }
1186
1187 // Set the M field
1188 if (ipHeader.GetDestination().IsMulticast())
1189 {
1190 iphcHeader.SetM(true);
1191 }
1192 else
1193 {
1194 iphcHeader.SetM(false);
1195 }
1196
1197 // This is just to limit the scope of some variables.
1198 {
1199 Ipv6Address dstAddr = ipHeader.GetDestination();
1200 dstAddr.GetBytes(addressBuf);
1201
1202 NS_LOG_LOGIC("Checking destination compression: " << dstAddr);
1203
1204 uint8_t serializedDstAddress[16];
1205 dstAddr.Serialize(serializedDstAddress);
1206
1207 if (!iphcHeader.GetM())
1208 {
1209 // Unicast address
1210
1211 uint8_t dstContextId;
1212 if (FindUnicastCompressionContext(dstAddr, dstContextId))
1213 {
1214 // We can do stateful compression.
1215 NS_LOG_LOGIC("Checking stateful destination compression: " << dstAddr);
1216
1217 iphcHeader.SetDac(true);
1218 if (dstContextId != 0)
1219 {
1220 // the default context is zero, no need to explicit it if it's zero
1221 iphcHeader.SetDstContextId(dstContextId);
1222 iphcHeader.SetCid(true);
1223 }
1224
1225 // Note that a context might include parts of the EUI-64 (i.e., be as long as
1226 // 128 bits).
1228 dst,
1229 m_contextTable[dstContextId].contextPrefix) == dstAddr)
1230 {
1232 }
1233 else
1234 {
1235 Ipv6Address cleanedAddr =
1236 CleanPrefix(dstAddr, m_contextTable[dstContextId].contextPrefix);
1237
1238 uint8_t serializedCleanedAddress[16];
1239 cleanedAddr.Serialize(serializedCleanedAddress);
1240
1241 if (serializedCleanedAddress[8] == 0x00 &&
1242 serializedCleanedAddress[9] == 0x00 &&
1243 serializedCleanedAddress[10] == 0x00 &&
1244 serializedCleanedAddress[11] == 0xff &&
1245 serializedCleanedAddress[12] == 0xfe &&
1246 serializedCleanedAddress[13] == 0x00)
1247 {
1249 iphcHeader.SetDstInlinePart(serializedCleanedAddress + 14, 2);
1250 }
1251 else
1252 {
1254 iphcHeader.SetDstInlinePart(serializedCleanedAddress + 8, 8);
1255 }
1256 }
1257 }
1258 else
1259 {
1260 NS_LOG_LOGIC("Checking stateless destination compression: " << dstAddr);
1261
1263 {
1265 }
1266 else if (memcmp(addressBuf, unicastAddrCheckerBuf, 14) == 0)
1267 {
1268 iphcHeader.SetDstInlinePart(serializedDstAddress + 14, 2);
1270 }
1271 else if (dstAddr.IsLinkLocal())
1272 {
1273 iphcHeader.SetDstInlinePart(serializedDstAddress + 8, 8);
1275 }
1276 else
1277 {
1278 iphcHeader.SetDstInlinePart(serializedDstAddress, 16);
1279 iphcHeader.SetDam(SixLowPanIphc::HC_INLINE);
1280 }
1281 }
1282 }
1283 else
1284 {
1285 // Multicast address
1286
1287 uint8_t dstContextId;
1288 if (FindMulticastCompressionContext(dstAddr, dstContextId))
1289 {
1290 // Stateful compression (only one possible case)
1291
1292 // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1293 uint8_t dstInlinePart[6] = {};
1294 dstInlinePart[0] = serializedDstAddress[1];
1295 dstInlinePart[1] = serializedDstAddress[2];
1296 dstInlinePart[2] = serializedDstAddress[12];
1297 dstInlinePart[3] = serializedDstAddress[13];
1298 dstInlinePart[4] = serializedDstAddress[14];
1299 dstInlinePart[5] = serializedDstAddress[15];
1300
1301 iphcHeader.SetDac(true);
1302 if (dstContextId != 0)
1303 {
1304 // the default context is zero, no need to explicit it if it's zero
1305 iphcHeader.SetDstContextId(dstContextId);
1306 iphcHeader.SetCid(true);
1307 }
1308 iphcHeader.SetDstInlinePart(dstInlinePart, 6);
1309 iphcHeader.SetDam(SixLowPanIphc::HC_INLINE);
1310 }
1311 else
1312 {
1313 // Stateless compression
1314
1315 uint8_t multicastAddrCheckerBuf[16];
1316 Ipv6Address multicastCheckAddress = Ipv6Address("ff02::1");
1317 multicastCheckAddress.GetBytes(multicastAddrCheckerBuf);
1318
1319 // The address takes the form ff02::00XX.
1320 if (memcmp(addressBuf, multicastAddrCheckerBuf, 15) == 0)
1321 {
1322 iphcHeader.SetDstInlinePart(serializedDstAddress + 15, 1);
1324 }
1325 // The address takes the form ffXX::00XX:XXXX.
1326 // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1327 else if ((addressBuf[0] == multicastAddrCheckerBuf[0]) &&
1328 (memcmp(addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0))
1329 {
1330 uint8_t dstInlinePart[4] = {};
1331 memcpy(dstInlinePart, serializedDstAddress + 1, 1);
1332 memcpy(dstInlinePart + 1, serializedDstAddress + 13, 3);
1333 iphcHeader.SetDstInlinePart(dstInlinePart, 4);
1335 }
1336 // The address takes the form ffXX::00XX:XXXX:XXXX.
1337 // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1338 else if ((addressBuf[0] == multicastAddrCheckerBuf[0]) &&
1339 (memcmp(addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0))
1340 {
1341 uint8_t dstInlinePart[6] = {};
1342 memcpy(dstInlinePart, serializedDstAddress + 1, 1);
1343 memcpy(dstInlinePart + 1, serializedDstAddress + 11, 5);
1344 iphcHeader.SetDstInlinePart(dstInlinePart, 6);
1346 }
1347 else
1348 {
1349 iphcHeader.SetDstInlinePart(serializedDstAddress, 16);
1350 iphcHeader.SetDam(SixLowPanIphc::HC_INLINE);
1351 }
1352 }
1353 }
1354 }
1355
1356 NS_LOG_DEBUG("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize());
1357 NS_LOG_DEBUG("IPHC Compression - packet size = " << packet->GetSize());
1358
1359 packet->AddHeader(iphcHeader);
1360
1361 NS_LOG_DEBUG("Packet after IPHC compression: " << *packet);
1362
1363 return size;
1364 }
1365 return 0;
1366}
1367
1368bool
1370{
1371 bool ret = false;
1372
1373 switch (nextHeader)
1374 {
1380 ret = true;
1381 break;
1383 default:
1384 ret = false;
1385 }
1386 return ret;
1387}
1388
1389bool
1391{
1392 NS_LOG_FUNCTION(this << *packet << src << dst);
1393
1394 Ipv6Header ipHeader;
1395 SixLowPanIphc encoding;
1396
1397 uint32_t ret [[maybe_unused]] = packet->RemoveHeader(encoding);
1398 NS_LOG_DEBUG("removed " << ret << " bytes - pkt is " << *packet);
1399
1400 // Hop Limit
1401 ipHeader.SetHopLimit(encoding.GetHopLimit());
1402
1403 // Source address
1404 if (encoding.GetSac())
1405 {
1406 // Source address compression uses stateful, context-based compression.
1407 if (encoding.GetSam() == SixLowPanIphc::HC_INLINE)
1408 {
1409 ipHeader.SetSource(Ipv6Address::GetAny());
1410 }
1411 else
1412 {
1413 uint8_t contextId = encoding.GetSrcContextId();
1414 if (m_contextTable.find(contextId) == m_contextTable.end())
1415 {
1416 NS_LOG_LOGIC("Unknown Source compression context (" << +contextId
1417 << "), dropping packet");
1418 return true;
1419 }
1420 if (m_contextTable[contextId].validLifetime < Simulator::Now())
1421 {
1422 NS_LOG_LOGIC("Expired Source compression context (" << +contextId
1423 << "), dropping packet");
1424 return true;
1425 }
1426
1427 uint8_t contextPrefix[16];
1428 m_contextTable[contextId].contextPrefix.GetBytes(contextPrefix);
1429 uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength();
1430
1431 uint8_t srcAddress[16] = {};
1432 if (encoding.GetSam() == SixLowPanIphc::HC_COMPR_64)
1433 {
1434 memcpy(srcAddress + 8, encoding.GetSrcInlinePart(), 8);
1435 }
1436 else if (encoding.GetSam() == SixLowPanIphc::HC_COMPR_16)
1437 {
1438 srcAddress[11] = 0xff;
1439 srcAddress[12] = 0xfe;
1440 memcpy(srcAddress + 14, encoding.GetSrcInlinePart(), 2);
1441 }
1442 else // SixLowPanIphc::HC_COMPR_0
1443 {
1445 }
1446
1447 uint8_t bytesToCopy = contextLength / 8;
1448 uint8_t bitsToCopy = contextLength % 8;
1449
1450 // Do not combine the prefix - we want to override the bytes.
1451 for (uint8_t i = 0; i < bytesToCopy; i++)
1452 {
1453 srcAddress[i] = contextPrefix[i];
1454 }
1455 if (bitsToCopy)
1456 {
1457 uint8_t addressBitMask = (1 << (8 - bitsToCopy)) - 1;
1458 uint8_t prefixBitMask = ~addressBitMask;
1459 srcAddress[bytesToCopy] = (contextPrefix[bytesToCopy] & prefixBitMask) |
1460 (srcAddress[bytesToCopy] & addressBitMask);
1461 }
1462 ipHeader.SetSource(Ipv6Address::Deserialize(srcAddress));
1463 }
1464 }
1465 else
1466 {
1467 // Source address compression uses stateless compression.
1468
1469 if (encoding.GetSam() == SixLowPanIphc::HC_INLINE)
1470 {
1471 uint8_t srcAddress[16] = {};
1472 memcpy(srcAddress, encoding.GetSrcInlinePart(), 16);
1473 ipHeader.SetSource(Ipv6Address::Deserialize(srcAddress));
1474 }
1475 else if (encoding.GetSam() == SixLowPanIphc::HC_COMPR_64)
1476 {
1477 uint8_t srcAddress[16] = {};
1478 memcpy(srcAddress + 8, encoding.GetSrcInlinePart(), 8);
1479 srcAddress[0] = 0xfe;
1480 srcAddress[1] = 0x80;
1481 ipHeader.SetSource(Ipv6Address::Deserialize(srcAddress));
1482 }
1483 else if (encoding.GetSam() == SixLowPanIphc::HC_COMPR_16)
1484 {
1485 uint8_t srcAddress[16] = {};
1486 memcpy(srcAddress + 14, encoding.GetSrcInlinePart(), 2);
1487 srcAddress[0] = 0xfe;
1488 srcAddress[1] = 0x80;
1489 srcAddress[11] = 0xff;
1490 srcAddress[12] = 0xfe;
1491 ipHeader.SetSource(Ipv6Address::Deserialize(srcAddress));
1492 }
1493 else // SixLowPanIphc::HC_COMPR_0
1494 {
1496 }
1497 }
1498 // Destination address
1499 if (encoding.GetDac())
1500 {
1501 // Destination address compression uses stateful, context-based compression.
1502 if ((encoding.GetDam() == SixLowPanIphc::HC_INLINE && !encoding.GetM()) ||
1503 (encoding.GetDam() == SixLowPanIphc::HC_COMPR_64 && encoding.GetM()) ||
1504 (encoding.GetDam() == SixLowPanIphc::HC_COMPR_16 && encoding.GetM()) ||
1505 (encoding.GetDam() == SixLowPanIphc::HC_COMPR_0 && encoding.GetM()))
1506 {
1507 NS_ABORT_MSG("Reserved code found");
1508 }
1509
1510 uint8_t contextId = encoding.GetDstContextId();
1511 if (m_contextTable.find(contextId) == m_contextTable.end())
1512 {
1513 NS_LOG_LOGIC("Unknown Destination compression context (" << +contextId
1514 << "), dropping packet");
1515 return true;
1516 }
1517 if (m_contextTable[contextId].validLifetime < Simulator::Now())
1518 {
1519 NS_LOG_LOGIC("Expired Destination compression context (" << +contextId
1520 << "), dropping packet");
1521 return true;
1522 }
1523
1524 uint8_t contextPrefix[16];
1525 m_contextTable[contextId].contextPrefix.GetBytes(contextPrefix);
1526 uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength();
1527
1528 if (!encoding.GetM())
1529 {
1530 // unicast
1531 uint8_t dstAddress[16] = {};
1532 if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_64)
1533 {
1534 memcpy(dstAddress + 8, encoding.GetDstInlinePart(), 8);
1535 }
1536 else if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_16)
1537 {
1538 dstAddress[11] = 0xff;
1539 dstAddress[12] = 0xfe;
1540 memcpy(dstAddress + 14, encoding.GetDstInlinePart(), 2);
1541 }
1542 else // SixLowPanIphc::HC_COMPR_0
1543 {
1545 }
1546
1547 uint8_t bytesToCopy = m_contextTable[contextId].contextPrefix.GetPrefixLength() / 8;
1548 uint8_t bitsToCopy = contextLength % 8;
1549
1550 // Do not combine the prefix - we want to override the bytes.
1551 for (uint8_t i = 0; i < bytesToCopy; i++)
1552 {
1553 dstAddress[i] = contextPrefix[i];
1554 }
1555 if (bitsToCopy)
1556 {
1557 uint8_t addressBitMask = (1 << (8 - bitsToCopy)) - 1;
1558 uint8_t prefixBitMask = ~addressBitMask;
1559 dstAddress[bytesToCopy] = (contextPrefix[bytesToCopy] & prefixBitMask) |
1560 (dstAddress[bytesToCopy] & addressBitMask);
1561 }
1562 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1563 }
1564 else
1565 {
1566 // multicast
1567 // Just one possibility: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1568 uint8_t dstAddress[16] = {};
1569 dstAddress[0] = 0xff;
1570 memcpy(dstAddress + 1, encoding.GetDstInlinePart(), 2);
1571 dstAddress[3] = contextLength;
1572 memcpy(dstAddress + 4, contextPrefix, 8);
1573 memcpy(dstAddress + 12, encoding.GetDstInlinePart() + 2, 4);
1574 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1575 }
1576 }
1577 else
1578 {
1579 // Destination address compression uses stateless compression.
1580 if (!encoding.GetM())
1581 {
1582 // unicast
1583 if (encoding.GetDam() == SixLowPanIphc::HC_INLINE)
1584 {
1585 uint8_t dstAddress[16] = {};
1586 memcpy(dstAddress, encoding.GetDstInlinePart(), 16);
1587 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1588 }
1589 else if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_64)
1590 {
1591 uint8_t dstAddress[16] = {};
1592 memcpy(dstAddress + 8, encoding.GetDstInlinePart(), 8);
1593 dstAddress[0] = 0xfe;
1594 dstAddress[1] = 0x80;
1595 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1596 }
1597 else if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_16)
1598 {
1599 uint8_t dstAddress[16] = {};
1600 memcpy(dstAddress + 14, encoding.GetDstInlinePart(), 2);
1601 dstAddress[0] = 0xfe;
1602 dstAddress[1] = 0x80;
1603 dstAddress[11] = 0xff;
1604 dstAddress[12] = 0xfe;
1605 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1606 }
1607 else // SixLowPanIphc::HC_COMPR_0
1608 {
1610 }
1611 }
1612 else
1613 {
1614 // multicast
1615 if (encoding.GetDam() == SixLowPanIphc::HC_INLINE)
1616 {
1617 uint8_t dstAddress[16] = {};
1618 memcpy(dstAddress, encoding.GetDstInlinePart(), 16);
1619 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1620 }
1621 else if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_64)
1622 {
1623 uint8_t dstAddress[16] = {};
1624 dstAddress[0] = 0xff;
1625 memcpy(dstAddress + 1, encoding.GetDstInlinePart(), 1);
1626 memcpy(dstAddress + 11, encoding.GetDstInlinePart() + 1, 5);
1627 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1628 }
1629 else if (encoding.GetDam() == SixLowPanIphc::HC_COMPR_16)
1630 {
1631 uint8_t dstAddress[16] = {};
1632 dstAddress[0] = 0xff;
1633 memcpy(dstAddress + 1, encoding.GetDstInlinePart(), 1);
1634 memcpy(dstAddress + 13, encoding.GetDstInlinePart() + 1, 3);
1635 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1636 }
1637 else // SixLowPanIphc::HC_COMPR_0
1638 {
1639 uint8_t dstAddress[16] = {};
1640 dstAddress[0] = 0xff;
1641 dstAddress[1] = 0x02;
1642 memcpy(dstAddress + 15, encoding.GetDstInlinePart(), 1);
1643 ipHeader.SetDestination(Ipv6Address::Deserialize(dstAddress));
1644 }
1645 }
1646 }
1647
1648 // Traffic class and Flow Label
1649 uint8_t traf = 0x00;
1650 switch (encoding.GetTf())
1651 {
1653 traf |= encoding.GetEcn();
1654 traf = (traf << 6) | encoding.GetDscp();
1655 ipHeader.SetTrafficClass(traf);
1656 ipHeader.SetFlowLabel(encoding.GetFlowLabel() & 0xfff); // Add 4-bit pad
1657 break;
1659 traf |= encoding.GetEcn();
1660 traf <<= 2; // Add 2-bit pad
1661 ipHeader.SetTrafficClass(traf);
1662 ipHeader.SetFlowLabel(encoding.GetFlowLabel());
1663 break;
1665 traf |= encoding.GetEcn();
1666 traf = (traf << 6) | encoding.GetDscp();
1667 ipHeader.SetTrafficClass(traf);
1668 ipHeader.SetFlowLabel(0);
1669 break;
1671 ipHeader.SetFlowLabel(0);
1672 ipHeader.SetTrafficClass(0);
1673 break;
1674 }
1675
1676 if (encoding.GetNh())
1677 {
1678 // Next Header
1679 uint8_t dispatchRawVal = 0;
1681
1682 packet->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
1683 dispatchVal = SixLowPanDispatch::GetNhcDispatchType(dispatchRawVal);
1684
1685 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1686 {
1688 DecompressLowPanUdpNhc(packet, ipHeader.GetSource(), ipHeader.GetDestination());
1689 }
1690 else
1691 {
1692 std::pair<uint8_t, bool> retval = DecompressLowPanNhc(packet,
1693 src,
1694 dst,
1695 ipHeader.GetSource(),
1696 ipHeader.GetDestination());
1697 if (retval.second)
1698 {
1699 return true;
1700 }
1701 else
1702 {
1703 ipHeader.SetNextHeader(retval.first);
1704 }
1705 }
1706 }
1707 else
1708 {
1709 ipHeader.SetNextHeader(encoding.GetNextHeader());
1710 }
1711
1712 ipHeader.SetPayloadLength(packet->GetSize());
1713
1714 packet->AddHeader(ipHeader);
1715
1716 NS_LOG_DEBUG("Rebuilt packet: " << *packet << " Size " << packet->GetSize());
1717
1718 return false;
1719}
1720
1723 uint8_t headerType,
1724 const Address& src,
1725 const Address& dst)
1726{
1727 NS_LOG_FUNCTION(this << *packet << int(headerType));
1728
1729 SixLowPanNhcExtension nhcHeader;
1730 uint32_t size = 0;
1731 Buffer blob;
1732
1733 if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1734 {
1736 packet->PeekHeader(hopHeader);
1737 if (hopHeader.GetLength() >= 0xff)
1738 {
1740 "LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1741 "that have more than 255 octets following the Length field after compression. "
1742 "Packet uncompressed.");
1743 return 0;
1744 }
1745
1746 size += packet->RemoveHeader(hopHeader);
1748
1749 // recursively compress other headers
1750 uint8_t nextHeader = hopHeader.GetNextHeader();
1751 if (CanCompressLowPanNhc(nextHeader))
1752 {
1753 if (nextHeader == Ipv6Header::IPV6_UDP)
1754 {
1755 nhcHeader.SetNh(true);
1756 size += CompressLowPanUdpNhc(packet, m_omitUdpChecksum);
1757 }
1758 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1759 {
1760 nhcHeader.SetNh(true);
1761 size += CompressLowPanIphc(packet, src, dst);
1762 }
1763 else
1764 {
1765 uint32_t sizeNhc = CompressLowPanNhc(packet, nextHeader, src, dst);
1766 // the compression might fail due to Extension header size.
1767 if (sizeNhc)
1768 {
1769 nhcHeader.SetNh(true);
1770 size += sizeNhc;
1771 }
1772 else
1773 {
1774 nhcHeader.SetNh(false);
1775 nhcHeader.SetNextHeader(nextHeader);
1776 }
1777 }
1778 }
1779 else
1780 {
1781 nhcHeader.SetNh(false);
1782 nhcHeader.SetNextHeader(nextHeader);
1783 }
1784
1785 uint32_t blobSize = hopHeader.GetSerializedSize();
1786 blob.AddAtStart(blobSize);
1787 hopHeader.Serialize(blob.Begin());
1788 blob.RemoveAtStart(2);
1789 blobSize = blob.GetSize();
1790 nhcHeader.SetBlob(blob.PeekData(), blobSize);
1791 }
1792 else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1793 {
1794 Ipv6ExtensionRoutingHeader routingHeader;
1795 packet->PeekHeader(routingHeader);
1796 if (routingHeader.GetLength() >= 0xff)
1797 {
1799 "LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1800 "that have more than 255 octets following the Length field after compression. "
1801 "Packet uncompressed.");
1802 return 0;
1803 }
1804
1805 size += packet->RemoveHeader(routingHeader);
1807
1808 // recursively compress other headers
1809 uint8_t nextHeader = routingHeader.GetNextHeader();
1810 if (CanCompressLowPanNhc(nextHeader))
1811 {
1812 if (nextHeader == Ipv6Header::IPV6_UDP)
1813 {
1814 nhcHeader.SetNh(true);
1815 size += CompressLowPanUdpNhc(packet, m_omitUdpChecksum);
1816 }
1817 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1818 {
1819 nhcHeader.SetNh(true);
1820 size += CompressLowPanIphc(packet, src, dst);
1821 }
1822 else
1823 {
1824 uint32_t sizeNhc = CompressLowPanNhc(packet, nextHeader, src, dst);
1825 // the compression might fail due to Extension header size.
1826 if (sizeNhc)
1827 {
1828 nhcHeader.SetNh(true);
1829 size += sizeNhc;
1830 }
1831 else
1832 {
1833 nhcHeader.SetNh(false);
1834 nhcHeader.SetNextHeader(nextHeader);
1835 }
1836 }
1837 }
1838 else
1839 {
1840 nhcHeader.SetNh(false);
1841 nhcHeader.SetNextHeader(nextHeader);
1842 }
1843
1844 uint32_t blobSize = routingHeader.GetSerializedSize();
1845 blob.AddAtStart(blobSize);
1846 routingHeader.Serialize(blob.Begin());
1847 blob.RemoveAtStart(2);
1848 blobSize = blob.GetSize();
1849 nhcHeader.SetBlob(blob.PeekData(), blobSize);
1850 }
1851 else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1852 {
1853 Ipv6ExtensionFragmentHeader fragHeader;
1854 packet->PeekHeader(fragHeader);
1855 if (fragHeader.GetLength() >= 0xff)
1856 {
1858 "LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1859 "that have more than 255 octets following the Length field after compression. "
1860 "Packet uncompressed.");
1861 return 0;
1862 }
1863 size += packet->RemoveHeader(fragHeader);
1865
1866 // recursively compress other headers
1867 uint8_t nextHeader = fragHeader.GetNextHeader();
1868 if (CanCompressLowPanNhc(nextHeader))
1869 {
1870 if (nextHeader == Ipv6Header::IPV6_UDP)
1871 {
1872 nhcHeader.SetNh(true);
1873 size += CompressLowPanUdpNhc(packet, m_omitUdpChecksum);
1874 }
1875 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1876 {
1877 nhcHeader.SetNh(true);
1878 size += CompressLowPanIphc(packet, src, dst);
1879 }
1880 else
1881 {
1882 uint32_t sizeNhc = CompressLowPanNhc(packet, nextHeader, src, dst);
1883 // the compression might fail due to Extension header size.
1884 if (sizeNhc)
1885 {
1886 nhcHeader.SetNh(true);
1887 size += sizeNhc;
1888 }
1889 else
1890 {
1891 nhcHeader.SetNh(false);
1892 nhcHeader.SetNextHeader(nextHeader);
1893 }
1894 }
1895 }
1896 else
1897 {
1898 nhcHeader.SetNh(false);
1899 nhcHeader.SetNextHeader(nextHeader);
1900 }
1901
1902 uint32_t blobSize = fragHeader.GetSerializedSize();
1903 blob.AddAtStart(blobSize);
1904 fragHeader.Serialize(blob.Begin());
1905 blob.RemoveAtStart(2);
1906 blobSize = blob.GetSize();
1907 nhcHeader.SetBlob(blob.PeekData(), blobSize);
1908 }
1909 else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1910 {
1912 packet->PeekHeader(destHeader);
1913 if (destHeader.GetLength() >= 0xff)
1914 {
1916 "LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1917 "that have more than 255 octets following the Length field after compression. "
1918 "Packet uncompressed.");
1919 return 0;
1920 }
1921 size += packet->RemoveHeader(destHeader);
1923
1924 // recursively compress other headers
1925 uint8_t nextHeader = destHeader.GetNextHeader();
1926 if (CanCompressLowPanNhc(nextHeader))
1927 {
1928 if (nextHeader == Ipv6Header::IPV6_UDP)
1929 {
1930 nhcHeader.SetNh(true);
1931 size += CompressLowPanUdpNhc(packet, m_omitUdpChecksum);
1932 }
1933 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1934 {
1935 nhcHeader.SetNh(true);
1936 size += CompressLowPanIphc(packet, src, dst);
1937 }
1938 else
1939 {
1940 uint32_t sizeNhc = CompressLowPanNhc(packet, nextHeader, src, dst);
1941 // the compression might fail due to Extension header size.
1942 if (sizeNhc)
1943 {
1944 nhcHeader.SetNh(true);
1945 size += sizeNhc;
1946 }
1947 else
1948 {
1949 nhcHeader.SetNh(false);
1950 nhcHeader.SetNextHeader(nextHeader);
1951 }
1952 }
1953 }
1954 else
1955 {
1956 nhcHeader.SetNh(false);
1957 nhcHeader.SetNextHeader(nextHeader);
1958 }
1959
1960 uint32_t blobSize = destHeader.GetSerializedSize();
1961 blob.AddAtStart(blobSize);
1962 destHeader.Serialize(blob.Begin());
1963 blob.RemoveAtStart(2);
1964 blobSize = blob.GetSize();
1965 nhcHeader.SetBlob(blob.PeekData(), blobSize);
1966 }
1967 else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1968 {
1969 // \todo: IPv6 Mobility Header is not supported in ns-3
1970 NS_ABORT_MSG("IPv6 Mobility Header is not supported in ns-3 yet");
1971 return 0;
1972 }
1973 else
1974 {
1975 NS_ABORT_MSG("Unexpected Extension Header");
1976 }
1977
1978 NS_LOG_DEBUG("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize());
1979 NS_LOG_DEBUG("NHC Compression - packet size = " << packet->GetSize());
1980
1981 packet->AddHeader(nhcHeader);
1982
1983 NS_LOG_DEBUG("Packet after NHC compression: " << *packet);
1984 return size;
1985}
1986
1987std::pair<uint8_t, bool>
1989 const Address& src,
1990 const Address& dst,
1991 Ipv6Address srcAddress,
1992 Ipv6Address dstAddress)
1993{
1994 NS_LOG_FUNCTION(this << *packet);
1995
1996 SixLowPanNhcExtension encoding;
1997
1998 uint32_t ret [[maybe_unused]] = packet->RemoveHeader(encoding);
1999 NS_LOG_DEBUG("removed " << ret << " bytes - pkt is " << *packet);
2000
2002 Ipv6ExtensionRoutingHeader routingHeader;
2003 Ipv6ExtensionFragmentHeader fragHeader;
2005
2006 uint32_t blobSize;
2007 uint8_t blobData[260];
2008 blobSize = encoding.CopyBlob(blobData + 2, 260 - 2);
2009 uint8_t paddingSize = 0;
2010
2011 uint8_t actualEncodedHeaderType = encoding.GetEid();
2012 uint8_t actualHeaderType;
2013 Buffer blob;
2014
2015 switch (actualEncodedHeaderType)
2016 {
2018 actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
2019 if (encoding.GetNh())
2020 {
2021 // Next Header
2022 uint8_t dispatchRawVal = 0;
2024
2025 packet->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
2026 dispatchVal = SixLowPanDispatch::GetNhcDispatchType(dispatchRawVal);
2027
2028 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2029 {
2030 blobData[0] = Ipv6Header::IPV6_UDP;
2031 DecompressLowPanUdpNhc(packet, srcAddress, dstAddress);
2032 }
2033 else
2034 {
2035 blobData[0] = DecompressLowPanNhc(packet, src, dst, srcAddress, dstAddress).first;
2036 }
2037 }
2038 else
2039 {
2040 blobData[0] = encoding.GetNextHeader();
2041 }
2042
2043 // manually add some padding if needed
2044 if ((blobSize + 2) % 8 > 0)
2045 {
2046 paddingSize = 8 - (blobSize + 2) % 8;
2047 }
2048 if (paddingSize == 1)
2049 {
2050 blobData[blobSize + 2] = 0;
2051 }
2052 else if (paddingSize > 1)
2053 {
2054 blobData[blobSize + 2] = 1;
2055 blobData[blobSize + 2 + 1] = paddingSize - 2;
2056 for (uint8_t i = 0; i < paddingSize - 2; i++)
2057 {
2058 blobData[blobSize + 2 + 2 + i] = 0;
2059 }
2060 }
2061 blobData[1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
2062 blob.AddAtStart(blobSize + 2 + paddingSize);
2063 blob.Begin().Write(blobData, blobSize + 2 + paddingSize);
2064 hopHeader.Deserialize(blob.Begin());
2065
2066 packet->AddHeader(hopHeader);
2067 break;
2068
2070 actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
2071 if (encoding.GetNh())
2072 {
2073 // Next Header
2074 uint8_t dispatchRawVal = 0;
2076
2077 packet->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
2078 dispatchVal = SixLowPanDispatch::GetNhcDispatchType(dispatchRawVal);
2079
2080 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2081 {
2082 blobData[0] = Ipv6Header::IPV6_UDP;
2083 DecompressLowPanUdpNhc(packet, srcAddress, dstAddress);
2084 }
2085 else
2086 {
2087 blobData[0] = DecompressLowPanNhc(packet, src, dst, srcAddress, dstAddress).first;
2088 }
2089 }
2090 else
2091 {
2092 blobData[0] = encoding.GetNextHeader();
2093 }
2094 blobData[1] = ((blobSize + 2) >> 3) - 1;
2095 blob.AddAtStart(blobSize + 2);
2096 blob.Begin().Write(blobData, blobSize + 2);
2097 routingHeader.Deserialize(blob.Begin());
2098 packet->AddHeader(routingHeader);
2099 break;
2100
2102 actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
2103 if (encoding.GetNh())
2104 {
2105 // Next Header
2106 uint8_t dispatchRawVal = 0;
2108
2109 packet->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
2110 dispatchVal = SixLowPanDispatch::GetNhcDispatchType(dispatchRawVal);
2111
2112 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2113 {
2114 blobData[0] = Ipv6Header::IPV6_UDP;
2115 DecompressLowPanUdpNhc(packet, srcAddress, dstAddress);
2116 }
2117 else
2118 {
2119 blobData[0] = DecompressLowPanNhc(packet, src, dst, srcAddress, dstAddress).first;
2120 }
2121 }
2122 else
2123 {
2124 blobData[0] = encoding.GetNextHeader();
2125 }
2126 blobData[1] = 0;
2127
2128 blob.AddAtStart(blobSize + 2);
2129 blob.Begin().Write(blobData, blobSize + 2);
2130
2131 fragHeader.Deserialize(blob.Begin());
2132 packet->AddHeader(fragHeader);
2133 break;
2134
2136 actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
2137 if (encoding.GetNh())
2138 {
2139 // Next Header
2140 uint8_t dispatchRawVal = 0;
2142
2143 packet->CopyData(&dispatchRawVal, sizeof(dispatchRawVal));
2144 dispatchVal = SixLowPanDispatch::GetNhcDispatchType(dispatchRawVal);
2145
2146 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2147 {
2148 blobData[0] = Ipv6Header::IPV6_UDP;
2149 DecompressLowPanUdpNhc(packet, srcAddress, dstAddress);
2150 }
2151 else
2152 {
2153 blobData[0] = DecompressLowPanNhc(packet, src, dst, srcAddress, dstAddress).first;
2154 }
2155 }
2156 else
2157 {
2158 blobData[0] = encoding.GetNextHeader();
2159 }
2160
2161 // manually add some padding if needed
2162 if ((blobSize + 2) % 8 > 0)
2163 {
2164 paddingSize = 8 - (blobSize + 2) % 8;
2165 }
2166 if (paddingSize == 1)
2167 {
2168 blobData[blobSize + 2] = 0;
2169 }
2170 else if (paddingSize > 1)
2171 {
2172 blobData[blobSize + 2] = 1;
2173 blobData[blobSize + 2 + 1] = paddingSize - 2;
2174 for (uint8_t i = 0; i < paddingSize - 2; i++)
2175 {
2176 blobData[blobSize + 2 + 2 + i] = 0;
2177 }
2178 }
2179 blobData[1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
2180 blob.AddAtStart(blobSize + 2 + paddingSize);
2181 blob.Begin().Write(blobData, blobSize + 2 + paddingSize);
2182 destHeader.Deserialize(blob.Begin());
2183
2184 packet->AddHeader(destHeader);
2185 break;
2187 // \todo: IPv6 Mobility Header is not supported in ns-3
2188 NS_ABORT_MSG("IPv6 Mobility Header is not supported in ns-3 yet");
2189 break;
2191 actualHeaderType = Ipv6Header::IPV6_IPV6;
2192 if (DecompressLowPanIphc(packet, src, dst))
2193 {
2195 return std::pair<uint8_t, bool>(0, true);
2196 }
2197 break;
2198 default:
2199 NS_ABORT_MSG("Trying to decode unknown Extension Header");
2200 break;
2201 }
2202
2203 NS_LOG_DEBUG("Rebuilt packet: " << *packet << " Size " << packet->GetSize());
2204 return std::pair<uint8_t, bool>(actualHeaderType, false);
2205}
2206
2209{
2210 NS_LOG_FUNCTION(this << *packet << int(omitChecksum));
2211
2212 UdpHeader udpHeader;
2213 SixLowPanUdpNhcExtension udpNhcHeader;
2214 uint32_t size = 0;
2215
2216 NS_ASSERT_MSG(packet->PeekHeader(udpHeader) != 0, "UDP header not found, abort");
2217
2218 size += packet->RemoveHeader(udpHeader);
2219
2220 // Set the C field and checksum
2221 udpNhcHeader.SetC(false);
2222 uint16_t checksum = udpHeader.GetChecksum();
2223 udpNhcHeader.SetChecksum(checksum);
2224
2225 if (omitChecksum && udpHeader.IsChecksumOk())
2226 {
2227 udpNhcHeader.SetC(true);
2228 }
2229
2230 // Set the value of the ports
2231 udpNhcHeader.SetSrcPort(udpHeader.GetSourcePort());
2232 udpNhcHeader.SetDstPort(udpHeader.GetDestinationPort());
2233
2234 // Set the P field
2235 if ((udpHeader.GetSourcePort() >> 4) == 0xf0b && (udpHeader.GetDestinationPort() >> 4) == 0xf0b)
2236 {
2238 }
2239 else if ((udpHeader.GetSourcePort() >> 8) == 0xf0 &&
2240 (udpHeader.GetDestinationPort() >> 8) != 0xf0)
2241 {
2243 }
2244 else if ((udpHeader.GetSourcePort() >> 8) != 0xf0 &&
2245 (udpHeader.GetDestinationPort() >> 8) == 0xf0)
2246 {
2248 }
2249 else
2250 {
2252 }
2253
2255 "UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize());
2256 NS_LOG_DEBUG("UDP_NHC Compression - packet size = " << packet->GetSize());
2257
2258 packet->AddHeader(udpNhcHeader);
2259
2260 NS_LOG_DEBUG("Packet after UDP_NHC compression: " << *packet);
2261
2262 return size;
2263}
2264
2265void
2267{
2268 NS_LOG_FUNCTION(this << *packet);
2269
2270 UdpHeader udpHeader;
2271 SixLowPanUdpNhcExtension encoding;
2272
2273 uint32_t ret [[maybe_unused]] = packet->RemoveHeader(encoding);
2274 NS_LOG_DEBUG("removed " << ret << " bytes - pkt is " << *packet);
2275
2276 // Set the value of the ports
2277 switch (encoding.GetPorts())
2278 {
2279 uint16_t temp;
2281 udpHeader.SetSourcePort(encoding.GetSrcPort());
2282 udpHeader.SetDestinationPort(encoding.GetDstPort());
2283 break;
2285 udpHeader.SetSourcePort(encoding.GetSrcPort());
2286 temp = (0xf0 << 8) | encoding.GetDstPort();
2287 udpHeader.SetDestinationPort(temp);
2288 break;
2290 temp = (0xf0 << 8) | encoding.GetSrcPort();
2291 udpHeader.SetSourcePort(temp);
2292 udpHeader.SetDestinationPort(encoding.GetDstPort());
2293 break;
2295 temp = (0xf0b << 4) | encoding.GetSrcPort();
2296 udpHeader.SetSourcePort(temp);
2297 temp = (0xf0b << 4) | encoding.GetDstPort();
2298 udpHeader.SetDestinationPort(temp);
2299 break;
2300 }
2301
2302 // Get the C field and checksum
2304 {
2305 if (encoding.GetC())
2306 {
2307 NS_LOG_LOGIC("Recalculating UDP Checksum");
2308 udpHeader.EnableChecksums();
2309 udpHeader.InitializeChecksum(saddr, daddr, UdpL4Protocol::PROT_NUMBER);
2310 packet->AddHeader(udpHeader);
2311 }
2312 else
2313 {
2314 NS_LOG_LOGIC("Forcing UDP Checksum to " << encoding.GetChecksum());
2315 udpHeader.ForceChecksum(encoding.GetChecksum());
2316 packet->AddHeader(udpHeader);
2317 NS_LOG_LOGIC("UDP checksum is ok ? " << udpHeader.IsChecksumOk());
2318 }
2319 }
2320 else
2321 {
2322 packet->AddHeader(udpHeader);
2323 }
2324
2325 NS_LOG_DEBUG("Rebuilt packet: " << *packet << " Size " << packet->GetSize());
2326}
2327
2328void
2330 uint32_t origPacketSize,
2331 uint32_t origHdrSize,
2332 uint32_t extraHdrSize,
2333 std::list<Ptr<Packet>>& listFragments)
2334{
2335 NS_LOG_FUNCTION(this << *packet);
2336
2337 Ptr<Packet> p = packet->Copy();
2338
2339 uint16_t offsetData = 0;
2340 uint16_t offset = 0;
2341 uint16_t l2Mtu = m_netDevice->GetMtu();
2342 uint32_t packetSize = packet->GetSize();
2343 uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
2344
2345 auto tag = static_cast<uint16_t>(m_rng->GetValue(0, 65535));
2346 NS_LOG_LOGIC("random tag " << tag << " - test " << packetSize);
2347
2348 // first fragment
2349 SixLowPanFrag1 frag1Hdr;
2350 frag1Hdr.SetDatagramTag(tag);
2351
2352 uint32_t size;
2353 NS_ASSERT_MSG(l2Mtu > frag1Hdr.GetSerializedSize(),
2354 "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
2355
2356 // All the headers are subtracted to get remaining units for data
2357 size = l2Mtu - frag1Hdr.GetSerializedSize() - compressedHeaderSize - extraHdrSize;
2358 size -= size % 8;
2359 size += compressedHeaderSize;
2360
2361 frag1Hdr.SetDatagramSize(origPacketSize);
2362
2363 Ptr<Packet> fragment1 = p->CreateFragment(offsetData, size);
2364 offset += size + origHdrSize - compressedHeaderSize;
2365 offsetData += size;
2366
2367 fragment1->AddHeader(frag1Hdr);
2368 listFragments.push_back(fragment1);
2369
2370 bool moreFrag = true;
2371 do
2372 {
2373 SixLowPanFragN fragNHdr;
2374 fragNHdr.SetDatagramTag(tag);
2375 fragNHdr.SetDatagramSize(origPacketSize);
2376 fragNHdr.SetDatagramOffset((offset) >> 3);
2377
2378 size = l2Mtu - fragNHdr.GetSerializedSize() - extraHdrSize;
2379 size -= size % 8;
2380
2381 if ((offsetData + size) > packetSize)
2382 {
2383 size = packetSize - offsetData;
2384 moreFrag = false;
2385 }
2386
2387 if (size > 0)
2388 {
2389 NS_LOG_LOGIC("Fragment creation - " << offset << ", " << offset);
2390 Ptr<Packet> fragment = p->CreateFragment(offsetData, size);
2391 NS_LOG_LOGIC("Fragment created - " << offset << ", " << fragment->GetSize());
2392
2393 offset += size;
2394 offsetData += size;
2395
2396 fragment->AddHeader(fragNHdr);
2397 listFragments.push_back(fragment);
2398 }
2399 } while (moreFrag);
2400}
2401
2402bool
2404 const Address& src,
2405 const Address& dst,
2406 bool isFirst)
2407{
2408 NS_LOG_FUNCTION(this << *packet);
2409 SixLowPanFrag1 frag1Header;
2410 SixLowPanFragN fragNHeader;
2411 FragmentKey_t key;
2412 uint16_t packetSize;
2413 key.first = std::pair<Address, Address>(src, dst);
2414
2415 Ptr<Packet> p = packet->Copy();
2416 uint16_t offset = 0;
2417
2418 /* Implementation note:
2419 *
2420 * The fragment offset is relative to the *uncompressed* packet.
2421 * On the other hand, the packet can not be uncompressed correctly without all
2422 * its fragments, as the UDP checksum can not be computed otherwise.
2423 *
2424 * As a consequence we must uncompress the packet twice, and save its first
2425 * fragment for the final one.
2426 */
2427
2428 if (isFirst)
2429 {
2430 uint8_t dispatchRawValFrag1 = 0;
2431 SixLowPanDispatch::Dispatch_e dispatchValFrag1;
2432
2433 p->RemoveHeader(frag1Header);
2434 packetSize = frag1Header.GetDatagramSize();
2435 p->CopyData(&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
2436 dispatchValFrag1 = SixLowPanDispatch::GetDispatchType(dispatchRawValFrag1);
2437 NS_LOG_DEBUG("Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1));
2438 NS_LOG_DEBUG("Packet: " << *p);
2439
2440 switch (dispatchValFrag1)
2441 {
2443 SixLowPanIpv6 uncompressedHdr;
2444 p->RemoveHeader(uncompressedHdr);
2445 }
2446 break;
2448 DecompressLowPanHc1(p, src, dst);
2449 break;
2451 if (DecompressLowPanIphc(p, src, dst))
2452 {
2454 return false;
2455 }
2456 break;
2457 default:
2458 NS_FATAL_ERROR("Unsupported 6LoWPAN encoding, exiting.");
2459 break;
2460 }
2461
2462 key.second = std::pair<uint16_t, uint16_t>(frag1Header.GetDatagramSize(),
2463 frag1Header.GetDatagramTag());
2464 }
2465 else
2466 {
2467 p->RemoveHeader(fragNHeader);
2468 packetSize = fragNHeader.GetDatagramSize();
2469 offset = fragNHeader.GetDatagramOffset() << 3;
2470 key.second = std::pair<uint16_t, uint16_t>(fragNHeader.GetDatagramSize(),
2471 fragNHeader.GetDatagramTag());
2472 }
2473
2474 Ptr<Fragments> fragments;
2475
2476 auto it = m_fragments.find(key);
2477 if (it == m_fragments.end())
2478 {
2479 // erase the oldest packet.
2481 {
2482 auto iter = m_timeoutEventList.begin();
2483 FragmentKey_t oldestKey = std::get<1>(*iter);
2484
2485 std::list<Ptr<Packet>> storedFragments = m_fragments[oldestKey]->GetFragments();
2486 for (auto fragIter = storedFragments.begin(); fragIter != storedFragments.end();
2487 fragIter++)
2488 {
2490 }
2491
2492 m_timeoutEventList.erase(m_fragments[oldestKey]->GetTimeoutIter());
2493 m_fragments[oldestKey] = nullptr;
2494 m_fragments.erase(oldestKey);
2495 }
2496 fragments = Create<Fragments>();
2497 fragments->SetPacketSize(packetSize);
2498 m_fragments.insert(std::make_pair(key, fragments));
2499 uint32_t ifIndex = GetIfIndex();
2500
2501 auto iter = SetTimeout(key, ifIndex);
2502 fragments->SetTimeoutIter(iter);
2503 }
2504 else
2505 {
2506 fragments = it->second;
2507 }
2508
2509 fragments->AddFragment(p, offset);
2510
2511 // add the very first fragment so we can correctly decode the packet once is rebuilt.
2512 // this is needed because otherwise the UDP header length and checksum can not be calculated.
2513 if (isFirst)
2514 {
2515 fragments->AddFirstFragment(packet);
2516 }
2517
2518 if (fragments->IsEntire())
2519 {
2520 packet = fragments->GetPacket();
2521 NS_LOG_LOGIC("Reconstructed packet: " << *packet);
2522
2523 SixLowPanFrag1 frag1Header;
2524 packet->RemoveHeader(frag1Header);
2525
2526 NS_LOG_LOGIC("Rebuilt packet. Size " << packet->GetSize() << " - " << *packet);
2527 m_timeoutEventList.erase(fragments->GetTimeoutIter());
2528 fragments = nullptr;
2529 m_fragments.erase(key);
2530 return true;
2531 }
2532
2533 return false;
2534}
2535
2537{
2538 NS_LOG_FUNCTION(this);
2539 m_packetSize = 0;
2540}
2541
2543{
2544 NS_LOG_FUNCTION(this);
2545}
2546
2547void
2549{
2550 NS_LOG_FUNCTION(this << fragmentOffset << *fragment);
2551
2552 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
2553 bool duplicate = false;
2554
2555 for (it = m_fragments.begin(); it != m_fragments.end(); it++)
2556 {
2557 if (it->second > fragmentOffset)
2558 {
2559 break;
2560 }
2561 if (it->second == fragmentOffset)
2562 {
2563 duplicate = true;
2564 NS_ASSERT_MSG(fragment->GetSize() == it->first->GetSize(),
2565 "Duplicate fragment size differs. Aborting.");
2566 break;
2567 }
2568 }
2569 if (!duplicate)
2570 {
2571 m_fragments.insert(it, std::make_pair(fragment, fragmentOffset));
2572 }
2573}
2574
2575void
2577{
2578 NS_LOG_FUNCTION(this << *fragment);
2579
2580 m_firstFragment = fragment;
2581}
2582
2583bool
2585{
2586 NS_LOG_FUNCTION(this);
2587
2588 bool ret = !m_fragments.empty();
2589 uint16_t lastEndOffset = 0;
2590
2591 if (ret)
2592 {
2593 for (auto it = m_fragments.begin(); it != m_fragments.end(); it++)
2594 {
2595 // overlapping fragments should not exist
2596 NS_LOG_LOGIC("Checking overlaps " << lastEndOffset << " - " << it->second);
2597
2598 if (lastEndOffset < it->second)
2599 {
2600 ret = false;
2601 break;
2602 }
2603 // fragments might overlap in strange ways
2604 uint16_t fragmentEnd = it->first->GetSize() + it->second;
2605 lastEndOffset = std::max(lastEndOffset, fragmentEnd);
2606 }
2607 }
2608
2609 return ret && lastEndOffset == m_packetSize;
2610}
2611
2614{
2615 NS_LOG_FUNCTION(this);
2616
2617 auto it = m_fragments.begin();
2618
2619 Ptr<Packet> p = Create<Packet>();
2620 uint16_t lastEndOffset = 0;
2621
2622 p->AddAtEnd(m_firstFragment);
2623 it = m_fragments.begin();
2624 lastEndOffset = it->first->GetSize();
2625
2626 for (it++; it != m_fragments.end(); it++)
2627 {
2628 if (lastEndOffset > it->second)
2629 {
2630 NS_ABORT_MSG("Overlapping fragments found, forbidden condition");
2631 }
2632 else
2633 {
2634 NS_LOG_LOGIC("Adding: " << *(it->first));
2635 p->AddAtEnd(it->first);
2636 }
2637 lastEndOffset += it->first->GetSize();
2638 }
2639
2640 return p;
2641}
2642
2643void
2645{
2646 NS_LOG_FUNCTION(this << packetSize);
2647 m_packetSize = packetSize;
2648}
2649
2650std::list<Ptr<Packet>>
2652{
2653 std::list<Ptr<Packet>> fragments;
2654 for (auto iter = m_fragments.begin(); iter != m_fragments.end(); iter++)
2655 {
2656 fragments.push_back(iter->first);
2657 }
2658 return fragments;
2659}
2660
2661void
2663{
2664 m_timeoutIter = iter;
2665}
2666
2669{
2670 return m_timeoutIter;
2671}
2672
2673void
2675{
2676 NS_LOG_FUNCTION(this);
2677
2678 auto it = m_fragments.find(key);
2679 std::list<Ptr<Packet>> storedFragments = it->second->GetFragments();
2680 for (auto fragIter = storedFragments.begin(); fragIter != storedFragments.end(); fragIter++)
2681 {
2682 m_dropTrace(DROP_FRAGMENT_TIMEOUT, *fragIter, this, iif);
2683 }
2684 // clear the buffers
2685 it->second = nullptr;
2686
2687 m_fragments.erase(key);
2688}
2689
2690Address
2692{
2693 NS_ASSERT_MSG(Mac48Address::IsMatchingType(addr), "Need a Mac48Address" << addr);
2694
2695 uint8_t buf[6];
2696 addr.CopyTo(buf);
2697
2698 Mac16Address shortAddr;
2699 shortAddr.CopyFrom(buf + 4);
2700
2701 return shortAddr;
2702}
2703
2706{
2707 if (m_timeoutEventList.empty())
2708 {
2711 this);
2712 }
2714
2715 auto iter = --m_timeoutEventList.end();
2716
2717 return (iter);
2718}
2719
2720void
2722{
2723 Time now = Simulator::Now();
2724
2725 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
2726 {
2727 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
2728 std::get<2>(*m_timeoutEventList.begin()));
2729 m_timeoutEventList.pop_front();
2730 }
2731
2732 if (m_timeoutEventList.empty())
2733 {
2734 return;
2735 }
2736
2737 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
2739}
2740
2741void
2743 Ipv6Prefix contextPrefix,
2744 bool compressionAllowed,
2745 Time validLifetime)
2746{
2747 NS_LOG_FUNCTION(this << +contextId << Ipv6Address::GetOnes().CombinePrefix(contextPrefix)
2748 << contextPrefix << compressionAllowed << validLifetime.As(Time::S));
2749
2750 if (contextId > 15)
2751 {
2752 NS_LOG_LOGIC("Invalid context ID (" << +contextId << "), ignoring");
2753 return;
2754 }
2755
2756 if (validLifetime == Time(0))
2757 {
2758 NS_LOG_LOGIC("Context (" << +contextId << "), removed (validity time is zero)");
2759 m_contextTable.erase(contextId);
2760 return;
2761 }
2762
2763 m_contextTable[contextId].contextPrefix = contextPrefix;
2764 m_contextTable[contextId].compressionAllowed = compressionAllowed;
2765 m_contextTable[contextId].validLifetime = Simulator::Now() + validLifetime;
2766}
2767
2768bool
2770 Ipv6Prefix& contextPrefix,
2771 bool& compressionAllowed,
2772 Time& validLifetime)
2773{
2774 NS_LOG_FUNCTION(this << +contextId);
2775
2776 if (contextId > 15)
2777 {
2778 NS_LOG_LOGIC("Invalid context ID (" << +contextId << "), ignoring");
2779 return false;
2780 }
2781
2782 if (m_contextTable.find(contextId) == m_contextTable.end())
2783 {
2784 NS_LOG_LOGIC("Context not found (" << +contextId << "), ignoring");
2785 return false;
2786 }
2787
2788 contextPrefix = m_contextTable[contextId].contextPrefix;
2789 compressionAllowed = m_contextTable[contextId].compressionAllowed;
2790 validLifetime = m_contextTable[contextId].validLifetime;
2791
2792 return true;
2793}
2794
2795void
2796SixLowPanNetDevice::RenewContext(uint8_t contextId, Time validLifetime)
2797{
2798 NS_LOG_FUNCTION(this << +contextId << validLifetime.As(Time::S));
2799
2800 if (contextId > 15)
2801 {
2802 NS_LOG_LOGIC("Invalid context ID (" << +contextId << "), ignoring");
2803 return;
2804 }
2805
2806 if (m_contextTable.find(contextId) == m_contextTable.end())
2807 {
2808 NS_LOG_LOGIC("Context not found (" << +contextId << "), ignoring");
2809 return;
2810 }
2811 m_contextTable[contextId].compressionAllowed = true;
2812 m_contextTable[contextId].validLifetime = Simulator::Now() + validLifetime;
2813}
2814
2815void
2817{
2818 NS_LOG_FUNCTION(this << +contextId);
2819
2820 if (contextId > 15)
2821 {
2822 NS_LOG_LOGIC("Invalid context ID (" << +contextId << "), ignoring");
2823 return;
2824 }
2825
2826 if (m_contextTable.find(contextId) == m_contextTable.end())
2827 {
2828 NS_LOG_LOGIC("Context not found (" << +contextId << "), ignoring");
2829 return;
2830 }
2831 m_contextTable[contextId].compressionAllowed = false;
2832}
2833
2834void
2836{
2837 NS_LOG_FUNCTION(this << +contextId);
2838
2839 if (contextId > 15)
2840 {
2841 NS_LOG_LOGIC("Invalid context ID (" << +contextId << "), ignoring");
2842 return;
2843 }
2844
2845 if (m_contextTable.find(contextId) == m_contextTable.end())
2846 {
2847 NS_LOG_LOGIC("Context not found (" << +contextId << "), ignoring");
2848 return;
2849 }
2850
2851 m_contextTable.erase(contextId);
2852}
2853
2854bool
2856{
2857 NS_LOG_FUNCTION(this << address);
2858
2859 for (const auto& iter : m_contextTable)
2860 {
2861 ContextEntry context = iter.second;
2862
2863 if (context.compressionAllowed && context.validLifetime > Simulator::Now())
2864 {
2865 if (address.HasPrefix(context.contextPrefix))
2866 {
2867 NS_LOG_LOGIC("Found context "
2868 << +contextId << " "
2869 << Ipv6Address::GetOnes().CombinePrefix(context.contextPrefix)
2870 << context.contextPrefix << " matching");
2871
2872 contextId = iter.first;
2873 return true;
2874 }
2875 }
2876 }
2877 return false;
2878}
2879
2880bool
2882{
2883 NS_LOG_FUNCTION(this << address);
2884
2885 // The only allowed context-based compressed multicast address is in the form
2886 // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
2887
2888 for (const auto& iter : m_contextTable)
2889 {
2890 ContextEntry context = iter.second;
2891
2892 if (context.compressionAllowed && context.validLifetime > Simulator::Now())
2893 {
2894 uint8_t contextLength = context.contextPrefix.GetPrefixLength();
2895
2896 if (contextLength <= 64) // only 64-bit prefixes or less are allowed.
2897 {
2898 uint8_t contextBytes[16];
2899 uint8_t addressBytes[16];
2900
2901 context.contextPrefix.GetBytes(contextBytes);
2902 address.GetBytes(addressBytes);
2903
2904 if (addressBytes[3] == contextLength && addressBytes[4] == contextBytes[0] &&
2905 addressBytes[5] == contextBytes[1] && addressBytes[6] == contextBytes[2] &&
2906 addressBytes[7] == contextBytes[3] && addressBytes[8] == contextBytes[4] &&
2907 addressBytes[9] == contextBytes[5] && addressBytes[10] == contextBytes[6] &&
2908 addressBytes[11] == contextBytes[7])
2909 {
2910 NS_LOG_LOGIC("Found context "
2911 << +contextId << " "
2912 << Ipv6Address::GetOnes().CombinePrefix(context.contextPrefix)
2913 << context.contextPrefix << " matching");
2914
2915 contextId = iter.first;
2916 return true;
2917 }
2918 }
2919 }
2920 }
2921 return false;
2922}
2923
2926{
2927 uint8_t addressBytes[16];
2928 address.GetBytes(addressBytes);
2929 uint8_t prefixLength = prefix.GetPrefixLength();
2930
2931 uint8_t bytesToClean = prefixLength / 8;
2932 uint8_t bitsToClean = prefixLength % 8;
2933 for (uint8_t i = 0; i < bytesToClean; i++)
2934 {
2935 addressBytes[i] = 0;
2936 }
2937 if (bitsToClean)
2938 {
2939 uint8_t cleanupMask = (1 << bitsToClean) - 1;
2940 addressBytes[bytesToClean] &= cleanupMask;
2941 }
2942
2943 Ipv6Address cleanedAddress = Ipv6Address::Deserialize(addressBytes);
2944
2945 return cleanedAddress;
2946}
2947
2948} // namespace ns3
2949
2950// namespace ns3
a polymophic address class
Definition: address.h:101
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition: address.cc:86
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Write(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:954
automatically resized byte buffer
Definition: buffer.h:94
uint32_t GetSize() const
Definition: buffer.h:1068
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:447
const uint8_t * PeekData() const
Definition: buffer.cc:709
Callback template class.
Definition: callback.h:438
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Describes an IPv6 address.
Definition: ipv6-address.h:49
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static Ipv6Address Deserialize(const uint8_t buf[16])
Deserialize this address.
static Ipv6Address MakeAutoconfiguredAddress(Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address from a Mac address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
void Serialize(uint8_t buf[16]) const
Serialize this address to a 16-byte buffer.
static Ipv6Address GetOnes()
Get the "all-1" IPv6 address (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
Header of IPv6 Extension Destination.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
void Serialize(Buffer::Iterator start) const override
Serialize the packet.
Header of IPv6 Extension Fragment.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
void Serialize(Buffer::Iterator start) const override
Serialize the packet.
uint16_t GetLength() const
Get the length of the extension.
uint8_t GetNextHeader() const
Get the next header.
Header of IPv6 Extension "Hop by Hop".
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
void Serialize(Buffer::Iterator start) const override
Serialize the packet.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Header of IPv6 Extension Routing.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
void Serialize(Buffer::Iterator start) const override
Serialize the packet.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Packet header for IPv6.
Definition: ipv6-header.h:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
uint32_t GetFlowLabel() const
Get the "Flow label" field.
Definition: ipv6-header.cc:64
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:106
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:94
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
uint8_t GetTrafficClass() const
Get the "Traffic class" field.
Definition: ipv6-header.cc:52
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:70
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
void SetFlowLabel(uint32_t flow)
Set the "Flow label" field.
Definition: ipv6-header.cc:58
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
Definition: ipv6-header.cc:46
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:82
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
uint8_t GetPrefixLength() const
Get prefix length.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the prefix.
This class can contain 16 bit addresses.
Definition: mac16-address.h:44
static bool IsMatchingType(const Address &address)
static Mac16Address ConvertFrom(const Address &address)
void CopyFrom(const uint8_t buffer[2])
bool IsMulticast() const
Checks if the address is a multicast address according to RFC 4944 Section 9 (i.e....
bool IsBroadcast() const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
static bool IsMatchingType(const Address &address)
Network layer to device interface.
Definition: net-device.h:98
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:300
uint32_t GetId() const
Definition: node.cc:117
static bool ChecksumEnabled()
Definition: node.cc:285
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:238
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:558
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
6LoWPAN BC0 header - see RFC 4944.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetSequenceNumber(uint8_t seqNumber)
Set the "Sequence Number" field.
uint8_t GetSequenceNumber() const
Get the "Sequence Number" field.
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
NhcDispatch_e
Dispatch values for Next Header compression.
6LoWPAN FRAG1 header - see RFC 4944.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
uint16_t GetDatagramSize() const
Get the datagram size.
uint16_t GetDatagramTag() const
Get the datagram tag.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
6LoWPAN FRAGN header - see RFC 4944.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
uint16_t GetDatagramTag() const
Get the datagram tag.
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
void SetDatagramOffset(uint8_t datagramOffset)
Set the datagram offset.
uint8_t GetDatagramOffset() const
Get the datagram offset.
uint16_t GetDatagramSize() const
Get the datagram size.
6LoWPAN HC1 header - see RFC 4944.
void SetTcflCompression(bool tcflCompression)
Set the Traffic Class and Flow Labels as compressed.
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label value.
void SetDstCompression(LowPanHc1Addr_e dstCompression)
Set Destination Compression type.
void SetTrafficClass(uint8_t trafficClass)
Set the Traffic Class value.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header value.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
void SetDstPrefix(const uint8_t *dstPrefix)
Set the destination prefix.
void SetSrcPrefix(const uint8_t *srcPrefix)
Set the source prefix.
void SetSrcInterface(const uint8_t *srcInterface)
Set the source interface.
LOWPAN_IPHC base Encoding - see RFC 6282.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field.
void SetHlim(Hlim_e hlimField)
Set the HLIM (Hop Limit) compression.
void SetDstContextId(uint8_t dstContextId)
Set the DstContextId.
void SetSam(HeaderCompression_e samField)
Set the SAM (Source Address Mode) compression.
void SetNh(bool nhField)
Set the NH (Next Header) compression.
void SetEcn(uint8_t ecn)
Set the ECN (2bits).
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label (20bits).
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
void SetTf(TrafficClassFlowLabel_e tfField)
Set the TF (Traffic Class, Flow Label) compression.
void SetDam(HeaderCompression_e damField)
Set the DAM (Destination Address Mode) compression.
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetSac(bool sacField)
Set the SAC (Source Address Compression) compression.
bool GetM() const
Get the M (Multicast) compression.
void SetDstInlinePart(uint8_t dstInlinePart[16], uint8_t size)
brief Set the destination address inline part
void SetSrcContextId(uint8_t srcContextId)
Set the SrcContextId.
void SetSrcInlinePart(uint8_t srcInlinePart[16], uint8_t size)
brief Set the source address inline part
void SetM(bool mField)
Set the M (Multicast) compression.
void SetHopLimit(uint8_t hopLimit)
Set the Hop Limit field.
void SetDac(bool dacField)
Set the DAC (Destination Address Compression) compression.
6LoWPAN IPv6 uncompressed header - see RFC 4944.
6LoWPAN Mesh header - see RFC 4944.
Address GetOriginator() const
Get the "Originator" address.
void SetHopsLeft(uint8_t hopsLeft)
Set the "Hops Left" field.
void SetFinalDst(Address finalDst)
Set the "Final Destination" address.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
uint8_t GetHopsLeft() const
Get the "Hops Left" field.
Address GetFinalDst() const
Get the "Final Destination" address.
void SetOriginator(Address originator)
Set the "Originator" address.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
bool IsEntire() const
If all fragments have been added.
std::list< Ptr< Packet > > GetFragments() const
Get a list of the current stored fragments.
void SetPacketSize(uint32_t packetSize)
Set the packet-to-be-defragmented size.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset)
Add a fragment to the pool.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
Ptr< Packet > GetPacket() const
Get the entire packet.
void AddFirstFragment(Ptr< Packet > fragment)
Add the first packet fragment.
Shim performing 6LoWPAN compression, decompression and fragmentation.
bool IsLinkUp() const override
bool SetMtu(const uint16_t mtu) override
void DecompressLowPanUdpNhc(Ptr< Packet > packet, Ipv6Address saddr, Ipv6Address daddr)
Decompress the headers according to NHC compression.
bool DoSend(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber, bool doSendFrom)
Ipv6Address CleanPrefix(Ipv6Address address, Ipv6Prefix prefix)
Clean an address from its prefix.
uint8_t m_bc0Serial
Serial number used in BC0 header.
bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber) override
void SetNode(Ptr< Node > node) override
bool NeedsArp() const override
EventId m_timeoutEvent
Event for the next scheduled timeout.
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
Ptr< UniformRandomVariable > m_rng
Rng for the fragments tag.
uint16_t m_meshCacheLength
length of the cache for each source.
bool IsPointToPoint() const override
Return true if the net device is on a point-to-point link.
bool m_useIphc
Use IPHC or HC1.
void RenewContext(uint8_t contextId, Time validLifetime)
Renew a context used in IPHC stateful compression.
bool DecompressLowPanIphc(Ptr< Packet > packet, const Address &src, const Address &dst)
Decompress the headers according to IPHC compression.
uint32_t CompressLowPanHc1(Ptr< Packet > packet, const Address &src, const Address &dst)
Compress the headers according to HC1 compression.
bool IsBridge() const override
Return true if the net device is acting as a bridge.
void DoFragmentation(Ptr< Packet > packet, uint32_t origPacketSize, uint32_t origHdrSize, uint32_t extraHdrSize, std::list< Ptr< Packet > > &listFragments)
Performs a packet fragmentation.
Ptr< Node > m_node
Smart pointer to the Node.
bool CanCompressLowPanNhc(uint8_t headerType)
Checks if the next header can be compressed using NHC.
Ptr< Channel > GetChannel() const override
uint16_t GetMtu() const override
Returns the link-layer MTU for this interface.
std::list< std::tuple< Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
bool m_forceEtherType
Force the EtherType number.
Address GetAddress() const override
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override
uint32_t m_compressionThreshold
Minimum L2 payload size.
Ptr< NetDevice > GetNetDevice() const
Returns a smart pointer to the underlying NetDevice.
void HandleTimeout()
Handles a fragmented packet timeout.
void ReceiveFromDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, const Address &source, const Address &destination, PacketType packetType)
Receives all the packets from a NetDevice for further processing.
uint32_t CompressLowPanNhc(Ptr< Packet > packet, uint8_t headerType, const Address &src, const Address &dst)
Compress the headers according to NHC compression.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
std::pair< std::pair< Address, Address >, std::pair< uint16_t, uint16_t > > FragmentKey_t
Fragment identifier type: src/dst address src/dst port.
@ DROP_DISALLOWED_COMPRESSION
HC1 while in IPHC mode or vice-versa.
@ DROP_UNKNOWN_EXTENSION
Unsupported compression kind.
@ DROP_FRAGMENT_BUFFER_FULL
Fragment buffer size exceeded.
@ DROP_SATETFUL_DECOMPRESSION_PROBLEM
Decompression failed due to missing or expired context.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
void AddContext(uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
Add, remove, or update a context used in IPHC stateful compression.
Ptr< NetDevice > m_netDevice
Smart pointer to the underlying NetDevice.
void SetNetDevice(Ptr< NetDevice > device)
Setup SixLowPan to be a proxy for the specified NetDevice.
std::map< uint8_t, ContextEntry > m_contextTable
Table of the contexts used in compression/decompression.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
bool GetContext(uint8_t contextId, Ipv6Prefix &contextPrefix, bool &compressionAllowed, Time &validLifetime)
Get a context used in IPHC stateful compression.
uint32_t GetIfIndex() const override
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
bool IsBroadcast() const override
Address Get16MacFrom48Mac(Address addr)
Get a Mac16 from its Mac48 pseudo-MAC.
TracedCallback< DropReason, Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_dropTrace
Callback to trace drop packets.
void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb) override
bool FindUnicastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given unicast address matches a context for compression.
Ptr< RandomVariableStream > m_meshUnderJitter
Random variable for the mesh-under packet retransmission.
uint32_t CompressLowPanUdpNhc(Ptr< Packet > packet, bool omitChecksum)
Compress the headers according to NHC compression.
void RemoveContext(uint8_t contextId)
Remove a context used in IPHC stateful compression.
bool m_omitUdpChecksum
Omit UDP checksum in NC1 encoding.
Ptr< Node > GetNode() const override
void AddLinkChangeCallback(Callback< void > callback) override
uint32_t m_ifIndex
Interface index.
Address GetBroadcast() const override
void SetIfIndex(const uint32_t index) override
uint32_t CompressLowPanIphc(Ptr< Packet > packet, const Address &src, const Address &dst)
Compress the headers according to IPHC compression.
void DoDispose() override
Destructor implementation.
bool IsMulticast() const override
Address GetMulticast(Ipv4Address multicastGroup) const override
Make and return a MAC multicast address using the provided multicast group.
Time m_fragmentExpirationTimeout
Time limit for fragment rebuilding.
uint16_t m_fragmentReassemblyListSize
How many packets can be rebuilt at the same time.
uint8_t m_meshUnderHopsLeft
Start value for mesh-under hops left.
void SetAddress(Address address) override
Set the address of this interface.
void DecompressLowPanHc1(Ptr< Packet > packet, const Address &src, const Address &dst)
Decompress the headers according to HC1 compression.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
std::pair< uint8_t, bool > DecompressLowPanNhc(Ptr< Packet > packet, const Address &src, const Address &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
Decompress the headers according to NHC compression.
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode.
void HandleFragmentsTimeout(FragmentKey_t key, uint32_t iif)
Process the timeout for packet fragments.
void InvalidateContext(uint8_t contextId)
Invalidate a context used in IPHC stateful compression.
static TypeId GetTypeId()
Get the type ID.
bool SupportsSendFrom() const override
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
bool ProcessFragment(Ptr< Packet > &packet, const Address &src, const Address &dst, bool isFirst)
Process a packet fragment.
MapFragments_t m_fragments
Fragments hold to be rebuilt.
bool FindMulticastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given multicast address matches a context for compression.
bool m_meshUnder
Use a mesh-under routing.
std::map< Address, std::list< uint8_t > > m_seenPkts
Seen packets, memorized by OriginatorAddress, SequenceNumber.
SixLowPanNetDevice()
Constructor for the SixLowPanNetDevice.
uint16_t m_etherType
EtherType number (used only if m_forceEtherType is true).
LOWPAN_NHC Extension Header Encoding - see RFC 6282.
void SetNh(bool nhField)
Set the NH field values.
void SetEid(Eid_e extensionHeaderType)
Set the Extension Header Type.
void SetBlob(const uint8_t *blob, uint32_t size)
Set the option header data blob.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
UDP LOWPAN_NHC Extension Header Encoding - see RFC 6282.
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
void SetChecksum(uint16_t checksum)
Set the Checksum field values.
void SetDstPort(uint16_t port)
Set the Destination Port.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetSrcPort(uint16_t port)
Set the Source Port.
void SetC(bool cField)
Set the C (Checksum).
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
@ S
second
Definition: nstime.h:116
AttributeValue implementation for Time.
Definition: nstime.h:1412
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:930
Packet header for UDP packets.
Definition: udp-header.h:41
void EnableChecksums()
Enable checksum calculation for UDP.
Definition: udp-header.cc:30
uint16_t GetDestinationPort() const
Definition: udp-header.cc:54
void ForceChecksum(uint16_t checksum)
Force the UDP checksum to a given value.
Definition: udp-header.cc:124
uint16_t GetSourcePort() const
Definition: udp-header.cc:48
bool IsChecksumOk() const
Is the UDP checksum correct ?
Definition: udp-header.cc:118
uint16_t GetChecksum() const
Return the checksum (only known after a Deserialize)
Definition: udp-header.cc:223
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:60
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:42
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:36
static const uint8_t PROT_NUMBER
protocol number (0x11)
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#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:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1433
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1413
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1325
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1337
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
Definition: second.py:1
Structure holding the information for a context (used in compression and decompression)
Ipv6Prefix contextPrefix
context prefix to be used in compression/decompression
bool compressionAllowed
compression and decompression allowed (true), decompression only (false)
Time validLifetime
validity period
uint32_t pktSize
packet size used for the simulation (in bytes)
static const uint32_t packetSize
Packet size generated at the AP.