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