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