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  if (useMesh)
577  {
578  Address source = src;
579  if (!doSendFrom)
580  {
581  source = m_netDevice->GetAddress ();
582  }
583 
584  if (Mac48Address::IsMatchingType (source))
585  {
586  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
587  source = Get16MacFrom48Mac (source);
588  }
589  if (Mac48Address::IsMatchingType (destination))
590  {
591  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
592  destination = Get16MacFrom48Mac (destination);
593  }
594 
595  meshHdr.SetOriginator (source);
596  meshHdr.SetFinalDst (destination);
598  destination = m_netDevice->GetBroadcast ();
599  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
600  }
601 
603  {
604  NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
605  packet = origPacket;
606  SixLowPanIpv6 ipv6UncompressedHdr;
607  packet->AddHeader (ipv6UncompressedHdr);
608  pktSize = packet->GetSize ();
609  if (useMesh)
610  {
611  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
612  }
613  }
614 
615 
616  if (pktSize > m_netDevice->GetMtu ())
617  {
618  NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
619  // fragment
620  std::list<Ptr<Packet> > fragmentList;
621  DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
622  std::list<Ptr<Packet> >::iterator it;
623  bool success = true;
624  for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
625  {
626  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
628 
629  if (useMesh)
630  {
631  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
632  (*it)->AddHeader (bc0Hdr);
633  (*it)->AddHeader (meshHdr);
634  }
635  if (doSendFrom)
636  {
637  success &= m_netDevice->SendFrom (*it, src, destination, protocolNumber);
638  }
639  else
640  {
641  success &= m_netDevice->Send (*it, destination, protocolNumber);
642  }
643  }
644  ret = success;
645  }
646  else
647  {
649 
650  if (useMesh)
651  {
652  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
653  packet->AddHeader (bc0Hdr);
654  packet->AddHeader (meshHdr);
655  }
656 
657  if (doSendFrom)
658  {
659  NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
660  ret = m_netDevice->SendFrom (packet, src, destination, protocolNumber);
661  }
662  else
663  {
664  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
665  ret = m_netDevice->Send (packet, destination, protocolNumber);
666  }
667  }
668 
669  return ret;
670 }
671 
673 {
674  NS_LOG_FUNCTION (this);
675  return m_node;
676 }
677 
679 {
680  NS_LOG_FUNCTION (this << node);
681  m_node = node;
682 }
683 
685 {
686  NS_LOG_FUNCTION (this);
687  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
688 
689  return m_netDevice->NeedsArp ();
690 }
691 
693 {
694  NS_LOG_FUNCTION (this << &cb);
695  m_rxCallback = cb;
696 }
697 
699 {
700  NS_LOG_FUNCTION (this << &cb);
701  m_promiscRxCallback = cb;
702 }
703 
705 {
706  NS_LOG_FUNCTION (this);
707  return true;
708 }
709 
710 uint32_t
712 {
713  NS_LOG_FUNCTION (this << *packet << src << dst);
714 
715  Ipv6Header ipHeader;
716  SixLowPanHc1 hc1Header;
717  uint32_t size = 0;
718 
719  NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () );
720 
721  if ( packet->PeekHeader (ipHeader) != 0 )
722  {
723  packet->RemoveHeader (ipHeader);
724  size += ipHeader.GetSerializedSize ();
725 
726  hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
727 
728  uint8_t bufOne[16];
729  uint8_t bufTwo[16];
730  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
731  srcAddr.GetBytes (bufOne);
733 
734  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
735 
736  mySrcAddr.GetBytes (bufTwo);
737  bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
738 
739  if (srcAddr.IsLinkLocal () && isSrcSrc )
740  {
742  }
743  else if (srcAddr.IsLinkLocal () )
744  {
746  hc1Header.SetSrcInterface (bufOne + 8);
747  }
748  else if ( isSrcSrc )
749  {
751  hc1Header.SetSrcPrefix (bufOne);
752  }
753  else
754  {
756  hc1Header.SetSrcInterface (bufOne + 8);
757  hc1Header.SetSrcPrefix (bufOne);
758  }
759 
760  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
761  dstAddr.GetBytes (bufOne);
763 
764  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
765 
766  myDstAddr.GetBytes (bufTwo);
767  bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
768 
769  if (dstAddr.IsLinkLocal () && isDstDst )
770  {
772  }
773  else if (dstAddr.IsLinkLocal () )
774  {
776  hc1Header.SetDstInterface (bufOne + 8);
777  }
778  else if ( isDstDst )
779  {
781  hc1Header.SetDstPrefix (bufOne);
782  }
783  else
784  {
786  hc1Header.SetDstInterface (bufOne + 8);
787  hc1Header.SetDstPrefix (bufOne);
788  }
789 
790  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
791  {
792  hc1Header.SetTcflCompression (true);
793  }
794  else
795  {
796  hc1Header.SetTcflCompression (false);
797  hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
798  hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
799  }
800 
801  uint8_t nextHeader = ipHeader.GetNextHeader ();
802  hc1Header.SetNextHeader (nextHeader);
803 
804  // \todo implement HC2 compression
805  hc1Header.SetHc2HeaderPresent (false);
806 
807  NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
808  NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
809 
810  packet->AddHeader (hc1Header);
811 
812  return size;
813  }
814 
815  return 0;
816 }
817 
818 void
820 {
821  NS_LOG_FUNCTION (this << *packet << src << dst);
822 
823  Ipv6Header ipHeader;
824  SixLowPanHc1 encoding;
825 
826  uint32_t ret = packet->RemoveHeader (encoding);
827  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
828  NS_UNUSED (ret);
829 
830  ipHeader.SetHopLimit (encoding.GetHopLimit ());
831 
832  switch (encoding.GetSrcCompression ())
833  {
834  const uint8_t* interface;
835  const uint8_t* prefix;
836  uint8_t address[16];
837 
839  prefix = encoding.GetSrcPrefix ();
840  interface = encoding.GetSrcInterface ();
841  for (int j = 0; j < 8; j++)
842  {
843  address[j + 8] = interface[j];
844  address[j] = prefix[j];
845  }
846  ipHeader.SetSourceAddress ( Ipv6Address (address) );
847  break;
849  prefix = encoding.GetSrcPrefix ();
850  for (int j = 0; j < 8; j++)
851  {
852  address[j + 8] = 0;
853  address[j] = prefix[j];
854  }
856  break;
858  interface = encoding.GetSrcInterface ();
859  address[0] = 0xfe;
860  address[1] = 0x80;
861  for (int j = 0; j < 8; j++)
862  {
863  address[j + 8] = interface[j];
864  }
865  ipHeader.SetSourceAddress ( Ipv6Address (address) );
866  break;
869  break;
870  }
871 
872  switch (encoding.GetDstCompression ())
873  {
874  const uint8_t* interface;
875  const uint8_t* prefix;
876  uint8_t address[16];
877 
879  prefix = encoding.GetDstPrefix ();
880  interface = encoding.GetDstInterface ();
881  for (int j = 0; j < 8; j++)
882  {
883  address[j + 8] = interface[j];
884  address[j] = prefix[j];
885  }
887  break;
889  prefix = encoding.GetDstPrefix ();
890  for (int j = 0; j < 8; j++)
891  {
892  address[j + 8] = 0;
893  address[j] = prefix[j];
894  }
896  break;
898  interface = encoding.GetDstInterface ();
899  address[0] = 0xfe;
900  address[1] = 0x80;
901  for (int j = 0; j < 8; j++)
902  {
903  address[j + 8] = interface[j];
904  }
906  break;
909  break;
910  }
911 
912  if ( !encoding.IsTcflCompression () )
913  {
914  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
915  ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
916  }
917  else
918  {
919  ipHeader.SetFlowLabel (0);
920  ipHeader.SetTrafficClass (0);
921  }
922 
923  ipHeader.SetNextHeader (encoding.GetNextHeader ());
924 
925  ipHeader.SetPayloadLength (packet->GetSize ());
926 
927  NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
928  "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
929 
930  packet->AddHeader (ipHeader);
931 
932  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
933 }
934 
935 uint32_t
937 {
938  NS_LOG_FUNCTION (this << *packet << src << dst);
939 
940  Ipv6Header ipHeader;
941  SixLowPanIphc iphcHeader;
942  uint32_t size = 0;
943 
944  NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () << " src: " << src << " dst: " << dst);
945 
946  if ( packet->PeekHeader (ipHeader) != 0 )
947  {
948  packet->RemoveHeader (ipHeader);
949  size += ipHeader.GetSerializedSize ();
950 
951  // Set the TF field
952  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
953  {
954  iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
955  }
956  else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
957  {
958  iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
959  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
960  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
961  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
962  }
963  else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
964  {
965  iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
966  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
967  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
968  }
969  else
970  {
972  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
973  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
974  }
975 
976  // Set the NH field and NextHeader
977 
978  uint8_t nextHeader = ipHeader.GetNextHeader ();
979  if (CanCompressLowPanNhc (nextHeader))
980  {
981  if (nextHeader == Ipv6Header::IPV6_UDP)
982  {
983  iphcHeader.SetNh (true);
984  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
985  }
986  else if (nextHeader == Ipv6Header::IPV6_IPV6)
987  {
988  iphcHeader.SetNh (true);
989  size += CompressLowPanIphc (packet, src, dst);
990  }
991  else
992  {
993  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
994  // the compression might fail due to Extension header size.
995  if (sizeNhc)
996  {
997  iphcHeader.SetNh (true);
998  size += sizeNhc;
999  }
1000  else
1001  {
1002  iphcHeader.SetNh (false);
1003  iphcHeader.SetNextHeader (nextHeader);
1004  }
1005  }
1006  }
1007  else
1008  {
1009  iphcHeader.SetNh (false);
1010  iphcHeader.SetNextHeader (nextHeader);
1011  }
1012 
1013  // Set the HLIM field
1014  if (ipHeader.GetHopLimit () == 1)
1015  {
1016  iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_1);
1017  }
1018  else if (ipHeader.GetHopLimit () == 0x40)
1019  {
1021  }
1022  else if (ipHeader.GetHopLimit () == 0xFF)
1023  {
1025  }
1026  else
1027  {
1028  iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
1029  // Set the HopLimit
1030  iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
1031  }
1032 
1033  // Set the CID + SAC + DAC fields to their default value
1034  iphcHeader.SetCid (false);
1035  iphcHeader.SetSac (false);
1036  iphcHeader.SetDac (false);
1037 
1038 
1039  Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
1040  uint8_t unicastAddrCheckerBuf[16];
1041  checker.GetBytes (unicastAddrCheckerBuf);
1042  uint8_t addressBuf[16];
1043 
1044  // This is just to limit the scope of some variables.
1045  if (true)
1046  {
1047  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
1048  uint8_t srcContextId;
1049 
1050  // The "::" address is compressed as a fake stateful compression.
1051  if (srcAddr == Ipv6Address::GetAny ())
1052  {
1053  // No context information is needed.
1054  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1055  iphcHeader.SetSac (true);
1056  }
1057  // Check if the address can be compressed with stateful compression
1058  else if ( FindUnicastCompressionContext (srcAddr, srcContextId) )
1059  {
1060  // We can do stateful compression.
1061  NS_LOG_LOGIC ("Checking stateful source compression: " << srcAddr );
1062 
1063  iphcHeader.SetSac (true);
1064  if (srcContextId != 0)
1065  {
1066  // the default context is zero, no need to explicit it if it's zero
1067  iphcHeader.SetSrcContextId (srcContextId);
1068  iphcHeader.SetCid (true);
1069  }
1070 
1071  // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1072 
1073  if (Ipv6Address::MakeAutoconfiguredAddress (src, m_contextTable[srcContextId].contextPrefix) == srcAddr)
1074  {
1075  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1076  }
1077  else
1078  {
1079  Ipv6Address cleanedAddr = CleanPrefix (srcAddr, m_contextTable[srcContextId].contextPrefix);
1080  uint8_t serializedCleanedAddress[16];
1081  cleanedAddr.Serialize (serializedCleanedAddress);
1082 
1083  if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1084  serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1085  serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1086  {
1087  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1088  iphcHeader.SetSrcInlinePart (serializedCleanedAddress+14, 2);
1089  }
1090  else
1091  {
1092  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1093  iphcHeader.SetSrcInlinePart (serializedCleanedAddress+8, 8);
1094 
1095  }
1096  }
1097  }
1098  else
1099  {
1100  // We must do stateless compression.
1101  NS_LOG_LOGIC ("Checking stateless source compression: " << srcAddr );
1102 
1103  srcAddr.GetBytes (addressBuf);
1104 
1105  uint8_t serializedSrcAddress[16];
1106  srcAddr.Serialize (serializedSrcAddress);
1107 
1108  if ( srcAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src) )
1109  {
1110  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1111  }
1112  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1113  {
1114  iphcHeader.SetSrcInlinePart (serializedSrcAddress+14, 2);
1115  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1116  }
1117  else if ( srcAddr.IsLinkLocal () )
1118  {
1119  iphcHeader.SetSrcInlinePart (serializedSrcAddress+8, 8);
1120  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1121  }
1122  else
1123  {
1124  iphcHeader.SetSrcInlinePart (serializedSrcAddress, 16);
1125  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1126  }
1127  }
1128  }
1129 
1130  // Set the M field
1131  if (ipHeader.GetDestinationAddress ().IsMulticast ())
1132  {
1133  iphcHeader.SetM (true);
1134  }
1135  else
1136  {
1137  iphcHeader.SetM (false);
1138  }
1139 
1140  // This is just to limit the scope of some variables.
1141  if (true)
1142  {
1143  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
1144  dstAddr.GetBytes (addressBuf);
1145 
1146  NS_LOG_LOGIC ("Checking destination compression: " << dstAddr );
1147 
1148  uint8_t serializedDstAddress[16];
1149  dstAddr.Serialize (serializedDstAddress);
1150 
1151  if ( !iphcHeader.GetM () )
1152  {
1153  // Unicast address
1154 
1155  uint8_t dstContextId;
1156  if ( FindUnicastCompressionContext (dstAddr, dstContextId) )
1157  {
1158  // We can do stateful compression.
1159  NS_LOG_LOGIC ("Checking stateful destination compression: " << dstAddr );
1160 
1161  iphcHeader.SetDac (true);
1162  if (dstContextId != 0)
1163  {
1164  // the default context is zero, no need to explicit it if it's zero
1165  iphcHeader.SetDstContextId (dstContextId);
1166  iphcHeader.SetCid (true);
1167  }
1168 
1169  // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1170  if (Ipv6Address::MakeAutoconfiguredAddress (dst, m_contextTable[dstContextId].contextPrefix) == dstAddr)
1171  {
1172  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1173  }
1174  else
1175  {
1176  Ipv6Address cleanedAddr = CleanPrefix (dstAddr, m_contextTable[dstContextId].contextPrefix);
1177 
1178  uint8_t serializedCleanedAddress[16];
1179  cleanedAddr.Serialize (serializedCleanedAddress);
1180 
1181  if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1182  serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1183  serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1184  {
1185  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1186  iphcHeader.SetDstInlinePart (serializedCleanedAddress+14, 2);
1187  }
1188  else
1189  {
1190  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1191  iphcHeader.SetDstInlinePart (serializedCleanedAddress+8, 8);
1192  }
1193  }
1194  }
1195  else
1196  {
1197  NS_LOG_LOGIC ("Checking stateless destination compression: " << dstAddr );
1198 
1199  if ( dstAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst) )
1200  {
1201  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1202  }
1203  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1204  {
1205  iphcHeader.SetDstInlinePart (serializedDstAddress+14, 2);
1206  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1207  }
1208  else if ( dstAddr.IsLinkLocal () )
1209  {
1210  iphcHeader.SetDstInlinePart (serializedDstAddress+8, 8);
1211  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1212  }
1213  else
1214  {
1215  iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1216  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1217  }
1218  }
1219  }
1220  else
1221  {
1222  // Multicast address
1223 
1224  uint8_t dstContextId;
1225  if ( FindMulticastCompressionContext (dstAddr, dstContextId) )
1226  {
1227  // Stateful compression (only one possible case)
1228 
1229  // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1230  uint8_t dstInlinePart[6] = {};
1231  dstInlinePart[0] = serializedDstAddress[1];
1232  dstInlinePart[1] = serializedDstAddress[2];
1233  dstInlinePart[2] = serializedDstAddress[12];
1234  dstInlinePart[3] = serializedDstAddress[13];
1235  dstInlinePart[4] = serializedDstAddress[14];
1236  dstInlinePart[5] = serializedDstAddress[15];
1237 
1238  iphcHeader.SetDac (true);
1239  if (dstContextId != 0)
1240  {
1241  // the default context is zero, no need to explicit it if it's zero
1242  iphcHeader.SetDstContextId (dstContextId);
1243  iphcHeader.SetCid (true);
1244  }
1245  iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1246  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1247  }
1248  else
1249  {
1250  // Stateless compression
1251 
1252  uint8_t multicastAddrCheckerBuf[16];
1253  Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
1254  multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
1255 
1256  // The address takes the form ff02::00XX.
1257  if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
1258  {
1259  iphcHeader.SetDstInlinePart (serializedDstAddress+15, 1);
1260  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1261  }
1262  // The address takes the form ffXX::00XX:XXXX.
1263  // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1264  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1265  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
1266  {
1267  uint8_t dstInlinePart[4] = {};
1268  memcpy (dstInlinePart, serializedDstAddress+1, 1);
1269  memcpy (dstInlinePart+1, serializedDstAddress+13, 3);
1270  iphcHeader.SetDstInlinePart (dstInlinePart, 4);
1271  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1272  }
1273  // The address takes the form ffXX::00XX:XXXX:XXXX.
1274  // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1275  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1276  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
1277  {
1278  uint8_t dstInlinePart[6] = {};
1279  memcpy (dstInlinePart, serializedDstAddress+1, 1);
1280  memcpy (dstInlinePart+1, serializedDstAddress+11, 5);
1281  iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1282  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1283  }
1284  else
1285  {
1286  iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1287  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1288  }
1289  }
1290  }
1291  }
1292 
1293  NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
1294  NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
1295 
1296  packet->AddHeader (iphcHeader);
1297 
1298  NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
1299 
1300  return size;
1301  }
1302  return 0;
1303 }
1304 
1305 bool
1307 {
1308  bool ret = false;
1309 
1310  switch (nextHeader)
1311  {
1312  case Ipv6Header::IPV6_UDP:
1316  case Ipv6Header::IPV6_IPV6:
1317  ret = true;
1318  break;
1320  default:
1321  ret = false;
1322  }
1323  return ret;
1324 }
1325 
1326 bool
1328 {
1329  NS_LOG_FUNCTION (this << *packet << src << dst);
1330 
1331  Ipv6Header ipHeader;
1332  SixLowPanIphc encoding;
1333 
1334  uint32_t ret = packet->RemoveHeader (encoding);
1335  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1336  NS_UNUSED (ret);
1337 
1338  // Hop Limit
1339  ipHeader.SetHopLimit (encoding.GetHopLimit ());
1340 
1341  // Source address
1342  if ( encoding.GetSac () )
1343  {
1344  // Source address compression uses stateful, context-based compression.
1345  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1346  {
1347  ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
1348  }
1349  else
1350  {
1351  uint8_t contextId = encoding.GetSrcContextId ();
1352  if (m_contextTable.find (contextId) == m_contextTable.end ())
1353  {
1354  NS_LOG_LOGIC ("Unknown Source compression context (" << +contextId << "), dropping packet");
1355  return true;
1356  }
1357  if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1358  {
1359  NS_LOG_LOGIC ("Expired Source compression context (" << +contextId << "), dropping packet");
1360  return true;
1361  }
1362 
1363  uint8_t contexPrefix[16];
1364  m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1365  uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1366 
1367  uint8_t srcAddress[16] = { };
1368  if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1369  {
1370  memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1371  }
1372  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1373  {
1374  srcAddress[11] = 0xff;
1375  srcAddress[12] = 0xfe;
1376  memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1377  }
1378  else // SixLowPanIphc::HC_COMPR_0
1379  {
1381  }
1382 
1383  uint8_t bytesToCopy = contextLength / 8;
1384  uint8_t bitsToCopy = contextLength % 8;
1385 
1386  // Do not combine the prefix - we want to override the bytes.
1387  for (uint8_t i=0; i<bytesToCopy; i++)
1388  {
1389  srcAddress[i] = contexPrefix[i];
1390  }
1391  if (bitsToCopy)
1392  {
1393  uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1394  uint8_t prefixBitMask = ~addressBitMask;
1395  srcAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (srcAddress[bytesToCopy] & addressBitMask);
1396  }
1397  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1398  }
1399  }
1400  else
1401  {
1402  // Source address compression uses stateless compression.
1403 
1404  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1405  {
1406  uint8_t srcAddress[16] = { };
1407  memcpy (srcAddress, encoding.GetSrcInlinePart (), 16);
1408  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1409  }
1410  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1411  {
1412  uint8_t srcAddress[16] = { };
1413  memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1414  srcAddress[0] = 0xfe;
1415  srcAddress[1] = 0x80;
1416  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1417  }
1418  else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1419  {
1420  uint8_t srcAddress[16] = { };
1421  memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1422  srcAddress[0] = 0xfe;
1423  srcAddress[1] = 0x80;
1424  srcAddress[11] = 0xff;
1425  srcAddress[12] = 0xfe;
1426  ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
1427  }
1428  else // SixLowPanIphc::HC_COMPR_0
1429  {
1431  }
1432  }
1433  // Destination address
1434  if ( encoding.GetDac () )
1435  {
1436  // Destination address compression uses stateful, context-based compression.
1437  if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1438  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1439  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1440  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1441  {
1442  NS_ABORT_MSG ("Reserved code found");
1443  }
1444 
1445  uint8_t contextId = encoding.GetDstContextId ();
1446  if (m_contextTable.find (contextId) == m_contextTable.end ())
1447  {
1448  NS_LOG_LOGIC ("Unknown Destination compression context (" << +contextId << "), dropping packet");
1449  return true;
1450  }
1451  if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1452  {
1453  NS_LOG_LOGIC ("Expired Destination compression context (" << +contextId << "), dropping packet");
1454  return true;
1455  }
1456 
1457  uint8_t contexPrefix[16];
1458  m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1459  uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1460 
1461  if (encoding.GetM () == false)
1462  {
1463  // unicast
1464  uint8_t dstAddress[16] = { };
1465  if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1466  {
1467  memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1468  }
1469  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1470  {
1471  dstAddress[11] = 0xff;
1472  dstAddress[12] = 0xfe;
1473  memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1474  }
1475  else // SixLowPanIphc::HC_COMPR_0
1476  {
1478  }
1479 
1480  uint8_t bytesToCopy = m_contextTable[contextId].contextPrefix.GetPrefixLength () / 8;
1481  uint8_t bitsToCopy = contextLength % 8;
1482 
1483  // Do not combine the prefix - we want to override the bytes.
1484  for (uint8_t i=0; i<bytesToCopy; i++)
1485  {
1486  dstAddress[i] = contexPrefix[i];
1487  }
1488  if (bitsToCopy)
1489  {
1490  uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1491  uint8_t prefixBitMask = ~addressBitMask;
1492  dstAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (dstAddress[bytesToCopy] & addressBitMask);
1493  }
1494  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1495  }
1496  else
1497  {
1498  // multicast
1499  // Just one possibility: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1500  uint8_t dstAddress[16] = { };
1501  dstAddress[0] = 0xff;
1502  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 2);
1503  dstAddress[3] = contextLength;
1504  memcpy (dstAddress +4, contexPrefix, 8);
1505  memcpy (dstAddress +12, encoding.GetDstInlinePart ()+2, 4);
1506  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1507  }
1508  }
1509  else
1510  {
1511  // Destination address compression uses stateless compression.
1512  if (encoding.GetM () == false)
1513  {
1514  // unicast
1515  if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1516  {
1517  uint8_t dstAddress[16] = { };
1518  memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1519  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1520  }
1521  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1522  {
1523  uint8_t dstAddress[16] = { };
1524  memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1525  dstAddress[0] = 0xfe;
1526  dstAddress[1] = 0x80;
1527  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1528  }
1529  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1530  {
1531  uint8_t dstAddress[16] = { };
1532  memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1533  dstAddress[0] = 0xfe;
1534  dstAddress[1] = 0x80;
1535  dstAddress[11] = 0xff;
1536  dstAddress[12] = 0xfe;
1537  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1538  }
1539  else // SixLowPanIphc::HC_COMPR_0
1540  {
1542  }
1543  }
1544  else
1545  {
1546  // multicast
1547  if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1548  {
1549  uint8_t dstAddress[16] = { };
1550  memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1551  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1552  }
1553  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1554  {
1555  uint8_t dstAddress[16] = { };
1556  dstAddress[0] = 0xff;
1557  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1558  memcpy (dstAddress +11, encoding.GetDstInlinePart ()+1, 5);
1559  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1560  }
1561  else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1562  {
1563  uint8_t dstAddress[16] = { };
1564  dstAddress[0] = 0xff;
1565  memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1566  memcpy (dstAddress +13, encoding.GetDstInlinePart ()+1, 3);
1567  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1568  }
1569  else // SixLowPanIphc::HC_COMPR_0
1570  {
1571  uint8_t dstAddress[16] = { };
1572  dstAddress[0] = 0xff;
1573  dstAddress[1] = 0x02;
1574  memcpy (dstAddress+15, encoding.GetDstInlinePart (), 1);
1575  ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
1576  }
1577  }
1578  }
1579 
1580  // Traffic class and Flow Label
1581  uint8_t traf = 0x00;
1582  switch (encoding.GetTf ())
1583  {
1585  traf |= encoding.GetEcn ();
1586  traf = ( traf << 6 ) | encoding.GetDscp ();
1587  ipHeader.SetTrafficClass (traf);
1588  ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1589  break;
1591  traf |= encoding.GetEcn ();
1592  traf <<= 2; // Add 2-bit pad
1593  ipHeader.SetTrafficClass (traf);
1594  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1595  break;
1597  traf |= encoding.GetEcn ();
1598  traf = ( traf << 6 ) | encoding.GetDscp ();
1599  ipHeader.SetTrafficClass (traf);
1600  ipHeader.SetFlowLabel (0);
1601  break;
1603  ipHeader.SetFlowLabel (0);
1604  ipHeader.SetTrafficClass (0);
1605  break;
1606  }
1607 
1608  if ( encoding.GetNh () )
1609  {
1610  // Next Header
1611  uint8_t dispatchRawVal = 0;
1613 
1614  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1615  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1616 
1617  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1618  {
1620  DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1621  }
1622  else
1623  {
1624  std::pair <uint8_t, bool> retval = DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1625  if ( retval.second == true )
1626  {
1627  return true;
1628  }
1629  else
1630  {
1631  ipHeader.SetNextHeader (retval.first);
1632  }
1633  }
1634  }
1635  else
1636  {
1637  ipHeader.SetNextHeader (encoding.GetNextHeader ());
1638  }
1639 
1640  ipHeader.SetPayloadLength (packet->GetSize ());
1641 
1642  packet->AddHeader (ipHeader);
1643 
1644  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1645 
1646  return false;
1647 }
1648 
1649 uint32_t
1650 SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1651 {
1652  NS_LOG_FUNCTION (this << *packet << int(headerType));
1653 
1654  SixLowPanNhcExtension nhcHeader;
1655  uint32_t size = 0;
1656  Buffer blob;
1657 
1658  if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1659  {
1660  Ipv6ExtensionHopByHopHeader hopHeader;
1661  packet->PeekHeader (hopHeader);
1662  if (hopHeader.GetLength () >= 0xff)
1663  {
1664  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1665  "that have more than 255 octets following the Length field after compression. "
1666  "Packet uncompressed.");
1667  return 0;
1668  }
1669 
1670  size += packet->RemoveHeader (hopHeader);
1672 
1673  // recursively compress other headers
1674  uint8_t nextHeader = hopHeader.GetNextHeader ();
1675  if (CanCompressLowPanNhc (nextHeader))
1676  {
1677  if (nextHeader == Ipv6Header::IPV6_UDP)
1678  {
1679  nhcHeader.SetNh (true);
1680  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1681  }
1682  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1683  {
1684  nhcHeader.SetNh (true);
1685  size += CompressLowPanIphc (packet, src, dst);
1686  }
1687  else
1688  {
1689  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1690  // the compression might fail due to Extension header size.
1691  if (sizeNhc)
1692  {
1693  nhcHeader.SetNh (true);
1694  size += sizeNhc;
1695  }
1696  else
1697  {
1698  nhcHeader.SetNh (false);
1699  nhcHeader.SetNextHeader (nextHeader);
1700  }
1701  }
1702  }
1703  else
1704  {
1705  nhcHeader.SetNh (false);
1706  nhcHeader.SetNextHeader (nextHeader);
1707  }
1708 
1709  uint32_t blobSize = hopHeader.GetSerializedSize ();
1710  blob.AddAtStart (blobSize);
1711  hopHeader.Serialize (blob.Begin ());
1712  blob.RemoveAtStart (2);
1713  blobSize = blob.GetSize ();
1714  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1715  }
1716  else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1717  {
1718  Ipv6ExtensionRoutingHeader routingHeader;
1719  packet->PeekHeader (routingHeader);
1720  if (routingHeader.GetLength () >= 0xff)
1721  {
1722  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1723  "that have more than 255 octets following the Length field after compression. "
1724  "Packet uncompressed.");
1725  return 0;
1726  }
1727 
1728  size += packet->RemoveHeader (routingHeader);
1730 
1731  // recursively compress other headers
1732  uint8_t nextHeader = routingHeader.GetNextHeader ();
1733  if (CanCompressLowPanNhc (nextHeader))
1734  {
1735  if (nextHeader == Ipv6Header::IPV6_UDP)
1736  {
1737  nhcHeader.SetNh (true);
1738  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1739  }
1740  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1741  {
1742  nhcHeader.SetNh (true);
1743  size += CompressLowPanIphc (packet, src, dst);
1744  }
1745  else
1746  {
1747  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1748  // the compression might fail due to Extension header size.
1749  if (sizeNhc)
1750  {
1751  nhcHeader.SetNh (true);
1752  size += sizeNhc;
1753  }
1754  else
1755  {
1756  nhcHeader.SetNh (false);
1757  nhcHeader.SetNextHeader (nextHeader);
1758  }
1759  }
1760  }
1761  else
1762  {
1763  nhcHeader.SetNh (false);
1764  nhcHeader.SetNextHeader (nextHeader);
1765  }
1766 
1767  uint32_t blobSize = routingHeader.GetSerializedSize ();
1768  blob.AddAtStart (blobSize);
1769  routingHeader.Serialize (blob.Begin ());
1770  blob.RemoveAtStart (2);
1771  blobSize = blob.GetSize ();
1772  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1773  }
1774  else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1775  {
1776  Ipv6ExtensionFragmentHeader fragHeader;
1777  packet->PeekHeader (fragHeader);
1778  if (fragHeader.GetLength () >= 0xff)
1779  {
1780  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1781  "that have more than 255 octets following the Length field after compression. "
1782  "Packet uncompressed.");
1783  return 0;
1784  }
1785  size += packet->RemoveHeader (fragHeader);
1787 
1788  // recursively compress other headers
1789  uint8_t nextHeader = fragHeader.GetNextHeader ();
1790  if (CanCompressLowPanNhc (nextHeader))
1791  {
1792  if (nextHeader == Ipv6Header::IPV6_UDP)
1793  {
1794  nhcHeader.SetNh (true);
1795  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1796  }
1797  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1798  {
1799  nhcHeader.SetNh (true);
1800  size += CompressLowPanIphc (packet, src, dst);
1801  }
1802  else
1803  {
1804  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1805  // the compression might fail due to Extension header size.
1806  if (sizeNhc)
1807  {
1808  nhcHeader.SetNh (true);
1809  size += sizeNhc;
1810  }
1811  else
1812  {
1813  nhcHeader.SetNh (false);
1814  nhcHeader.SetNextHeader (nextHeader);
1815  }
1816  }
1817  }
1818  else
1819  {
1820  nhcHeader.SetNh (false);
1821  nhcHeader.SetNextHeader (nextHeader);
1822  }
1823 
1824  uint32_t blobSize = fragHeader.GetSerializedSize ();
1825  blob.AddAtStart (blobSize);
1826  fragHeader.Serialize (blob.Begin ());
1827  blob.RemoveAtStart (2);
1828  blobSize = blob.GetSize ();
1829  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1830  }
1831  else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1832  {
1833  Ipv6ExtensionDestinationHeader destHeader;
1834  packet->PeekHeader (destHeader);
1835  if (destHeader.GetLength () >= 0xff)
1836  {
1837  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1838  "that have more than 255 octets following the Length field after compression. "
1839  "Packet uncompressed.");
1840  return 0;
1841  }
1842  size += packet->RemoveHeader (destHeader);
1844 
1845  // recursively compress other headers
1846  uint8_t nextHeader = destHeader.GetNextHeader ();
1847  if (CanCompressLowPanNhc (nextHeader))
1848  {
1849  if (nextHeader == Ipv6Header::IPV6_UDP)
1850  {
1851  nhcHeader.SetNh (true);
1852  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1853  }
1854  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1855  {
1856  nhcHeader.SetNh (true);
1857  size += CompressLowPanIphc (packet, src, dst);
1858  }
1859  else
1860  {
1861  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1862  // the compression might fail due to Extension header size.
1863  if (sizeNhc)
1864  {
1865  nhcHeader.SetNh (true);
1866  size += sizeNhc;
1867  }
1868  else
1869  {
1870  nhcHeader.SetNh (false);
1871  nhcHeader.SetNextHeader (nextHeader);
1872  }
1873  }
1874  }
1875  else
1876  {
1877  nhcHeader.SetNh (false);
1878  nhcHeader.SetNextHeader (nextHeader);
1879  }
1880 
1881  uint32_t blobSize = destHeader.GetSerializedSize ();
1882  blob.AddAtStart (blobSize);
1883  destHeader.Serialize (blob.Begin ());
1884  blob.RemoveAtStart (2);
1885  blobSize = blob.GetSize ();
1886  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1887  }
1888  else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1889  {
1890  // \todo: IPv6 Mobility Header is not supported in ns-3
1891  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1892  return 0;
1893  }
1894  else
1895  {
1896  NS_ABORT_MSG ("Unexpected Extension Header");
1897  }
1898 
1899  NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1900  NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1901 
1902  packet->AddHeader (nhcHeader);
1903 
1904  NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1905  return size;
1906 }
1907 
1908 std::pair <uint8_t, bool>
1909 SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1910 {
1911  NS_LOG_FUNCTION (this << *packet);
1912 
1913  SixLowPanNhcExtension encoding;
1914 
1915  uint32_t ret = packet->RemoveHeader (encoding);
1916  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1917  NS_UNUSED (ret);
1918 
1919  Ipv6ExtensionHopByHopHeader hopHeader;
1920  Ipv6ExtensionRoutingHeader routingHeader;
1921  Ipv6ExtensionFragmentHeader fragHeader;
1922  Ipv6ExtensionDestinationHeader destHeader;
1923 
1924  uint32_t blobSize;
1925  uint8_t blobData[260];
1926  blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
1927  uint8_t paddingSize = 0;
1928 
1929  uint8_t actualEncodedHeaderType = encoding.GetEid ();
1930  uint8_t actualHeaderType;
1931  Buffer blob;
1932 
1933  switch (actualEncodedHeaderType)
1934  {
1936  actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1937  if ( encoding.GetNh () )
1938  {
1939  // Next Header
1940  uint8_t dispatchRawVal = 0;
1942 
1943  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1944  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1945 
1946  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1947  {
1948  blobData [0] = Ipv6Header::IPV6_UDP;
1949  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1950  }
1951  else
1952  {
1953  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
1954  }
1955  }
1956  else
1957  {
1958  blobData [0] = encoding.GetNextHeader ();
1959  }
1960 
1961  // manually add some padding if needed
1962  if ((blobSize + 2) % 8 > 0)
1963  {
1964  paddingSize = 8 - (blobSize + 2) % 8;
1965  }
1966  if (paddingSize == 1)
1967  {
1968  blobData[blobSize + 2] = 0;
1969  }
1970  else if (paddingSize > 1)
1971  {
1972  blobData[blobSize + 2] = 1;
1973  blobData[blobSize + 2 + 1] = paddingSize - 2;
1974  for (uint8_t i = 0; i < paddingSize - 2; i++)
1975  {
1976  blobData[blobSize + 2 + 2 + i] = 0;
1977  }
1978  }
1979  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1980  blob.AddAtStart (blobSize + 2 + paddingSize);
1981  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1982  hopHeader.Deserialize (blob.Begin ());
1983 
1984  packet->AddHeader (hopHeader);
1985  break;
1986 
1988  actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1989  if ( encoding.GetNh () )
1990  {
1991  // Next Header
1992  uint8_t dispatchRawVal = 0;
1994 
1995  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1996  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1997 
1998  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1999  {
2000  blobData [0] = Ipv6Header::IPV6_UDP;
2001  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2002  }
2003  else
2004  {
2005  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2006  }
2007  }
2008  else
2009  {
2010  blobData [0] = encoding.GetNextHeader ();
2011  }
2012  blobData [1] = ((blobSize + 2) >> 3) - 1;
2013  blob.AddAtStart (blobSize + 2);
2014  blob.Begin ().Write (blobData, blobSize + 2);
2015  routingHeader.Deserialize (blob.Begin ());
2016  packet->AddHeader (routingHeader);
2017  break;
2018 
2020  actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
2021  if ( encoding.GetNh () )
2022  {
2023  // Next Header
2024  uint8_t dispatchRawVal = 0;
2026 
2027  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2028  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2029 
2030  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2031  {
2032  blobData [0] = Ipv6Header::IPV6_UDP;
2033  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2034  }
2035  else
2036  {
2037  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2038  }
2039  }
2040  else
2041  {
2042  blobData [0] = encoding.GetNextHeader ();
2043  }
2044  blobData [1] = 0;
2045 
2046  blob.AddAtStart (blobSize + 2);
2047  blob.Begin ().Write (blobData, blobSize + 2);
2048 
2049  fragHeader.Deserialize (blob.Begin ());
2050  packet->AddHeader (fragHeader);
2051  break;
2052 
2054  actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
2055  if ( encoding.GetNh () )
2056  {
2057  // Next Header
2058  uint8_t dispatchRawVal = 0;
2060 
2061  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2062  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2063 
2064  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2065  {
2066  blobData [0] = Ipv6Header::IPV6_UDP;
2067  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2068  }
2069  else
2070  {
2071  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2072  }
2073  }
2074  else
2075  {
2076  blobData [0] = encoding.GetNextHeader ();
2077  }
2078 
2079  // manually add some padding if needed
2080  if ((blobSize + 2) % 8 > 0)
2081  {
2082  paddingSize = 8 - (blobSize + 2) % 8;
2083  }
2084  if (paddingSize == 1)
2085  {
2086  blobData[blobSize + 2] = 0;
2087  }
2088  else if (paddingSize > 1)
2089  {
2090  blobData[blobSize + 2] = 1;
2091  blobData[blobSize + 2 + 1] = paddingSize - 2;
2092  for (uint8_t i = 0; i < paddingSize - 2; i++)
2093  {
2094  blobData[blobSize + 2 + 2 + i] = 0;
2095  }
2096  }
2097  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
2098  blob.AddAtStart (blobSize + 2 + paddingSize);
2099  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
2100  destHeader.Deserialize (blob.Begin ());
2101 
2102  packet->AddHeader (destHeader);
2103  break;
2105  // \todo: IPv6 Mobility Header is not supported in ns-3
2106  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
2107  break;
2109  actualHeaderType = Ipv6Header::IPV6_IPV6;
2110  if (DecompressLowPanIphc (packet, src, dst))
2111  {
2113  return std::pair<uint8_t, bool> (0, true);
2114  }
2115  break;
2116  default:
2117  NS_ABORT_MSG ("Trying to decode unknown Extension Header");
2118  break;
2119  }
2120 
2121  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2122  return std::pair<uint8_t, bool> (actualHeaderType, false);
2123 }
2124 
2125 uint32_t
2127 {
2128  NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
2129 
2130  UdpHeader udpHeader;
2131  SixLowPanUdpNhcExtension udpNhcHeader;
2132  uint32_t size = 0;
2133 
2134  NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
2135 
2136  size += packet->RemoveHeader (udpHeader);
2137 
2138  // Set the C field and checksum
2139  udpNhcHeader.SetC (false);
2140  uint16_t checksum = udpHeader.GetChecksum ();
2141  udpNhcHeader.SetChecksum (checksum);
2142 
2143  if (omitChecksum && udpHeader.IsChecksumOk ())
2144  {
2145  udpNhcHeader.SetC (true);
2146  }
2147 
2148  // Set the value of the ports
2149  udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
2150  udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
2151 
2152  //Set the P field
2153  if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
2154  {
2156  }
2157  else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
2158  {
2160  }
2161  else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
2162  {
2164  }
2165  else
2166  {
2168  }
2169 
2170  NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
2171  NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
2172 
2173  packet->AddHeader (udpNhcHeader);
2174 
2175  NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
2176 
2177  return size;
2178 }
2179 
2180 void
2182 {
2183  NS_LOG_FUNCTION (this << *packet);
2184 
2185  UdpHeader udpHeader;
2186  SixLowPanUdpNhcExtension encoding;
2187 
2188  uint32_t ret = packet->RemoveHeader (encoding);
2189  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
2190  NS_UNUSED (ret);
2191 
2192  // Set the value of the ports
2193  switch ( encoding.GetPorts () )
2194  {
2195  uint16_t temp;
2197  udpHeader.SetSourcePort (encoding.GetSrcPort ());
2198  udpHeader.SetDestinationPort (encoding.GetDstPort ());
2199  break;
2201  udpHeader.SetSourcePort (encoding.GetSrcPort ());
2202  temp = 0xf0;
2203  temp |= (temp << 8) | encoding.GetDstPort ();
2204  udpHeader.SetDestinationPort (temp);
2205  break;
2207  temp = 0xf0;
2208  temp |= (temp << 8) | encoding.GetSrcPort ();
2209  udpHeader.SetSourcePort (temp);
2210  udpHeader.SetDestinationPort (encoding.GetDstPort ());
2211  break;
2213  temp = 0xf0b;
2214  temp |= (temp << 4) | encoding.GetSrcPort ();
2215  udpHeader.SetSourcePort (temp);
2216  temp = 0xf0b;
2217  temp |= (temp << 4) | encoding.GetDstPort ();
2218  udpHeader.SetDestinationPort (temp);
2219  break;
2220  }
2221 
2222  // Get the C field and checksum
2223  if (Node::ChecksumEnabled ())
2224  {
2225  if ( encoding.GetC () )
2226  {
2227  NS_LOG_LOGIC ("Recalculating UDP Checksum");
2228  udpHeader.EnableChecksums ();
2229  udpHeader.InitializeChecksum (saddr,
2230  daddr,
2232  packet->AddHeader (udpHeader);
2233  }
2234  else
2235  {
2236  NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
2237  udpHeader.ForceChecksum (encoding.GetChecksum ());
2238  packet->AddHeader (udpHeader);
2239  NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
2240  }
2241  }
2242  else
2243  {
2244  packet->AddHeader (udpHeader);
2245  }
2246 
2247  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2248 }
2249 
2251  uint32_t origPacketSize,
2252  uint32_t origHdrSize,
2253  std::list<Ptr<Packet> >& listFragments)
2254 {
2255  NS_LOG_FUNCTION (this << *packet);
2256 
2257  Ptr<Packet> p = packet->Copy ();
2258 
2259  uint16_t offsetData = 0;
2260  uint16_t offset = 0;
2261  uint16_t l2Mtu = m_netDevice->GetMtu ();
2262  uint32_t packetSize = packet->GetSize ();
2263  uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
2264 
2265  uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
2266  NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
2267 
2268  // first fragment
2269  SixLowPanFrag1 frag1Hdr;
2270  frag1Hdr.SetDatagramTag (tag);
2271 
2272  uint32_t size;
2273  NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
2274  "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
2275 
2276  size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize;
2277  size -= size % 8;
2278  size += compressedHeaderSize;
2279 
2280  frag1Hdr.SetDatagramSize (origPacketSize);
2281 
2282  Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
2283  offset += size + origHdrSize - compressedHeaderSize;
2284  offsetData += size;
2285 
2286  fragment1->AddHeader (frag1Hdr);
2287  listFragments.push_back (fragment1);
2288 
2289  bool moreFrag = true;
2290  do
2291  {
2292  SixLowPanFragN fragNHdr;
2293  fragNHdr.SetDatagramTag (tag);
2294  fragNHdr.SetDatagramSize (origPacketSize);
2295  fragNHdr.SetDatagramOffset ((offset) >> 3);
2296 
2297  size = l2Mtu - fragNHdr.GetSerializedSize ();
2298  size -= size % 8;
2299 
2300  if ( (offsetData + size) > packetSize )
2301  {
2302  size = packetSize - offsetData;
2303  moreFrag = false;
2304  }
2305 
2306  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
2307  Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
2308  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
2309 
2310  offset += size;
2311  offsetData += size;
2312 
2313  fragment->AddHeader (fragNHdr);
2314  listFragments.push_back (fragment);
2315 
2316  }
2317  while (moreFrag);
2318 
2319  return;
2320 }
2321 
2322 bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
2323 {
2324  NS_LOG_FUNCTION ( this << *packet );
2325  SixLowPanFrag1 frag1Header;
2326  SixLowPanFragN fragNHeader;
2327  FragmentKey_t key;
2328  uint16_t packetSize;
2329  key.first = std::pair<Address, Address> (src, dst);
2330 
2331  Ptr<Packet> p = packet->Copy ();
2332  uint16_t offset = 0;
2333 
2334  /* Implementation note:
2335  *
2336  * The fragment offset is relative to the *uncompressed* packet.
2337  * On the other hand, the packet can not be uncompressed correctly without all
2338  * its fragments, as the UDP checksum can not be computed otherwise.
2339  *
2340  * As a consequence we must uncompress the packet twice, and save its first
2341  * fragment for the final one.
2342  */
2343 
2344  if ( isFirst )
2345  {
2346  uint8_t dispatchRawValFrag1 = 0;
2347  SixLowPanDispatch::Dispatch_e dispatchValFrag1;
2348 
2349  p->RemoveHeader (frag1Header);
2350  packetSize = frag1Header.GetDatagramSize ();
2351  p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
2352  dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
2353  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
2354  NS_LOG_DEBUG ( "Packet: " << *p );
2355 
2356  switch ( dispatchValFrag1 )
2357  {
2359  {
2360  SixLowPanIpv6 uncompressedHdr;
2361  p->RemoveHeader (uncompressedHdr);
2362  }
2363  break;
2365  DecompressLowPanHc1 (p, src, dst);
2366  break;
2368  if (DecompressLowPanIphc (p, src, dst))
2369  {
2371  return false;
2372  }
2373  break;
2374  default:
2375  NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
2376  break;
2377  }
2378 
2379  key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
2380  }
2381  else
2382  {
2383  p->RemoveHeader (fragNHeader);
2384  packetSize = fragNHeader.GetDatagramSize ();
2385  offset = fragNHeader.GetDatagramOffset () << 3;
2386  key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
2387  }
2388 
2389  Ptr<Fragments> fragments;
2390 
2391  MapFragments_t::iterator it = m_fragments.find (key);
2392  if (it == m_fragments.end ())
2393  {
2394  // erase the oldest packet.
2396  {
2398  FragmentKey_t oldestKey = std::get<1> (*iter);
2399 
2400  std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
2401  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2402  fragIter != storedFragments.end (); fragIter++)
2403  {
2405  }
2406 
2407  m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
2408  m_fragments[oldestKey] = 0;
2409  m_fragments.erase (oldestKey);
2410 
2411  }
2412  fragments = Create<Fragments> ();
2413  fragments->SetPacketSize (packetSize);
2414  m_fragments.insert (std::make_pair (key, fragments));
2415  uint32_t ifIndex = GetIfIndex ();
2416 
2417  FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
2418  fragments->SetTimeoutIter (iter);
2419  }
2420  else
2421  {
2422  fragments = it->second;
2423  }
2424 
2425  fragments->AddFragment (p, offset);
2426 
2427  // add the very first fragment so we can correctly decode the packet once is rebuilt.
2428  // this is needed because otherwise the UDP header length and checksum can not be calculated.
2429  if ( isFirst )
2430  {
2431  fragments->AddFirstFragment (packet);
2432  }
2433 
2434  if ( fragments->IsEntire () )
2435  {
2436  packet = fragments->GetPacket ();
2437  NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
2438 
2439  SixLowPanFrag1 frag1Header;
2440  packet->RemoveHeader (frag1Header);
2441 
2442  NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
2443  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
2444  fragments = 0;
2445  m_fragments.erase (key);
2446  return true;
2447  }
2448 
2449  return false;
2450 }
2451 
2453 {
2454  NS_LOG_FUNCTION (this);
2455  m_packetSize = 0;
2456 }
2457 
2459 {
2460  NS_LOG_FUNCTION (this);
2461 }
2462 
2463 void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
2464 {
2465  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
2466 
2467  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
2468  bool duplicate = false;
2469 
2470  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
2471  {
2472  if (it->second > fragmentOffset)
2473  {
2474  break;
2475  }
2476  if (it->second == fragmentOffset)
2477  {
2478  duplicate = true;
2479  NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
2480  break;
2481  }
2482  }
2483  if (!duplicate)
2484  {
2485  m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
2486  }
2487 }
2488 
2490 {
2491  NS_LOG_FUNCTION (this << *fragment);
2492 
2493  m_firstFragment = fragment;
2494 }
2495 
2497 {
2498  NS_LOG_FUNCTION (this);
2499 
2500  bool ret = m_fragments.size () > 0;
2501  uint16_t lastEndOffset = 0;
2502 
2503  if (ret)
2504  {
2505  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
2506  {
2507  // overlapping fragments should not exist
2508  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
2509 
2510  if (lastEndOffset < it->second)
2511  {
2512  ret = false;
2513  break;
2514  }
2515  // fragments might overlap in strange ways
2516  uint16_t fragmentEnd = it->first->GetSize () + it->second;
2517  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
2518  }
2519  }
2520 
2521  if ( ret && (lastEndOffset == m_packetSize))
2522  {
2523  return true;
2524  }
2525  return false;
2526 }
2527 
2529 {
2530  NS_LOG_FUNCTION (this);
2531 
2532  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2533 
2534  Ptr<Packet> p = Create<Packet> ();
2535  uint16_t lastEndOffset = 0;
2536 
2537  p->AddAtEnd (m_firstFragment);
2538  it = m_fragments.begin ();
2539  lastEndOffset = it->first->GetSize ();
2540 
2541  for ( it++; it != m_fragments.end (); it++)
2542  {
2543  if ( lastEndOffset > it->second )
2544  {
2545  NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2546  }
2547  else
2548  {
2549  NS_LOG_LOGIC ("Adding: " << *(it->first) );
2550  p->AddAtEnd (it->first);
2551  }
2552  lastEndOffset += it->first->GetSize ();
2553  }
2554 
2555  return p;
2556 }
2557 
2559 {
2560  NS_LOG_FUNCTION (this << packetSize);
2561  m_packetSize = packetSize;
2562 }
2563 
2564 std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2565 {
2566  std::list< Ptr<Packet> > fragments;
2567  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2568  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
2569  {
2570  fragments.push_back (iter->first);
2571  }
2572  return fragments;
2573 }
2574 
2575 void
2577 {
2578  m_timeoutIter = iter;
2579  return;
2580 }
2581 
2584 {
2585  return m_timeoutIter;
2586 }
2587 
2589 {
2590  NS_LOG_FUNCTION (this);
2591 
2592  MapFragments_t::iterator it = m_fragments.find (key);
2593  std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2594  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2595  fragIter != storedFragments.end (); fragIter++)
2596  {
2598  }
2599  // clear the buffers
2600  it->second = 0;
2601 
2602  m_fragments.erase (key);
2603 }
2604 
2606 {
2607  NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
2608 
2609  uint8_t buf[6];
2610  addr.CopyTo (buf);
2611 
2612  Mac16Address shortAddr;
2613  shortAddr.CopyFrom (buf + 4);
2614 
2615  return shortAddr;
2616 }
2617 
2619 {
2620  if (m_timeoutEventList.empty ())
2621  {
2623  }
2624  m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, iif);
2625 
2627 
2628  return (iter);
2629 }
2630 
2632 {
2633  Time now = Simulator::Now ();
2634 
2635  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
2636  {
2637  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
2638  std::get<2> (*m_timeoutEventList.begin ()));
2639  m_timeoutEventList.pop_front ();
2640  }
2641 
2642  if (m_timeoutEventList.empty ())
2643  {
2644  return;
2645  }
2646 
2647  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
2649 
2650  return;
2651 }
2652 
2653 void SixLowPanNetDevice::AddContext (uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
2654 {
2655  NS_LOG_FUNCTION (this << +contextId << Ipv6Address::GetOnes ().CombinePrefix (contextPrefix) << contextPrefix << compressionAllowed << validLifetime.As (Time::S));
2656 
2657  if (contextId > 15)
2658  {
2659  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2660  return;
2661  }
2662 
2663  if (validLifetime == Time(0))
2664  {
2665  NS_LOG_LOGIC ("Context (" << +contextId << "), removed (validity time is zero)");
2666  m_contextTable.erase (contextId);
2667  return;
2668  }
2669 
2670  m_contextTable[contextId].contextPrefix = contextPrefix;
2671  m_contextTable[contextId].compressionAllowed = compressionAllowed;
2672  m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2673 
2674  return;
2675 }
2676 
2677 bool SixLowPanNetDevice::GetContext (uint8_t contextId, Ipv6Prefix& contextPrefix, bool& compressionAllowed, Time& validLifetime)
2678 {
2679  NS_LOG_FUNCTION (this << +contextId);
2680 
2681  if (contextId > 15)
2682  {
2683  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2684  return false;
2685  }
2686 
2687  if (m_contextTable.find (contextId) == m_contextTable.end ())
2688  {
2689  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2690  return false;
2691  }
2692 
2693  contextPrefix = m_contextTable[contextId].contextPrefix;
2694  compressionAllowed = m_contextTable[contextId].compressionAllowed;
2695  validLifetime = m_contextTable[contextId].validLifetime;
2696 
2697  return true;
2698 }
2699 
2700 void SixLowPanNetDevice::RenewContext (uint8_t contextId, Time validLifetime)
2701 {
2702  NS_LOG_FUNCTION (this << +contextId << validLifetime.As (Time::S));
2703 
2704  if (contextId > 15)
2705  {
2706  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2707  return;
2708  }
2709 
2710  if (m_contextTable.find (contextId) == m_contextTable.end ())
2711  {
2712  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2713  return;
2714  }
2715  m_contextTable[contextId].compressionAllowed = true;
2716  m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2717  return;
2718 }
2719 
2720 
2722 {
2723  NS_LOG_FUNCTION (this << +contextId);
2724 
2725  if (contextId > 15)
2726  {
2727  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2728  return;
2729  }
2730 
2731  if (m_contextTable.find (contextId) == m_contextTable.end ())
2732  {
2733  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2734  return;
2735  }
2736  m_contextTable[contextId].compressionAllowed = false;
2737  return;
2738 }
2739 
2740 void SixLowPanNetDevice::RemoveContext (uint8_t contextId)
2741 {
2742  NS_LOG_FUNCTION (this << +contextId);
2743 
2744  if (contextId > 15)
2745  {
2746  NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2747  return;
2748  }
2749 
2750  if (m_contextTable.find (contextId) == m_contextTable.end ())
2751  {
2752  NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2753  return;
2754  }
2755 
2756  m_contextTable.erase (contextId);
2757  return;
2758 }
2759 
2761 {
2762  NS_LOG_FUNCTION (this << address);
2763 
2764  for (const auto& iter: m_contextTable)
2765  {
2766  ContextEntry context = iter.second;
2767 
2768  if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2769  {
2770 
2771  if (address.HasPrefix (context.contextPrefix))
2772  {
2773  NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2774  Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2775 
2776  contextId = iter.first;
2777  return true;
2778  }
2779  }
2780  }
2781  return false;
2782 }
2783 
2785 {
2786  NS_LOG_FUNCTION (this << address);
2787 
2788  // The only allowed context-based compressed multicast address is in the form
2789  // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
2790 
2791  for (const auto& iter: m_contextTable)
2792  {
2793  ContextEntry context = iter.second;
2794 
2795  if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2796  {
2797  uint8_t contextLength = context.contextPrefix.GetPrefixLength ();
2798 
2799  if (contextLength <= 64) // only 64-bit prefixes or less are allowed.
2800  {
2801  uint8_t contextBytes[16];
2802  uint8_t addressBytes[16];
2803 
2804  context.contextPrefix.GetBytes (contextBytes);
2805  address.GetBytes (addressBytes);
2806 
2807  if (addressBytes[3] == contextLength &&
2808  addressBytes[4] == contextBytes[0] &&
2809  addressBytes[5] == contextBytes[1] &&
2810  addressBytes[6] == contextBytes[2] &&
2811  addressBytes[7] == contextBytes[3] &&
2812  addressBytes[8] == contextBytes[4] &&
2813  addressBytes[9] == contextBytes[5] &&
2814  addressBytes[10] == contextBytes[6] &&
2815  addressBytes[11] == contextBytes[7])
2816  {
2817  NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2818  Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2819 
2820  contextId = iter.first;
2821  return true;
2822  }
2823  }
2824  }
2825  }
2826  return false;
2827 }
2828 
2830 {
2831  uint8_t addressBytes[16];
2832  address.GetBytes (addressBytes);
2833  uint8_t prefixLength = prefix.GetPrefixLength ();
2834 
2835  uint8_t bytesToClean = prefixLength / 8;
2836  uint8_t bitsToClean = prefixLength % 8;
2837  for (uint8_t i=0; i<bytesToClean; i++)
2838  {
2839  addressBytes[i] = 0;
2840  }
2841  if (bitsToClean)
2842  {
2843  uint8_t cleanupMask = (1<<bitsToClean)-1;
2844  addressBytes[bytesToClean] &= cleanupMask;
2845  }
2846 
2847  Ipv6Address cleanedAddress = Ipv6Address::Deserialize (addressBytes);
2848 
2849  return cleanedAddress;
2850 }
2851 
2852 }
2853 
2854 // namespace ns3
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.
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.
void DoFragmentation(Ptr< Packet > packet, uint32_t origPacketSize, uint32_t origHdrSize, std::list< Ptr< Packet > > &listFragments)
Performs a packet fragmentation.
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:467
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:83
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.