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