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