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