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