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