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