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