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 
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");
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);
285  Simulator::Schedule (Time (MilliSeconds (m_meshUnderJitter->GetValue ())), &NetDevice::Send, m_netDevice, sendPkt, m_netDevice->GetBroadcast (), protocol);
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.");
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 
409  m_netDevice->SetAddress (address);
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 );
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  {
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.GetSourceAddress ();
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.GetDestinationAddress ();
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  uint32_t ret = packet->RemoveHeader (encoding);
831  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
832  NS_UNUSED (ret);
833 
834  ipHeader.SetHopLimit (encoding.GetHopLimit ());
835 
836  switch (encoding.GetSrcCompression ())
837  {
838  const uint8_t* interface;
839  const uint8_t* prefix;
840  uint8_t address[16];
841 
843  prefix = encoding.GetSrcPrefix ();
844  interface = encoding.GetSrcInterface ();
845  for (int j = 0; j < 8; j++)
846  {
847  address[j + 8] = interface[j];
848  address[j] = prefix[j];
849  }
850  ipHeader.SetSourceAddress ( Ipv6Address (address) );
851  break;
853  prefix = encoding.GetSrcPrefix ();
854  for (int j = 0; j < 8; j++)
855  {
856  address[j + 8] = 0;
857  address[j] = prefix[j];
858  }
860  break;
862  interface = encoding.GetSrcInterface ();
863  address[0] = 0xfe;
864  address[1] = 0x80;
865  for (int j = 0; j < 8; j++)
866  {
867  address[j + 8] = interface[j];
868  }
869  ipHeader.SetSourceAddress ( Ipv6Address (address) );
870  break;
873  break;
874  }
875 
876  switch (encoding.GetDstCompression ())
877  {
878  const uint8_t* interface;
879  const uint8_t* prefix;
880  uint8_t address[16];
881 
883  prefix = encoding.GetDstPrefix ();
884  interface = encoding.GetDstInterface ();
885  for (int j = 0; j < 8; j++)
886  {
887  address[j + 8] = interface[j];
888  address[j] = prefix[j];
889  }
891  break;
893  prefix = encoding.GetDstPrefix ();
894  for (int j = 0; j < 8; j++)
895  {
896  address[j + 8] = 0;
897  address[j] = prefix[j];
898  }
900  break;
902  interface = encoding.GetDstInterface ();
903  address[0] = 0xfe;
904  address[1] = 0x80;
905  for (int j = 0; j < 8; j++)
906  {
907  address[j + 8] = interface[j];
908  }
910  break;
913  break;
914  }
915 
916  if ( !encoding.IsTcflCompression () )
917  {
918  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
919  ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
920  }
921  else
922  {
923  ipHeader.SetFlowLabel (0);
924  ipHeader.SetTrafficClass (0);
925  }
926 
927  ipHeader.SetNextHeader (encoding.GetNextHeader ());
928 
929  ipHeader.SetPayloadLength (packet->GetSize ());
930 
931  NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
932  "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
933 
934  packet->AddHeader (ipHeader);
935 
936  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
937 }
938 
939 uint32_t
941 {
942  NS_LOG_FUNCTION (this << *packet << src << dst);
943 
944  Ipv6Header ipHeader;
945  SixLowPanIphc iphcHeader;
946  uint32_t size = 0;
947 
948  NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () << " src: " << src << " dst: " << dst);
949 
950  if ( packet->PeekHeader (ipHeader) != 0 )
951  {
952  packet->RemoveHeader (ipHeader);
953  size += ipHeader.GetSerializedSize ();
954 
955  // Set the TF field
956  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
957  {
958  iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
959  }
960  else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
961  {
962  iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
963  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
964  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
965  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
966  }
967  else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
968  {
969  iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
970  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
971  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
972  }
973  else
974  {
976  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
977  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
978  }
979 
980  // Set the NH field and NextHeader
981 
982  uint8_t nextHeader = ipHeader.GetNextHeader ();
983  if (CanCompressLowPanNhc (nextHeader))
984  {
985  if (nextHeader == Ipv6Header::IPV6_UDP)
986  {
987  iphcHeader.SetNh (true);
988  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
989  }
990  else if (nextHeader == Ipv6Header::IPV6_IPV6)
991  {
992  iphcHeader.SetNh (true);
993  size += CompressLowPanIphc (packet, src, dst);
994  }
995  else
996  {
997  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
998  // the compression might fail due to Extension header size.
999  if (sizeNhc)
1000  {
1001  iphcHeader.SetNh (true);
1002  size += sizeNhc;
1003  }
1004  else
1005  {
1006  iphcHeader.SetNh (false);
1007  iphcHeader.SetNextHeader (nextHeader);
1008  }
1009  }
1010  }
1011  else
1012  {
1013  iphcHeader.SetNh (false);
1014  iphcHeader.SetNextHeader (nextHeader);
1015  }
1016 
1017  // Set the HLIM field
1018  if (ipHeader.GetHopLimit () == 1)
1019  {
1020  iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_1);
1021  }
1022  else if (ipHeader.GetHopLimit () == 0x40)
1023  {
1025  }
1026  else if (ipHeader.GetHopLimit () == 0xFF)
1027  {
1029  }
1030  else
1031  {
1032  iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
1033  // Set the HopLimit
1034  iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
1035  }
1036 
1037  // Set the CID + SAC + DAC fields to their default value
1038  iphcHeader.SetCid (false);
1039  iphcHeader.SetSac (false);
1040  iphcHeader.SetDac (false);
1041 
1042 
1043  Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
1044  uint8_t unicastAddrCheckerBuf[16];
1045  checker.GetBytes (unicastAddrCheckerBuf);
1046  uint8_t addressBuf[16];
1047 
1048  // This is just to limit the scope of some variables.
1049  if (true)
1050  {
1051  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
1052  uint8_t srcContextId;
1053 
1054  // The "::" address is compressed as a fake stateful compression.
1055  if (srcAddr == Ipv6Address::GetAny ())
1056  {
1057  // No context information is needed.
1058  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1059  iphcHeader.SetSac (true);
1060  }
1061  // Check if the address can be compressed with stateful compression
1062  else if ( FindUnicastCompressionContext (srcAddr, srcContextId) )
1063  {
1064  // We can do stateful compression.
1065  NS_LOG_LOGIC ("Checking stateful source compression: " << srcAddr );
1066 
1067  iphcHeader.SetSac (true);
1068  if (srcContextId != 0)
1069  {
1070  // the default context is zero, no need to explicit it if it's zero
1071  iphcHeader.SetSrcContextId (srcContextId);
1072  iphcHeader.SetCid (true);
1073  }
1074 
1075  // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1076 
1077  if (Ipv6Address::MakeAutoconfiguredAddress (src, m_contextTable[srcContextId].contextPrefix) == srcAddr)
1078  {
1079  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1080  }
1081  else
1082  {
1083  Ipv6Address cleanedAddr = CleanPrefix (srcAddr, m_contextTable[srcContextId].contextPrefix);
1084  uint8_t serializedCleanedAddress[16];
1085  cleanedAddr.Serialize (serializedCleanedAddress);
1086 
1087  if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1088  serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1089  serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1090  {
1091  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1092  iphcHeader.SetSrcInlinePart (serializedCleanedAddress+14, 2);
1093  }
1094  else
1095  {
1096  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1097  iphcHeader.SetSrcInlinePart (serializedCleanedAddress+8, 8);
1098 
1099  }
1100  }
1101  }
1102  else
1103  {
1104  // We must do stateless compression.
1105  NS_LOG_LOGIC ("Checking stateless source compression: " << srcAddr );
1106 
1107  srcAddr.GetBytes (addressBuf);
1108 
1109  uint8_t serializedSrcAddress[16];
1110  srcAddr.Serialize (serializedSrcAddress);
1111 
1112  if ( srcAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src) )
1113  {
1114  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1115  }
1116  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1117  {
1118  iphcHeader.SetSrcInlinePart (serializedSrcAddress+14, 2);
1119  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1120  }
1121  else if ( srcAddr.IsLinkLocal () )
1122  {
1123  iphcHeader.SetSrcInlinePart (serializedSrcAddress+8, 8);
1124  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1125  }
1126  else
1127  {
1128  iphcHeader.SetSrcInlinePart (serializedSrcAddress, 16);
1129  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1130  }
1131  }
1132  }
1133 
1134  // Set the M field
1135  if (ipHeader.GetDestinationAddress ().IsMulticast ())
1136  {
1137  iphcHeader.SetM (true);
1138  }
1139  else
1140  {
1141  iphcHeader.SetM (false);
1142  }
1143 
1144  // This is just to limit the scope of some variables.
1145  if (true)
1146  {
1147  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
1148  dstAddr.GetBytes (addressBuf);
1149 
1150  NS_LOG_LOGIC ("Checking destination compression: " << dstAddr );
1151 
1152  uint8_t serializedDstAddress[16];
1153  dstAddr.Serialize (serializedDstAddress);
1154 
1155  if ( !iphcHeader.GetM () )
1156  {
1157  // Unicast address
1158 
1159  uint8_t dstContextId;
1160  if ( FindUnicastCompressionContext (dstAddr, dstContextId) )
1161  {
1162  // We can do stateful compression.
1163  NS_LOG_LOGIC ("Checking stateful destination compression: " << dstAddr );
1164 
1165  iphcHeader.SetDac (true);
1166  if (dstContextId != 0)
1167  {
1168  // the default context is zero, no need to explicit it if it's zero
1169  iphcHeader.SetDstContextId (dstContextId);
1170  iphcHeader.SetCid (true);
1171  }
1172 
1173  // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1174  if (Ipv6Address::MakeAutoconfiguredAddress (dst, m_contextTable[dstContextId].contextPrefix) == dstAddr)
1175  {
1176  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1177  }
1178  else
1179  {
1180  Ipv6Address cleanedAddr = CleanPrefix (dstAddr, m_contextTable[dstContextId].contextPrefix);
1181 
1182  uint8_t serializedCleanedAddress[16];
1183  cleanedAddr.Serialize (serializedCleanedAddress);
1184 
1185  if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1186  serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1187  serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1188  {
1189  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1190  iphcHeader.SetDstInlinePart (serializedCleanedAddress+14, 2);
1191  }
1192  else
1193  {
1194  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1195  iphcHeader.SetDstInlinePart (serializedCleanedAddress+8, 8);
1196  }
1197  }
1198  }
1199  else
1200  {
1201  NS_LOG_LOGIC ("Checking stateless destination compression: " << dstAddr );
1202 
1203  if ( dstAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst) )
1204  {
1205  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1206  }
1207  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1208  {
1209  iphcHeader.SetDstInlinePart (serializedDstAddress+14, 2);
1210  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1211  }
1212  else if ( dstAddr.IsLinkLocal () )
1213  {
1214  iphcHeader.SetDstInlinePart (serializedDstAddress+8, 8);
1215  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1216  }
1217  else
1218  {
1219  iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1220  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1221  }
1222  }
1223  }
1224  else
1225  {
1226  // Multicast address
1227 
1228  uint8_t dstContextId;
1229  if ( FindMulticastCompressionContext (dstAddr, dstContextId) )
1230  {
1231  // Stateful compression (only one possible case)
1232 
1233  // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1234  uint8_t dstInlinePart[6] = {};
1235  dstInlinePart[0] = serializedDstAddress[1];
1236  dstInlinePart[1] = serializedDstAddress[2];
1237  dstInlinePart[2] = serializedDstAddress[12];
1238  dstInlinePart[3] = serializedDstAddress[13];
1239  dstInlinePart[4] = serializedDstAddress[14];
1240  dstInlinePart[5] = serializedDstAddress[15];
1241 
1242  iphcHeader.SetDac (true);
1243  if (dstContextId != 0)
1244  {
1245  // the default context is zero, no need to explicit it if it's zero
1246  iphcHeader.SetDstContextId (dstContextId);
1247  iphcHeader.SetCid (true);
1248  }
1249  iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1250  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1251  }
1252  else
1253  {
1254  // Stateless compression
1255 
1256  uint8_t multicastAddrCheckerBuf[16];
1257  Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
1258  multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
1259 
1260  // The address takes the form ff02::00XX.
1261  if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
1262  {
1263  iphcHeader.SetDstInlinePart (serializedDstAddress+15, 1);
1264  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1265  }
1266  // The address takes the form ffXX::00XX:XXXX.
1267  // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1268  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1269  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
1270  {
1271  uint8_t dstInlinePart[4] = {};
1272  memcpy (dstInlinePart, serializedDstAddress+1, 1);
1273  memcpy (dstInlinePart+1, serializedDstAddress+13, 3);
1274  iphcHeader.SetDstInlinePart (dstInlinePart, 4);
1275  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1276  }
1277  // The address takes the form ffXX::00XX:XXXX:XXXX.
1278  // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1279  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1280  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
1281  {
1282  uint8_t dstInlinePart[6] = {};
1283  memcpy (dstInlinePart, serializedDstAddress+1, 1);
1284  memcpy (dstInlinePart+1, serializedDstAddress+11, 5);
1285  iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1286  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1287  }
1288  else
1289  {
1290  iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1291  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1292  }
1293  }
1294  }
1295  }
1296 
1297  NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
1298  NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
1299 
1300  packet->AddHeader (iphcHeader);
1301 
1302  NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
1303 
1304  return size;
1305  }
1306  return 0;
1307 }
1308 
1309 bool
1311 {
1312  bool ret = false;
1313 
1314  switch (nextHeader)
1315  {
1316  case Ipv6Header::IPV6_UDP:
1320  case Ipv6Header::IPV6_IPV6:
1321  ret = true;
1322  break;
1324  default:
1325  ret = false;
1326  }
1327  return ret;
1328 }
1329 
1330 bool
1332 {
1333  NS_LOG_FUNCTION (this << *packet << src << dst);
1334 
1335  Ipv6Header ipHeader;
1336  SixLowPanIphc encoding;
1337 
1338  uint32_t ret = packet->RemoveHeader (encoding);
1339  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1340  NS_UNUSED (ret);
1341 
1342  // Hop Limit
1343  ipHeader.SetHopLimit (encoding.GetHopLimit ());
1344 
1345  // Source address
1346  if ( encoding.GetSac () )
1347  {
1348  // Source address compression uses stateful, context-based compression.
1349  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1350  {
1351  ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
1352  }
1353  else
1354  {
1355  uint8_t contextId = encoding.GetSrcContextId ();
1356  if (m_contextTable.find (contextId) == m_contextTable.end ())
1357  {
1358  NS_LOG_LOGIC ("Unknown Source compression context (" << +contextId << "), dropping packet");
1359  return true;
1360  }
1361  if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1362  {
1363  NS_LOG_LOGIC ("Expired Source compression context (" << +contextId << "), dropping packet");
1364  return true;
1365  }
1366 
1367  uint8_t contexPrefix[16];
1368  m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1369  uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1370 
1371  uint8_t srcAddress[16] = { };
1372  if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1373  {
1374  memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1375  }
1376  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1377  {
1378  srcAddress[11] = 0xff;
1379  srcAddress[12] = 0xfe;
1380  memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1381  }
1382  else // SixLowPanIphc::HC_COMPR_0
1383  {
1385  }
1386 
1387  uint8_t bytesToCopy = contextLength / 8;
1388  uint8_t bitsToCopy = contextLength % 8;
1389 
1390  // Do not combine the prefix - we want to override the bytes.
1391  for (uint8_t i=0; i<bytesToCopy; i++)
1392  {
1393  srcAddress[i] = contexPrefix[i];
1394  }
1395  if (bitsToCopy)
1396  {
1397  uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1398  uint8_t prefixBitMask = ~addressBitMask;
1399  srcAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (srcAddress[bytesToCopy] & addressBitMask);
1400  }
1401  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1402  }
1403  }
1404  else
1405  {
1406  // Source address compression uses stateless compression.
1407 
1408  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1409  {
1410  uint8_t srcAddress[16] = { };
1411  memcpy (srcAddress, encoding.GetSrcInlinePart (), 16);
1412  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1413  }
1414  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1415  {
1416  uint8_t srcAddress[16] = { };
1417  memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1418  srcAddress[0] = 0xfe;
1419  srcAddress[1] = 0x80;
1420  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1421  }
1422  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1423  {
1424  uint8_t srcAddress[16] = { };
1425  memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1426  srcAddress[0] = 0xfe;
1427  srcAddress[1] = 0x80;
1428  srcAddress[11] = 0xff;
1429  srcAddress[12] = 0xfe;
1430  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1431  }
1432  else // SixLowPanIphc::HC_COMPR_0
1433  {
1435  }
1436  }
1437  // Destination address
1438  if ( encoding.GetDac () )
1439  {
1440  // Destination address compression uses stateful, context-based compression.
1441  if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1442  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1443  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1444  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1445  {
1446  NS_ABORT_MSG ("Reserved code found");
1447  }
1448 
1449  uint8_t contextId = encoding.GetDstContextId ();
1450  if (m_contextTable.find (contextId) == m_contextTable.end ())
1451  {
1452  NS_LOG_LOGIC ("Unknown Destination compression context (" << +contextId << "), dropping packet");
1453  return true;
1454  }
1455  if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1456  {
1457  NS_LOG_LOGIC ("Expired Destination compression context (" << +contextId << "), dropping packet");
1458  return true;
1459  }
1460 
1461  uint8_t contexPrefix[16];
1462  m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1463  uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1464 
1465  if (encoding.GetM () == false)
1466  {
1467  // unicast
1468  uint8_t dstAddress[16] = { };
1469  if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1470  {
1471  memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1472  }
1473  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1474  {
1475  dstAddress[11] = 0xff;
1476  dstAddress[12] = 0xfe;
1477  memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1478  }
1479  else // SixLowPanIphc::HC_COMPR_0
1480  {
1482  }
1483 
1484  uint8_t bytesToCopy = m_contextTable[contextId].contextPrefix.GetPrefixLength () / 8;
1485  uint8_t bitsToCopy = contextLength % 8;
1486 
1487  // Do not combine the prefix - we want to override the bytes.
1488  for (uint8_t i=0; i<bytesToCopy; i++)
1489  {
1490  dstAddress[i] = contexPrefix[i];
1491  }
1492  if (bitsToCopy)
1493  {
1494  uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1495  uint8_t prefixBitMask = ~addressBitMask;
1496  dstAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (dstAddress[bytesToCopy] & addressBitMask);
1497  }
1498  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1499  }
1500  else
1501  {
1502  // multicast
1503  // Just one possibility: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1504  uint8_t dstAddress[16] = { };
1505  dstAddress[0] = 0xff;
1506  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 2);
1507  dstAddress[3] = contextLength;
1508  memcpy (dstAddress +4, contexPrefix, 8);
1509  memcpy (dstAddress +12, encoding.GetDstInlinePart ()+2, 4);
1510  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1511  }
1512  }
1513  else
1514  {
1515  // Destination address compression uses stateless compression.
1516  if (encoding.GetM () == false)
1517  {
1518  // unicast
1519  if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1520  {
1521  uint8_t dstAddress[16] = { };
1522  memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1523  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1524  }
1525  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1526  {
1527  uint8_t dstAddress[16] = { };
1528  memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1529  dstAddress[0] = 0xfe;
1530  dstAddress[1] = 0x80;
1531  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1532  }
1533  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1534  {
1535  uint8_t dstAddress[16] = { };
1536  memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1537  dstAddress[0] = 0xfe;
1538  dstAddress[1] = 0x80;
1539  dstAddress[11] = 0xff;
1540  dstAddress[12] = 0xfe;
1541  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1542  }
1543  else // SixLowPanIphc::HC_COMPR_0
1544  {
1546  }
1547  }
1548  else
1549  {
1550  // multicast
1551  if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1552  {
1553  uint8_t dstAddress[16] = { };
1554  memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1555  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1556  }
1557  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1558  {
1559  uint8_t dstAddress[16] = { };
1560  dstAddress[0] = 0xff;
1561  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1562  memcpy (dstAddress +11, encoding.GetDstInlinePart ()+1, 5);
1563  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1564  }
1565  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1566  {
1567  uint8_t dstAddress[16] = { };
1568  dstAddress[0] = 0xff;
1569  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1570  memcpy (dstAddress +13, encoding.GetDstInlinePart ()+1, 3);
1571  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1572  }
1573  else // SixLowPanIphc::HC_COMPR_0
1574  {
1575  uint8_t dstAddress[16] = { };
1576  dstAddress[0] = 0xff;
1577  dstAddress[1] = 0x02;
1578  memcpy (dstAddress+15, encoding.GetDstInlinePart (), 1);
1579  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1580  }
1581  }
1582  }
1583 
1584  // Traffic class and Flow Label
1585  uint8_t traf = 0x00;
1586  switch (encoding.GetTf ())
1587  {
1589  traf |= encoding.GetEcn ();
1590  traf = ( traf << 6 ) | encoding.GetDscp ();
1591  ipHeader.SetTrafficClass (traf);
1592  ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1593  break;
1595  traf |= encoding.GetEcn ();
1596  traf <<= 2; // Add 2-bit pad
1597  ipHeader.SetTrafficClass (traf);
1598  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1599  break;
1601  traf |= encoding.GetEcn ();
1602  traf = ( traf << 6 ) | encoding.GetDscp ();
1603  ipHeader.SetTrafficClass (traf);
1604  ipHeader.SetFlowLabel (0);
1605  break;
1607  ipHeader.SetFlowLabel (0);
1608  ipHeader.SetTrafficClass (0);
1609  break;
1610  }
1611 
1612  if ( encoding.GetNh () )
1613  {
1614  // Next Header
1615  uint8_t dispatchRawVal = 0;
1617 
1618  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1619  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1620 
1621  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1622  {
1624  DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1625  }
1626  else
1627  {
1628  std::pair <uint8_t, bool> retval = DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1629  if ( retval.second == true )
1630  {
1631  return true;
1632  }
1633  else
1634  {
1635  ipHeader.SetNextHeader (retval.first);
1636  }
1637  }
1638  }
1639  else
1640  {
1641  ipHeader.SetNextHeader (encoding.GetNextHeader ());
1642  }
1643 
1644  ipHeader.SetPayloadLength (packet->GetSize ());
1645 
1646  packet->AddHeader (ipHeader);
1647 
1648  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1649 
1650  return false;
1651 }
1652 
1653 uint32_t
1654 SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1655 {
1656  NS_LOG_FUNCTION (this << *packet << int(headerType));
1657 
1658  SixLowPanNhcExtension nhcHeader;
1659  uint32_t size = 0;
1660  Buffer blob;
1661 
1662  if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1663  {
1664  Ipv6ExtensionHopByHopHeader hopHeader;
1665  packet->PeekHeader (hopHeader);
1666  if (hopHeader.GetLength () >= 0xff)
1667  {
1668  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1669  "that have more than 255 octets following the Length field after compression. "
1670  "Packet uncompressed.");
1671  return 0;
1672  }
1673 
1674  size += packet->RemoveHeader (hopHeader);
1676 
1677  // recursively compress other headers
1678  uint8_t nextHeader = hopHeader.GetNextHeader ();
1679  if (CanCompressLowPanNhc (nextHeader))
1680  {
1681  if (nextHeader == Ipv6Header::IPV6_UDP)
1682  {
1683  nhcHeader.SetNh (true);
1684  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1685  }
1686  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1687  {
1688  nhcHeader.SetNh (true);
1689  size += CompressLowPanIphc (packet, src, dst);
1690  }
1691  else
1692  {
1693  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1694  // the compression might fail due to Extension header size.
1695  if (sizeNhc)
1696  {
1697  nhcHeader.SetNh (true);
1698  size += sizeNhc;
1699  }
1700  else
1701  {
1702  nhcHeader.SetNh (false);
1703  nhcHeader.SetNextHeader (nextHeader);
1704  }
1705  }
1706  }
1707  else
1708  {
1709  nhcHeader.SetNh (false);
1710  nhcHeader.SetNextHeader (nextHeader);
1711  }
1712 
1713  uint32_t blobSize = hopHeader.GetSerializedSize ();
1714  blob.AddAtStart (blobSize);
1715  hopHeader.Serialize (blob.Begin ());
1716  blob.RemoveAtStart (2);
1717  blobSize = blob.GetSize ();
1718  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1719  }
1720  else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1721  {
1722  Ipv6ExtensionRoutingHeader routingHeader;
1723  packet->PeekHeader (routingHeader);
1724  if (routingHeader.GetLength () >= 0xff)
1725  {
1726  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1727  "that have more than 255 octets following the Length field after compression. "
1728  "Packet uncompressed.");
1729  return 0;
1730  }
1731 
1732  size += packet->RemoveHeader (routingHeader);
1734 
1735  // recursively compress other headers
1736  uint8_t nextHeader = routingHeader.GetNextHeader ();
1737  if (CanCompressLowPanNhc (nextHeader))
1738  {
1739  if (nextHeader == Ipv6Header::IPV6_UDP)
1740  {
1741  nhcHeader.SetNh (true);
1742  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1743  }
1744  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1745  {
1746  nhcHeader.SetNh (true);
1747  size += CompressLowPanIphc (packet, src, dst);
1748  }
1749  else
1750  {
1751  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1752  // the compression might fail due to Extension header size.
1753  if (sizeNhc)
1754  {
1755  nhcHeader.SetNh (true);
1756  size += sizeNhc;
1757  }
1758  else
1759  {
1760  nhcHeader.SetNh (false);
1761  nhcHeader.SetNextHeader (nextHeader);
1762  }
1763  }
1764  }
1765  else
1766  {
1767  nhcHeader.SetNh (false);
1768  nhcHeader.SetNextHeader (nextHeader);
1769  }
1770 
1771  uint32_t blobSize = routingHeader.GetSerializedSize ();
1772  blob.AddAtStart (blobSize);
1773  routingHeader.Serialize (blob.Begin ());
1774  blob.RemoveAtStart (2);
1775  blobSize = blob.GetSize ();
1776  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1777  }
1778  else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1779  {
1780  Ipv6ExtensionFragmentHeader fragHeader;
1781  packet->PeekHeader (fragHeader);
1782  if (fragHeader.GetLength () >= 0xff)
1783  {
1784  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1785  "that have more than 255 octets following the Length field after compression. "
1786  "Packet uncompressed.");
1787  return 0;
1788  }
1789  size += packet->RemoveHeader (fragHeader);
1791 
1792  // recursively compress other headers
1793  uint8_t nextHeader = fragHeader.GetNextHeader ();
1794  if (CanCompressLowPanNhc (nextHeader))
1795  {
1796  if (nextHeader == Ipv6Header::IPV6_UDP)
1797  {
1798  nhcHeader.SetNh (true);
1799  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1800  }
1801  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1802  {
1803  nhcHeader.SetNh (true);
1804  size += CompressLowPanIphc (packet, src, dst);
1805  }
1806  else
1807  {
1808  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1809  // the compression might fail due to Extension header size.
1810  if (sizeNhc)
1811  {
1812  nhcHeader.SetNh (true);
1813  size += sizeNhc;
1814  }
1815  else
1816  {
1817  nhcHeader.SetNh (false);
1818  nhcHeader.SetNextHeader (nextHeader);
1819  }
1820  }
1821  }
1822  else
1823  {
1824  nhcHeader.SetNh (false);
1825  nhcHeader.SetNextHeader (nextHeader);
1826  }
1827 
1828  uint32_t blobSize = fragHeader.GetSerializedSize ();
1829  blob.AddAtStart (blobSize);
1830  fragHeader.Serialize (blob.Begin ());
1831  blob.RemoveAtStart (2);
1832  blobSize = blob.GetSize ();
1833  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1834  }
1835  else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1836  {
1837  Ipv6ExtensionDestinationHeader destHeader;
1838  packet->PeekHeader (destHeader);
1839  if (destHeader.GetLength () >= 0xff)
1840  {
1841  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1842  "that have more than 255 octets following the Length field after compression. "
1843  "Packet uncompressed.");
1844  return 0;
1845  }
1846  size += packet->RemoveHeader (destHeader);
1848 
1849  // recursively compress other headers
1850  uint8_t nextHeader = destHeader.GetNextHeader ();
1851  if (CanCompressLowPanNhc (nextHeader))
1852  {
1853  if (nextHeader == Ipv6Header::IPV6_UDP)
1854  {
1855  nhcHeader.SetNh (true);
1856  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1857  }
1858  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1859  {
1860  nhcHeader.SetNh (true);
1861  size += CompressLowPanIphc (packet, src, dst);
1862  }
1863  else
1864  {
1865  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1866  // the compression might fail due to Extension header size.
1867  if (sizeNhc)
1868  {
1869  nhcHeader.SetNh (true);
1870  size += sizeNhc;
1871  }
1872  else
1873  {
1874  nhcHeader.SetNh (false);
1875  nhcHeader.SetNextHeader (nextHeader);
1876  }
1877  }
1878  }
1879  else
1880  {
1881  nhcHeader.SetNh (false);
1882  nhcHeader.SetNextHeader (nextHeader);
1883  }
1884 
1885  uint32_t blobSize = destHeader.GetSerializedSize ();
1886  blob.AddAtStart (blobSize);
1887  destHeader.Serialize (blob.Begin ());
1888  blob.RemoveAtStart (2);
1889  blobSize = blob.GetSize ();
1890  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1891  }
1892  else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1893  {
1894  // \todo: IPv6 Mobility Header is not supported in ns-3
1895  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1896  return 0;
1897  }
1898  else
1899  {
1900  NS_ABORT_MSG ("Unexpected Extension Header");
1901  }
1902 
1903  NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1904  NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1905 
1906  packet->AddHeader (nhcHeader);
1907 
1908  NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1909  return size;
1910 }
1911 
1912 std::pair <uint8_t, bool>
1913 SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1914 {
1915  NS_LOG_FUNCTION (this << *packet);
1916 
1917  SixLowPanNhcExtension encoding;
1918 
1919  uint32_t ret = packet->RemoveHeader (encoding);
1920  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1921  NS_UNUSED (ret);
1922 
1923  Ipv6ExtensionHopByHopHeader hopHeader;
1924  Ipv6ExtensionRoutingHeader routingHeader;
1925  Ipv6ExtensionFragmentHeader fragHeader;
1926  Ipv6ExtensionDestinationHeader destHeader;
1927 
1928  uint32_t blobSize;
1929  uint8_t blobData[260];
1930  blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
1931  uint8_t paddingSize = 0;
1932 
1933  uint8_t actualEncodedHeaderType = encoding.GetEid ();
1934  uint8_t actualHeaderType;
1935  Buffer blob;
1936 
1937  switch (actualEncodedHeaderType)
1938  {
1940  actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1941  if ( encoding.GetNh () )
1942  {
1943  // Next Header
1944  uint8_t dispatchRawVal = 0;
1946 
1947  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1948  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1949 
1950  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1951  {
1952  blobData [0] = Ipv6Header::IPV6_UDP;
1953  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1954  }
1955  else
1956  {
1957  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
1958  }
1959  }
1960  else
1961  {
1962  blobData [0] = encoding.GetNextHeader ();
1963  }
1964 
1965  // manually add some padding if needed
1966  if ((blobSize + 2) % 8 > 0)
1967  {
1968  paddingSize = 8 - (blobSize + 2) % 8;
1969  }
1970  if (paddingSize == 1)
1971  {
1972  blobData[blobSize + 2] = 0;
1973  }
1974  else if (paddingSize > 1)
1975  {
1976  blobData[blobSize + 2] = 1;
1977  blobData[blobSize + 2 + 1] = paddingSize - 2;
1978  for (uint8_t i = 0; i < paddingSize - 2; i++)
1979  {
1980  blobData[blobSize + 2 + 2 + i] = 0;
1981  }
1982  }
1983  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1984  blob.AddAtStart (blobSize + 2 + paddingSize);
1985  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1986  hopHeader.Deserialize (blob.Begin ());
1987 
1988  packet->AddHeader (hopHeader);
1989  break;
1990 
1992  actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1993  if ( encoding.GetNh () )
1994  {
1995  // Next Header
1996  uint8_t dispatchRawVal = 0;
1998 
1999  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2000  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2001 
2002  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2003  {
2004  blobData [0] = Ipv6Header::IPV6_UDP;
2005  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2006  }
2007  else
2008  {
2009  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2010  }
2011  }
2012  else
2013  {
2014  blobData [0] = encoding.GetNextHeader ();
2015  }
2016  blobData [1] = ((blobSize + 2) >> 3) - 1;
2017  blob.AddAtStart (blobSize + 2);
2018  blob.Begin ().Write (blobData, blobSize + 2);
2019  routingHeader.Deserialize (blob.Begin ());
2020  packet->AddHeader (routingHeader);
2021  break;
2022 
2024  actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
2025  if ( encoding.GetNh () )
2026  {
2027  // Next Header
2028  uint8_t dispatchRawVal = 0;
2030 
2031  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2032  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2033 
2034  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2035  {
2036  blobData [0] = Ipv6Header::IPV6_UDP;
2037  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2038  }
2039  else
2040  {
2041  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2042  }
2043  }
2044  else
2045  {
2046  blobData [0] = encoding.GetNextHeader ();
2047  }
2048  blobData [1] = 0;
2049 
2050  blob.AddAtStart (blobSize + 2);
2051  blob.Begin ().Write (blobData, blobSize + 2);
2052 
2053  fragHeader.Deserialize (blob.Begin ());
2054  packet->AddHeader (fragHeader);
2055  break;
2056 
2058  actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
2059  if ( encoding.GetNh () )
2060  {
2061  // Next Header
2062  uint8_t dispatchRawVal = 0;
2064 
2065  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2066  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2067 
2068  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2069  {
2070  blobData [0] = Ipv6Header::IPV6_UDP;
2071  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2072  }
2073  else
2074  {
2075  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2076  }
2077  }
2078  else
2079  {
2080  blobData [0] = encoding.GetNextHeader ();
2081  }
2082 
2083  // manually add some padding if needed
2084  if ((blobSize + 2) % 8 > 0)
2085  {
2086  paddingSize = 8 - (blobSize + 2) % 8;
2087  }
2088  if (paddingSize == 1)
2089  {
2090  blobData[blobSize + 2] = 0;
2091  }
2092  else if (paddingSize > 1)
2093  {
2094  blobData[blobSize + 2] = 1;
2095  blobData[blobSize + 2 + 1] = paddingSize - 2;
2096  for (uint8_t i = 0; i < paddingSize - 2; i++)
2097  {
2098  blobData[blobSize + 2 + 2 + i] = 0;
2099  }
2100  }
2101  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
2102  blob.AddAtStart (blobSize + 2 + paddingSize);
2103  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
2104  destHeader.Deserialize (blob.Begin ());
2105 
2106  packet->AddHeader (destHeader);
2107  break;
2109  // \todo: IPv6 Mobility Header is not supported in ns-3
2110  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
2111  break;
2113  actualHeaderType = Ipv6Header::IPV6_IPV6;
2114  if (DecompressLowPanIphc (packet, src, dst))
2115  {
2117  return std::pair<uint8_t, bool> (0, true);
2118  }
2119  break;
2120  default:
2121  NS_ABORT_MSG ("Trying to decode unknown Extension Header");
2122  break;
2123  }
2124 
2125  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2126  return std::pair<uint8_t, bool> (actualHeaderType, false);
2127 }
2128 
2129 uint32_t
2131 {
2132  NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
2133 
2134  UdpHeader udpHeader;
2135  SixLowPanUdpNhcExtension udpNhcHeader;
2136  uint32_t size = 0;
2137 
2138  NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
2139 
2140  size += packet->RemoveHeader (udpHeader);
2141 
2142  // Set the C field and checksum
2143  udpNhcHeader.SetC (false);
2144  uint16_t checksum = udpHeader.GetChecksum ();
2145  udpNhcHeader.SetChecksum (checksum);
2146 
2147  if (omitChecksum && udpHeader.IsChecksumOk ())
2148  {
2149  udpNhcHeader.SetC (true);
2150  }
2151 
2152  // Set the value of the ports
2153  udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
2154  udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
2155 
2156  //Set the P field
2157  if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
2158  {
2160  }
2161  else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
2162  {
2164  }
2165  else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
2166  {
2168  }
2169  else
2170  {
2172  }
2173 
2174  NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
2175  NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
2176 
2177  packet->AddHeader (udpNhcHeader);
2178 
2179  NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
2180 
2181  return size;
2182 }
2183 
2184 void
2186 {
2187  NS_LOG_FUNCTION (this << *packet);
2188 
2189  UdpHeader udpHeader;
2190  SixLowPanUdpNhcExtension encoding;
2191 
2192  uint32_t ret = packet->RemoveHeader (encoding);
2193  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
2194  NS_UNUSED (ret);
2195 
2196  // Set the value of the ports
2197  switch ( encoding.GetPorts () )
2198  {
2199  uint16_t temp;
2201  udpHeader.SetSourcePort (encoding.GetSrcPort ());
2202  udpHeader.SetDestinationPort (encoding.GetDstPort ());
2203  break;
2205  udpHeader.SetSourcePort (encoding.GetSrcPort ());
2206  temp = 0xf0;
2207  temp |= (temp << 8) | encoding.GetDstPort ();
2208  udpHeader.SetDestinationPort (temp);
2209  break;
2211  temp = 0xf0;
2212  temp |= (temp << 8) | encoding.GetSrcPort ();
2213  udpHeader.SetSourcePort (temp);
2214  udpHeader.SetDestinationPort (encoding.GetDstPort ());
2215  break;
2217  temp = 0xf0b;
2218  temp |= (temp << 4) | encoding.GetSrcPort ();
2219  udpHeader.SetSourcePort (temp);
2220  temp = 0xf0b;
2221  temp |= (temp << 4) | encoding.GetDstPort ();
2222  udpHeader.SetDestinationPort (temp);
2223  break;
2224  }
2225 
2226  // Get the C field and checksum
2227  if (Node::ChecksumEnabled ())
2228  {
2229  if ( encoding.GetC () )
2230  {
2231  NS_LOG_LOGIC ("Recalculating UDP Checksum");
2232  udpHeader.EnableChecksums ();
2233  udpHeader.InitializeChecksum (saddr,
2234  daddr,
2236  packet->AddHeader (udpHeader);
2237  }
2238  else
2239  {
2240  NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
2241  udpHeader.ForceChecksum (encoding.GetChecksum ());
2242  packet->AddHeader (udpHeader);
2243  NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
2244  }
2245  }
2246  else
2247  {
2248  packet->AddHeader (udpHeader);
2249  }
2250 
2251  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2252 }
2253 
2255  uint32_t origPacketSize,
2256  uint32_t origHdrSize,
2257  uint32_t extraHdrSize,
2258  std::list<Ptr<Packet> >& listFragments)
2259 {
2260  NS_LOG_FUNCTION (this << *packet);
2261 
2262  Ptr<Packet> p = packet->Copy ();
2263 
2264  uint16_t offsetData = 0;
2265  uint16_t offset = 0;
2266  uint16_t l2Mtu = m_netDevice->GetMtu ();
2267  uint32_t packetSize = packet->GetSize ();
2268  uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
2269 
2270  uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
2271  NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
2272 
2273  // first fragment
2274  SixLowPanFrag1 frag1Hdr;
2275  frag1Hdr.SetDatagramTag (tag);
2276 
2277  uint32_t size;
2278  NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
2279  "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
2280 
2281  // All the headers are substracted to get remaining units for data
2282  size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize - extraHdrSize;
2283  size -= size % 8;
2284  size += compressedHeaderSize;
2285 
2286  frag1Hdr.SetDatagramSize (origPacketSize);
2287 
2288  Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
2289  offset += size + origHdrSize - compressedHeaderSize;
2290  offsetData += size;
2291 
2292  fragment1->AddHeader (frag1Hdr);
2293  listFragments.push_back (fragment1);
2294 
2295  bool moreFrag = true;
2296  do
2297  {
2298  SixLowPanFragN fragNHdr;
2299  fragNHdr.SetDatagramTag (tag);
2300  fragNHdr.SetDatagramSize (origPacketSize);
2301  fragNHdr.SetDatagramOffset ((offset) >> 3);
2302 
2303  size = l2Mtu - fragNHdr.GetSerializedSize () - extraHdrSize;
2304  size -= size % 8;
2305 
2306  if ( (offsetData + size) > packetSize )
2307  {
2308  size = packetSize - offsetData;
2309  moreFrag = false;
2310  }
2311 
2312  if (size > 0)
2313  {
2314  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
2315  Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
2316  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
2317 
2318  offset += size;
2319  offsetData += size;
2320 
2321  fragment->AddHeader (fragNHdr);
2322  listFragments.push_back (fragment);
2323  }
2324  }
2325  while (moreFrag);
2326 
2327  return;
2328 }
2329 
2330 bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
2331 {
2332  NS_LOG_FUNCTION ( this << *packet );
2333  SixLowPanFrag1 frag1Header;
2334  SixLowPanFragN fragNHeader;
2335  FragmentKey_t key;
2336  uint16_t packetSize;
2337  key.first = std::pair<Address, Address> (src, dst);
2338 
2339  Ptr<Packet> p = packet->Copy ();
2340  uint16_t offset = 0;
2341 
2342  /* Implementation note:
2343  *
2344  * The fragment offset is relative to the *uncompressed* packet.
2345  * On the other hand, the packet can not be uncompressed correctly without all
2346  * its fragments, as the UDP checksum can not be computed otherwise.
2347  *
2348  * As a consequence we must uncompress the packet twice, and save its first
2349  * fragment for the final one.
2350  */
2351 
2352  if ( isFirst )
2353  {
2354  uint8_t dispatchRawValFrag1 = 0;
2355  SixLowPanDispatch::Dispatch_e dispatchValFrag1;
2356 
2357  p->RemoveHeader (frag1Header);
2358  packetSize = frag1Header.GetDatagramSize ();
2359  p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
2360  dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
2361  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
2362  NS_LOG_DEBUG ( "Packet: " << *p );
2363 
2364  switch ( dispatchValFrag1 )
2365  {
2367  {
2368  SixLowPanIpv6 uncompressedHdr;
2369  p->RemoveHeader (uncompressedHdr);
2370  }
2371  break;
2373  DecompressLowPanHc1 (p, src, dst);
2374  break;
2376  if (DecompressLowPanIphc (p, src, dst))
2377  {
2379  return false;
2380  }
2381  break;
2382  default:
2383  NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
2384  break;
2385  }
2386 
2387  key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
2388  }
2389  else
2390  {
2391  p->RemoveHeader (fragNHeader);
2392  packetSize = fragNHeader.GetDatagramSize ();
2393  offset = fragNHeader.GetDatagramOffset () << 3;
2394  key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
2395  }
2396 
2397  Ptr<Fragments> fragments;
2398 
2399  MapFragments_t::iterator it = m_fragments.find (key);
2400  if (it == m_fragments.end ())
2401  {
2402  // erase the oldest packet.
2404  {
2406  FragmentKey_t oldestKey = std::get<1> (*iter);
2407 
2408  std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
2409  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2410  fragIter != storedFragments.end (); fragIter++)
2411  {
2413  }
2414 
2415  m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
2416  m_fragments[oldestKey] = 0;
2417  m_fragments.erase (oldestKey);
2418 
2419  }
2420  fragments = Create<Fragments> ();
2421  fragments->SetPacketSize (packetSize);
2422  m_fragments.insert (std::make_pair (key, fragments));
2423  uint32_t ifIndex = GetIfIndex ();
2424 
2425  FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
2426  fragments->SetTimeoutIter (iter);
2427  }
2428  else
2429  {
2430  fragments = it->second;
2431  }
2432 
2433  fragments->AddFragment (p, offset);
2434 
2435  // add the very first fragment so we can correctly decode the packet once is rebuilt.
2436  // this is needed because otherwise the UDP header length and checksum can not be calculated.
2437  if ( isFirst )
2438  {
2439  fragments->AddFirstFragment (packet);
2440  }
2441 
2442  if ( fragments->IsEntire () )
2443  {
2444  packet = fragments->GetPacket ();
2445  NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
2446 
2447  SixLowPanFrag1 frag1Header;
2448  packet->RemoveHeader (frag1Header);
2449 
2450  NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
2451  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
2452  fragments = 0;
2453  m_fragments.erase (key);
2454  return true;
2455  }
2456 
2457  return false;
2458 }
2459 
2461 {
2462  NS_LOG_FUNCTION (this);
2463  m_packetSize = 0;
2464 }
2465 
2467 {
2468  NS_LOG_FUNCTION (this);
2469 }
2470 
2471 void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
2472 {
2473  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
2474 
2475  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
2476  bool duplicate = false;
2477 
2478  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
2479  {
2480  if (it->second > fragmentOffset)
2481  {
2482  break;
2483  }
2484  if (it->second == fragmentOffset)
2485  {
2486  duplicate = true;
2487  NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
2488  break;
2489  }
2490  }
2491  if (!duplicate)
2492  {
2493  m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
2494  }
2495 }
2496 
2498 {
2499  NS_LOG_FUNCTION (this << *fragment);
2500 
2501  m_firstFragment = fragment;
2502 }
2503 
2505 {
2506  NS_LOG_FUNCTION (this);
2507 
2508  bool ret = m_fragments.size () > 0;
2509  uint16_t lastEndOffset = 0;
2510 
2511  if (ret)
2512  {
2513  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
2514  {
2515  // overlapping fragments should not exist
2516  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
2517 
2518  if (lastEndOffset < it->second)
2519  {
2520  ret = false;
2521  break;
2522  }
2523  // fragments might overlap in strange ways
2524  uint16_t fragmentEnd = it->first->GetSize () + it->second;
2525  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
2526  }
2527  }
2528 
2529  if ( ret && (lastEndOffset == m_packetSize))
2530  {
2531  return true;
2532  }
2533  return false;
2534 }
2535 
2537 {
2538  NS_LOG_FUNCTION (this);
2539 
2540  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2541 
2542  Ptr<Packet> p = Create<Packet> ();
2543  uint16_t lastEndOffset = 0;
2544 
2545  p->AddAtEnd (m_firstFragment);
2546  it = m_fragments.begin ();
2547  lastEndOffset = it->first->GetSize ();
2548 
2549  for ( it++; it != m_fragments.end (); it++)
2550  {
2551  if ( lastEndOffset > it->second )
2552  {
2553  NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2554  }
2555  else
2556  {
2557  NS_LOG_LOGIC ("Adding: " << *(it->first) );
2558  p->AddAtEnd (it->first);
2559  }
2560  lastEndOffset += it->first->GetSize ();
2561  }
2562 
2563  return p;
2564 }
2565 
2567 {
2568  NS_LOG_FUNCTION (this << packetSize);
2569  m_packetSize = packetSize;
2570 }
2571 
2572 std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2573 {
2574  std::list< Ptr<Packet> > fragments;
2575  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2576  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
2577  {
2578  fragments.push_back (iter->first);
2579  }
2580  return fragments;
2581 }
2582 
2583 void
2585 {
2586  m_timeoutIter = iter;
2587  return;
2588 }
2589 
2592 {
2593  return m_timeoutIter;
2594 }
2595 
2597 {
2598  NS_LOG_FUNCTION (this);
2599 
2600  MapFragments_t::iterator it = m_fragments.find (key);
2601  std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2602  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2603  fragIter != storedFragments.end (); fragIter++)
2604  {
2606  }
2607  // clear the buffers
2608  it->second = 0;
2609 
2610  m_fragments.erase (key);
2611 }
2612 
2614 {
2615  NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
2616 
2617  uint8_t buf[6];
2618  addr.CopyTo (buf);
2619 
2620  Mac16Address shortAddr;
2621  shortAddr.CopyFrom (buf + 4);
2622 
2623  return shortAddr;
2624 }
2625 
2627 {
2628  if (m_timeoutEventList.empty ())
2629  {
2631  }
2632  m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, iif);
2633 
2635 
2636  return (iter);
2637 }
2638 
2640 {
2641  Time now = Simulator::Now ();
2642 
2643  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
2644  {
2645  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
2646  std::get<2> (*m_timeoutEventList.begin ()));
2647  m_timeoutEventList.pop_front ();
2648  }
2649 
2650  if (m_timeoutEventList.empty ())
2651  {
2652  return;
2653  }
2654 
2655  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
2657 
2658  return;
2659 }
2660 
2661 void SixLowPanNetDevice::AddContext (uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
2662 {
2663  NS_LOG_FUNCTION (this << +contextId << Ipv6Address::GetOnes ().CombinePrefix (contextPrefix) << contextPrefix << compressionAllowed << validLifetime.As (Time::S));
2664 
2665  if (contextId > 15)
2666  {
2667  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2668  return;
2669  }
2670 
2671  if (validLifetime == Time(0))
2672  {
2673  NS_LOG_LOGIC ("Context (" << +contextId << "), removed (validity time is zero)");
2674  m_contextTable.erase (contextId);
2675  return;
2676  }
2677 
2678  m_contextTable[contextId].contextPrefix = contextPrefix;
2679  m_contextTable[contextId].compressionAllowed = compressionAllowed;
2680  m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2681 
2682  return;
2683 }
2684 
2685 bool SixLowPanNetDevice::GetContext (uint8_t contextId, Ipv6Prefix& contextPrefix, bool& compressionAllowed, Time& validLifetime)
2686 {
2687  NS_LOG_FUNCTION (this << +contextId);
2688 
2689  if (contextId > 15)
2690  {
2691  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2692  return false;
2693  }
2694 
2695  if (m_contextTable.find (contextId) == m_contextTable.end ())
2696  {
2697  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2698  return false;
2699  }
2700 
2701  contextPrefix = m_contextTable[contextId].contextPrefix;
2702  compressionAllowed = m_contextTable[contextId].compressionAllowed;
2703  validLifetime = m_contextTable[contextId].validLifetime;
2704 
2705  return true;
2706 }
2707 
2708 void SixLowPanNetDevice::RenewContext (uint8_t contextId, Time validLifetime)
2709 {
2710  NS_LOG_FUNCTION (this << +contextId << validLifetime.As (Time::S));
2711 
2712  if (contextId > 15)
2713  {
2714  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2715  return;
2716  }
2717 
2718  if (m_contextTable.find (contextId) == m_contextTable.end ())
2719  {
2720  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2721  return;
2722  }
2723  m_contextTable[contextId].compressionAllowed = true;
2724  m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2725  return;
2726 }
2727 
2728 
2730 {
2731  NS_LOG_FUNCTION (this << +contextId);
2732 
2733  if (contextId > 15)
2734  {
2735  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2736  return;
2737  }
2738 
2739  if (m_contextTable.find (contextId) == m_contextTable.end ())
2740  {
2741  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2742  return;
2743  }
2744  m_contextTable[contextId].compressionAllowed = false;
2745  return;
2746 }
2747 
2748 void SixLowPanNetDevice::RemoveContext (uint8_t contextId)
2749 {
2750  NS_LOG_FUNCTION (this << +contextId);
2751 
2752  if (contextId > 15)
2753  {
2754  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2755  return;
2756  }
2757 
2758  if (m_contextTable.find (contextId) == m_contextTable.end ())
2759  {
2760  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2761  return;
2762  }
2763 
2764  m_contextTable.erase (contextId);
2765  return;
2766 }
2767 
2769 {
2770  NS_LOG_FUNCTION (this << address);
2771 
2772  for (const auto& iter: m_contextTable)
2773  {
2774  ContextEntry context = iter.second;
2775 
2776  if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2777  {
2778 
2779  if (address.HasPrefix (context.contextPrefix))
2780  {
2781  NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2782  Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2783 
2784  contextId = iter.first;
2785  return true;
2786  }
2787  }
2788  }
2789  return false;
2790 }
2791 
2793 {
2794  NS_LOG_FUNCTION (this << address);
2795 
2796  // The only allowed context-based compressed multicast address is in the form
2797  // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
2798 
2799  for (const auto& iter: m_contextTable)
2800  {
2801  ContextEntry context = iter.second;
2802 
2803  if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2804  {
2805  uint8_t contextLength = context.contextPrefix.GetPrefixLength ();
2806 
2807  if (contextLength <= 64) // only 64-bit prefixes or less are allowed.
2808  {
2809  uint8_t contextBytes[16];
2810  uint8_t addressBytes[16];
2811 
2812  context.contextPrefix.GetBytes (contextBytes);
2813  address.GetBytes (addressBytes);
2814 
2815  if (addressBytes[3] == contextLength &&
2816  addressBytes[4] == contextBytes[0] &&
2817  addressBytes[5] == contextBytes[1] &&
2818  addressBytes[6] == contextBytes[2] &&
2819  addressBytes[7] == contextBytes[3] &&
2820  addressBytes[8] == contextBytes[4] &&
2821  addressBytes[9] == contextBytes[5] &&
2822  addressBytes[10] == contextBytes[6] &&
2823  addressBytes[11] == contextBytes[7])
2824  {
2825  NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2826  Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2827 
2828  contextId = iter.first;
2829  return true;
2830  }
2831  }
2832  }
2833  }
2834  return false;
2835 }
2836 
2838 {
2839  uint8_t addressBytes[16];
2840  address.GetBytes (addressBytes);
2841  uint8_t prefixLength = prefix.GetPrefixLength ();
2842 
2843  uint8_t bytesToClean = prefixLength / 8;
2844  uint8_t bitsToClean = prefixLength % 8;
2845  for (uint8_t i=0; i<bytesToClean; i++)
2846  {
2847  addressBytes[i] = 0;
2848  }
2849  if (bitsToClean)
2850  {
2851  uint8_t cleanupMask = (1<<bitsToClean)-1;
2852  addressBytes[bytesToClean] &= cleanupMask;
2853  }
2854 
2855  Ipv6Address cleanedAddress = Ipv6Address::Deserialize (addressBytes);
2856 
2857  return cleanedAddress;
2858 }
2859 
2860 }
2861 
2862 // namespace ns3
uint8_t GetEcn(void) const
Get the ECN.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
void DecompressLowPanUdpNhc(Ptr< Packet > packet, Ipv6Address saddr, Ipv6Address daddr)
Decompress the headers according to NHC compression.
static bool IsMatchingType(const Address &address)
uint8_t GetNextHeader(void) const
Get the Next Header field value.
Address GetOriginator(void) const
Get the "Originator" address.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
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:429
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
NhcDispatch_e
Dispatch values for Next Header compression.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
bool DecompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Decompress the headers according to IPHC compression.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
uint8_t GetDstContextId(void) const
Get the DstContextId.
void SetTcflCompression(bool tcflCompression)
Set the Traffic Class and Flow Labels as compressed.
Packet header for IPv6.
Definition: ipv6-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::pair< std::pair< Address, Address >, std::pair< uint16_t, uint16_t > > FragmentKey_t
Fragment identifier type: src/dst address src/dst port.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
void HandleTimeout(void)
Handles a fragmented packet timeout.
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:75
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void SetHopLimit(uint8_t hopLimit)
Set the Hop Limit field.
Definition: second.py:1
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
uint32_t GetId(void) const
Definition: node.cc:109
void SetDstCompression(LowPanHc1Addr_e dstCompression)
Set Destination Compression type.
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
uint8_t GetHopsLeft(void) const
Get the "Hops Left" field.
const uint8_t * GetDstInlinePart(void) const
brief Get the destination address inline part
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
EventId m_timeoutEvent
Event for the next scheduled timeout.
6LoWPAN IPv6 uncompressed header - see RFC 4944.
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:438
uint8_t GetDscp(void) const
Get the DSCP.
uint16_t GetDstPort() const
Get the Destination Port.
Hold variables of type string.
Definition: string.h:41
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
uint8_t GetSequenceNumber(void) const
Get the "Sequence Number" field.
virtual void SetIfIndex(const uint32_t index)
static Mac16Address ConvertFrom(const Address &address)
void SetPacketSize(uint32_t packetSize)
Set the packet-to-be-defragmented size.
void AddFirstFragment(Ptr< Packet > fragment)
Add the first packet fragment.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
static const uint32_t packetSize
Header of IPv6 Extension Routing.
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
static Ipv6Address Deserialize(const uint8_t buf[16])
Deserialize this address.
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
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static bool ChecksumEnabled(void)
Definition: node.cc:278
LOWPAN_IPHC base Encoding - see RFC 6282.
automatically resized byte buffer
Definition: buffer.h:92
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:55
static Ipv6Address MakeAutoconfiguredAddress(Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address from a Mac address.
uint8_t GetNextHeader() const
Get the next header.
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
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
void CopyFrom(const uint8_t buffer[2])
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
void SetSrcContextId(uint8_t srcContextId)
Set the SrcContextId.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static TypeId GetTypeId(void)
Get the type ID.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
virtual bool IsBroadcast(void) const
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
HeaderCompression_e GetSam(void) const
Get the SAM (Source Address Mode) compression.
uint16_t GetLength() const
Get the length of the extension.
std::list< std::tuple< Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
const uint8_t * GetSrcInlinePart(void) const
brief Get the source address inline part
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
bool GetNh(void) const
Get the Next Header field value.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the prefix.
LOWPAN_NHC Extension Header Encoding - see RFC 6282.
void DoFragmentation(Ptr< Packet > packet, uint32_t origPacketSize, uint32_t origHdrSize, uint32_t extraHdrSize, std::list< Ptr< Packet > > &listFragments)
Performs a packet fragmentation.
uint16_t m_fragmentReassemblyListSize
How many packets can be rebuilt at the same time.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:813
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
void SetDatagramOffset(uint8_t datagramOffset)
Set the datagram offset.
void SetSam(HeaderCompression_e samField)
Set the SAM (Source Address Mode) compression.
uint8_t const * PeekData(void) const
Definition: buffer.cc:705
6LoWPAN FRAGN header - see RFC 4944.
virtual Address GetAddress(void) const
void HandleFragmentsTimeout(FragmentKey_t key, uint32_t iif)
Process the timeout for packet fragments.
uint32_t GetFlowLabel(void) const
Get the Flow Label.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint8_t m_bc0Serial
Serial number used in BC0 header.
virtual bool SetMtu(const uint16_t mtu)
bool IsEntire() const
If all fragments have been added.
void SetNetDevice(Ptr< NetDevice > device)
Setup SixLowPan to be a proxy for the specified NetDevice.
void SetTrafficClass(uint8_t trafficClass)
Set the Traffic Class value.
Header of IPv6 Extension "Hop by Hop".
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
a polymophic address class
Definition: address.h:90
void SetSequenceNumber(uint8_t seqNumber)
Set the "Sequence Number" field.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
bool FindMulticastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given multicast address matches a context for compression.
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.
Ipv6Prefix contextPrefix
context prefix to be used in compression/decompression
void SetHopsLeft(uint8_t hopsLeft)
Set the "Hops Left" field.
void ForceChecksum(uint16_t checksum)
Force the UDP checksum to a given value.
Definition: udp-header.cc:142
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetHlim(Hlim_e hlimField)
Set the HLIM (Hop Limit) compression.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual bool IsMulticast(void) const
uint32_t CompressLowPanNhc(Ptr< Packet > packet, uint8_t headerType, Address const &src, Address const &dst)
Compress the headers according to NHC compression.
bool m_useIphc
Use IPHC or HC1.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
Ptr< Node > m_node
Smart pointer to the Node.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
uint8_t GetSrcContextId(void) const
Get the SrcContextId.
void SetBlob(const uint8_t *blob, uint32_t size)
Set the option header data blob.
uint32_t CompressLowPanUdpNhc(Ptr< Packet > packet, bool omitChecksum)
Compress the headers according to NHC compression.
uint32_t CompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to IPHC compression.
HeaderCompression_e GetDam(void) const
Get the DAM (Destination Address Mode) compression.
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
#define max(a, b)
Definition: 80211b.c:43
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
Address GetFinalDst(void) const
Get the "Final Destination" address.
AttributeValue implementation for Time.
Definition: nstime.h:1353
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:49
std::map< Address, std::list< uint8_t > > m_seenPkts
Seen packets, memorized by OriginatorAdddress, SequenceNumber.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Ptr< Packet > GetPacket() const
Get the entire packet.
Ptr< RandomVariableStream > m_meshUnderJitter
Random variable for the mesh-under packet retransmission.
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
bool GetNh(void) const
Get the NH (Next Header) compression.
bool compressionAllowed
compression and decompression allowed (true), decompression only (false)
void SetOriginator(Address originator)
Set the "Originator" address.
void SetSac(bool sacField)
Set the SAC (Source Address Compression) compression.
std::list< Ptr< Packet > > GetFraments() const
Get a list of the current stored fragments.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
6LoWPAN BC0 header - see RFC 4944.
void SetNh(bool nhField)
Set the NH (Next Header) compression.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
void SetChecksum(uint16_t checksum)
Set the Checksum field values.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
uint8_t GetNextHeader(void) const
Get the Next Header field.
void SetDstPort(uint16_t port)
Set the Destination Port.
uint8_t GetTrafficClass() const
Get the Traffic Class value.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
bool IsHc2HeaderPresent() const
Check if there is a HC2 compressed header.
bool m_meshUnder
Use a mesh-under routing.
TracedCallback< DropReason, Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_dropTrace
Callback to trace drop packets.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
#define list
void SetSrcPort(uint16_t port)
Set the Source Port.
virtual Ptr< Channel > GetChannel(void) const
uint16_t GetChecksum()
Return the checksum (only known after a Deserialize)
Definition: udp-header.cc:241
Time m_fragmentExpirationTimeout
Time limit for fragment rebuilding.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
bool m_forceEtherType
Force the EtherType number.
virtual bool NeedsArp(void) const
virtual uint32_t GetIfIndex(void) const
Decompression failed due to missing or expired context.
const uint8_t * GetDstPrefix() const
Get the destination prefix.
virtual bool IsBridge(void) const
Return true if the net device is acting as a bridge.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
virtual void SetNode(Ptr< Node > node)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field.
Time validLifetime
validity period
TrafficClassFlowLabel_e GetTf(void) const
Get the TF (Traffic Class, Flow Label) compression.
address
Definition: first.py:44
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
uint32_t m_compressionThreshold
Minimum L2 payload size.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
Shim performing 6LoWPAN compression, decompression and fragmentation.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
bool IsTcflCompression() const
Check if the Traffic Class and Flow Labels are compressed.
Address Get16MacFrom48Mac(Address addr)
Get a Mac16 from its Mac48 pseudo-MAC.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
uint16_t GetSrcPort() const
Get the Source Port.
Packet header for UDP packets.
Definition: udp-header.h:39
virtual void AddLinkChangeCallback(Callback< void > callback)
void SetDstContextId(uint8_t dstContextId)
Set the DstContextId.
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
LowPanHc1Addr_e GetDstCompression() const
Get Destination Compression type.
std::map< uint8_t, ContextEntry > m_contextTable
Table of the contexts used in compression/decompression.
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
void RenewContext(uint8_t contextId, Time validLifetime)
Renew a context used in IPHC stateful compression.
bool FindUnicastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given unicast address matches a context for compression.
uint8_t GetDatagramOffset(void) const
Get the datagram offset.
This class can contain 16 bit addresses.
Definition: mac16-address.h:41
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:1354
uint8_t GetPrefixLength() const
Get prefix length.
bool GetSac(void) const
Get the SAC (Source Address Compression) compression.
uint32_t GetFlowLabel(void) const
Get the "Flow label" field.
Definition: ipv6-header.cc:60
uint16_t GetChecksum(void) const
Get the Checksum field value.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
uint16_t GetDatagramSize(void) const
Get the datagram size.
6LoWPAN HC1 header - see RFC 4944.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
virtual bool SupportsSendFrom() const
void SetDac(bool dacField)
Set the DAC (Destination Address Compression) compression.
void AddContext(uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
Add, remove, or update a context used in IPHC stateful compression.
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:229
Structure holding the informations for a context (used in compression and decompression) ...
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
#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
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
void SetSrcInterface(const uint8_t *srcInterface)
Set the source interface.
uint16_t m_etherType
EtherType number (used only if m_forceEtherType is true).
void InvalidateContext(uint8_t contextId)
Invalidate a context used in IPHC stateful compression.
Ipv6Address CleanPrefix(Ipv6Address address, Ipv6Prefix prefix)
Clean an address from its prefix.
void SetDstPrefix(const uint8_t *dstPrefix)
Set the destination prefix.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
SixLowPanNetDevice()
Constructor for the SixLowPanNetDevice.
virtual Ptr< Node > GetNode(void) const
uint32_t GetFlowLabel() const
Get the Flow Label 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).
Definition: ipv6-header.cc:85
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label (20bits).
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
void SetFinalDst(Address finalDst)
Set the "Final Destination" address.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
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.
bool GetContext(uint8_t contextId, Ipv6Prefix &contextPrefix, bool &compressionAllowed, Time &validLifetime)
Get a context used in IPHC stateful compression.
Network layer to device interface.
Definition: net-device.h:95
uint8_t GetHopLimit(void) const
Get the Hop Limit field.
6LoWPAN Mesh header - see RFC 4944.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
Header of IPv6 Extension Destination.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void SetFlowLabel(uint32_t flow)
Set the "Flow label" field.
Definition: ipv6-header.cc:55
LowPanHc1Addr_e GetSrcCompression() const
Get Source Compression type.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
static Ipv6Address GetOnes()
Get the "all-1" IPv6 address (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
uint32_t GetSize(void) const
Definition: buffer.h:1063
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
void SetEid(Eid_e extensionHeaderType)
Set the Extension Header Type.
Header of IPv6 Extension Fragment.
std::map< FragmentKey_t, Ptr< Fragments > >::iterator MapFragmentsI_t
Container Iterator for fragment key -> fragments.
Eid_e GetEid(void) const
Get the Extension Header Type.
bool CanCompressLowPanNhc(uint8_t headerType)
Checks if the next header can be compressed using NHC.
Describes an IPv6 prefix.
Definition: ipv6-address.h:466
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:953
bool m_omitUdpChecksum
Omit UDP checksum in NC1 encoding.
Ports_e GetPorts(void) const
Get the compressed Src and Dst Ports.
bool DoSend(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber, bool doSendFrom)
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
Definition: ipv6-header.cc:45
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
void SetNh(bool nhField)
Set the NH field values.
void SetTf(TrafficClassFlowLabel_e tfField)
Set the TF (Traffic Class, Flow Label) compression.
uint16_t m_meshCacheLength
length of the cache for each source.
uint16_t GetDatagramSize(void) const
Get the datagram size.
void RemoveContext(uint8_t contextId)
Remove a context used in IPHC stateful compression.
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
Dispatch_e
Dispatch values, as defined in RFC 4944 and RFC 6282
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
second
Definition: nstime.h:115
Ptr< NetDevice > m_netDevice
Smart pointer to the underlying NetDevice.
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset)
Add a fragment to the pool.
void SetDstInlinePart(uint8_t dstInlinePart[16], uint8_t size)
brief Set the destination address inline part
bool ProcessFragment(Ptr< Packet > &packet, Address const &src, Address const &dst, bool isFirst)
Process a packet fragment.
void SetM(bool mField)
Set the M (Multicast) compression.
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:296
void SetSrcPrefix(const uint8_t *srcPrefix)
Set the source prefix.
bool GetM(void) const
Get the M (Multicast) compression.
Ptr< NetDevice > GetNetDevice() const
Returns a smart pointer to the underlying NetDevice.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
virtual bool IsLinkUp(void) const
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual uint16_t GetMtu(void) const
Returns the link-layer MTU for this interface.
static bool IsMatchingType(const Address &address)
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
uint32_t CopyBlob(uint8_t *blob, uint32_t size) const
Get the option header data blob.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:86
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
void SetEcn(uint8_t ecn)
Set the ECN (2bits).
bool GetC(void) const
Get the C (Checksum).
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
6LoWPAN FRAG1 header - see RFC 4944.
uint32_t CompressLowPanHc1(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to HC1 compression.
virtual Address GetBroadcast(void) const
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
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
a unique identifier for an interface.
Definition: type-id.h:58
bool GetDac(void) const
Get the DAC (Destination Address Compression) compression.
static const uint8_t PROT_NUMBER
protocol number (0x11)
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
uint8_t m_meshUnderHopsLeft
Start value for mesh-under hops left.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
uint32_t m_ifIndex
Interface index.
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
UDP LOWPAN_NHC Extension Header Encoding - see RFC 6282.
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:1642
void SetC(bool cField)
Set the C (Checksum).
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
virtual void SetAddress(Address address)
Set the address of this interface.
const uint8_t * GetSrcPrefix() const
Get the source prefix.
void DecompressLowPanHc1(Ptr< Packet > packet, Address const &src, Address const &dst)
Decompress the headers according to HC1 compression.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header value.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void SetDam(HeaderCompression_e damField)
Set the DAM (Destination Address Mode) compression.
MapFragments_t m_fragments
Fragments hold to be rebuilt.
Ptr< UniformRandomVariable > m_rng
Rng for the fragments tag.
void SetSrcInlinePart(uint8_t srcInlinePart[16], uint8_t size)
brief Set the source address inline part
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label value.
void Serialize(uint8_t buf[16]) const
Serialize this address to a 16-byte buffer.
virtual void DoDispose(void)
Destructor implementation.
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition: address.cc:82
bool IsChecksumOk(void) const
Is the UDP checksum correct ?
Definition: udp-header.cc:136
uint8_t GetNextHeader() const
Get the Next Header value.