A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 "ns3/node.h"
23 #include "ns3/channel.h"
24 #include "ns3/packet.h"
25 #include "ns3/log.h"
26 #include "ns3/boolean.h"
27 #include "ns3/abort.h"
28 #include "ns3/simulator.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/icmpv6-header.h"
31 #include "ns3/ipv6-header.h"
32 #include "ns3/random-variable.h"
33 #include "ns3/mac16-address.h"
34 #include "ns3/mac48-address.h"
35 #include "ns3/mac64-address.h"
36 #include "ns3/unused.h"
37 #include "ns3/ipv6-l3-protocol.h"
38 #include "ns3/ipv6-extension-header.h"
39 #include "ns3/udp-header.h"
40 #include "ns3/udp-l4-protocol.h"
41 #include "sixlowpan-net-device.h"
42 #include "sixlowpan-header.h"
43 
44 NS_LOG_COMPONENT_DEFINE ("SixLowPanNetDevice");
45 
46 namespace ns3 {
47 
48 NS_OBJECT_ENSURE_REGISTERED (SixLowPanNetDevice);
49 
51 {
52  static TypeId tid = TypeId ("ns3::SixLowPanNetDevice")
53  .SetParent<NetDevice> ()
54  .AddConstructor<SixLowPanNetDevice> ()
55  .AddAttribute ("Rfc6282", "Use RFC6282 (IPHC) if true, RFC4944 (HC1) otherwise.",
56  BooleanValue (true),
57  MakeBooleanAccessor (&SixLowPanNetDevice::m_useIphc),
58  MakeBooleanChecker ())
59  .AddAttribute ("OmitUdpChecksum",
60  "Omit the UDP checksum in IPHC compression.",
61  BooleanValue (true),
62  MakeBooleanAccessor (&SixLowPanNetDevice::m_omitUdpChecksum),
63  MakeBooleanChecker ())
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),
76  MakeUintegerAccessor (&SixLowPanNetDevice::m_compressionThreshold),
77  MakeUintegerChecker<uint32_t> ())
78  .AddAttribute ("ForceEtherType",
79  "Force a specific EtherType in L2 frames.",
80  BooleanValue (false),
81  MakeBooleanAccessor (&SixLowPanNetDevice::m_forceEtherType),
82  MakeBooleanChecker ())
83  .AddAttribute ("EtherType",
84  "The specific EtherType to be used in L2 frames.",
85  UintegerValue (0xFFFF),
86  MakeUintegerAccessor (&SixLowPanNetDevice::m_etherType),
87  MakeUintegerChecker<uint16_t> ())
88  .AddTraceSource ("Tx", "Send - packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
90  .AddTraceSource ("Rx", "Receive - packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
92  .AddTraceSource ("Drop", "Drop - DropReason, packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
94  ;
95  return tid;
96 }
97 
99  : m_node (0),
100  m_netDevice (0),
101  m_ifIndex (0)
102 {
103  NS_LOG_FUNCTION (this);
104  m_netDevice = 0;
105  m_rng = CreateObject<UniformRandomVariable> ();
106 }
107 
109 {
110  NS_LOG_FUNCTION (this);
111  return m_netDevice;
112 }
113 
115 {
116  NS_LOG_FUNCTION (this << device);
117  m_netDevice = device;
118 
119  NS_LOG_DEBUG ("RegisterProtocolHandler for " << device->GetInstanceTypeId ().GetName ());
120 
121  uint16_t protocolType = 0;
122  if ( m_forceEtherType )
123  {
124  protocolType = m_etherType;
125  }
127  this),
128  protocolType, device, false);
129 }
130 
131 int64_t SixLowPanNetDevice::AssignStreams (int64_t stream)
132 {
133  NS_LOG_FUNCTION (this << stream);
134  m_rng->SetStream (stream);
135  return 1;
136 }
137 
139 {
140  NS_LOG_FUNCTION (this);
141 
142  m_netDevice = 0;
143  m_node = 0;
144 
145  for (MapFragmentsTimersI_t iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
146  {
147  iter->second.Cancel ();
148  }
149  m_fragmentsTimers.clear ();
150 
151  for (MapFragmentsI_t iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
152  {
153  iter->second = 0;
154  }
155  m_fragments.clear ();
156 
158 }
159 
161  Ptr<const Packet> packet,
162  uint16_t protocol,
163  Address const &src,
164  Address const &dst,
165  PacketType packetType)
166 {
167  NS_LOG_FUNCTION (this << incomingPort << packet << protocol << src << dst);
168  NS_LOG_DEBUG ("UID is " << packet->GetUid ());
169 
170  uint8_t dispatchRawVal = 0;
171  SixLowPanDispatch::Dispatch_e dispatchVal;
172  Ptr<Packet> copyPkt = packet->Copy ();
173 
175 
176  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
177  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
178  bool isPktDecompressed = false;
179  bool fragmented = false;
180 
181  NS_LOG_DEBUG ( "Packet received: " << *copyPkt );
182  NS_LOG_DEBUG ( "Packet length: " << copyPkt->GetSize () );
183  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal) );
184 
185  if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1 )
186  {
187  isPktDecompressed = ProcessFragment (copyPkt, src, dst, true);
188  fragmented = true;
189  }
190  else if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN )
191  {
192  isPktDecompressed = ProcessFragment (copyPkt, src, dst, false);
193  fragmented = true;
194  }
195  if ( fragmented )
196  {
197  if ( !isPktDecompressed )
198  {
199  return;
200  }
201  else
202  {
203  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
204  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
205  }
206  }
207 
208  switch ( dispatchVal )
209  {
211  NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: MESH, dropping.");
213  break;
215  NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: BC0, dropping.");
217  break;
219  NS_LOG_DEBUG ( "Packet without compression. Length: " << copyPkt->GetSize () );
220  {
221  SixLowPanIpv6 uncompressedHdr;
222  copyPkt->RemoveHeader(uncompressedHdr);
223  isPktDecompressed = true;
224  }
225  break;
227  DecompressLowPanHc1 (copyPkt, src, dst);
228  isPktDecompressed = true;
229  break;
231  DecompressLowPanIphc (copyPkt, src, dst);
232  isPktDecompressed = true;
233  break;
234  default:
235  NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
237  break;
238  }
239 
240  if ( !isPktDecompressed )
241  {
242  return;
243  }
244 
245  NS_LOG_DEBUG ( "Packet decompressed length: " << copyPkt->GetSize () );
246  NS_LOG_DEBUG ( "Packet decompressed received: " << *copyPkt );
247 
248  if (!m_promiscRxCallback.IsNull ())
249  {
250  m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src, dst, packetType);
251  }
252 
253  m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src);
254 
255  return;
256 }
257 
258 void SixLowPanNetDevice::SetIfIndex (const uint32_t index)
259 {
260  NS_LOG_FUNCTION (this << index);
261  m_ifIndex = index;
262 }
263 
264 uint32_t SixLowPanNetDevice::GetIfIndex (void) const
265 {
266  NS_LOG_FUNCTION (this);
267  return m_ifIndex;
268 }
269 
271 {
272  NS_LOG_FUNCTION (this);
273  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
274 
275  return m_netDevice->GetChannel ();
276 }
277 
279 {
280  NS_LOG_FUNCTION (this << address);
281  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
282 
283  m_netDevice->SetAddress (address);
284 }
285 
287 {
288  NS_LOG_FUNCTION (this);
289  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
290 
291  return m_netDevice->GetAddress ();
292 }
293 
294 bool SixLowPanNetDevice::SetMtu (const uint16_t mtu)
295 {
296  NS_LOG_FUNCTION (this << mtu);
297  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
298 
299  return m_netDevice->SetMtu (mtu);
300 }
301 
302 uint16_t SixLowPanNetDevice::GetMtu (void) const
303 {
304  NS_LOG_FUNCTION (this);
305 
306  uint16_t mtu = m_netDevice->GetMtu ();
307 
308  // RFC 4944, section 4.
309  if (mtu < 1280)
310  {
311  mtu = 1280;
312  }
313  return mtu;
314 }
315 
317 {
318  NS_LOG_FUNCTION (this);
319  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
320 
321  return m_netDevice->IsLinkUp ();
322 }
323 
325 {
326  NS_LOG_FUNCTION (this);
327  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
328 
329  return m_netDevice->AddLinkChangeCallback (callback);
330 }
331 
333 {
334  NS_LOG_FUNCTION (this);
335  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
336 
337  return m_netDevice->IsBroadcast ();
338 }
339 
341 {
342  NS_LOG_FUNCTION (this);
343  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
344 
345  return m_netDevice->GetBroadcast ();
346 }
347 
349 {
350  NS_LOG_FUNCTION (this);
351  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
352 
353  return m_netDevice->IsMulticast ();
354 }
355 
357 {
358  NS_LOG_FUNCTION (this << multicastGroup);
359  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
360 
361  return m_netDevice->GetMulticast (multicastGroup);
362 }
363 
365 {
366  NS_LOG_FUNCTION (this << addr);
367  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
368 
369  return m_netDevice->GetMulticast (addr);
370 }
371 
373 {
374  NS_LOG_FUNCTION (this);
375  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
376 
377  return m_netDevice->IsPointToPoint ();
378 }
379 
381 {
382  NS_LOG_FUNCTION (this);
383  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
384 
385  return m_netDevice->IsBridge ();
386 }
387 
389  const Address& dest,
390  uint16_t protocolNumber)
391 {
392  NS_LOG_FUNCTION (this << *packet << dest << protocolNumber);
393  bool ret = false;
394  Address src;
395 
396  ret = DoSend (packet, src, dest, protocolNumber, false);
397  return ret;
398 }
399 
401  const Address& src,
402  const Address& dest,
403  uint16_t protocolNumber)
404 {
405  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber);
406  bool ret = false;
407 
408  ret = DoSend (packet, src, dest, protocolNumber, true);
409  return ret;
410 }
411 
413  const Address& src,
414  const Address& dest,
415  uint16_t protocolNumber,
416  bool doSendFrom)
417 {
418  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber << doSendFrom);
419  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
420 
421  Ptr<Packet> origPacket = packet->Copy ();
422  uint32_t origHdrSize = 0;
423  uint32_t origPacketSize = packet->GetSize ();
424  bool ret = false;
425 
426  if (m_forceEtherType)
427  {
428  protocolNumber = m_etherType;
429  }
430 
431  if (m_useIphc)
432  {
433  origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), dest);
434  }
435  else
436  {
437  origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), dest);
438  }
439 
440  if ( packet->GetSize () > m_netDevice->GetMtu () )
441  {
442  NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
443  // fragment
444  std::list<Ptr<Packet> > fragmentList;
445  DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
446  std::list<Ptr<Packet> >::iterator it;
447  bool success = true;
448  for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
449  {
450  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
452  if (doSendFrom)
453  {
454  success &= m_netDevice->SendFrom (*it, src, dest, protocolNumber);
455  }
456  else
457  {
458  success &= m_netDevice->Send (*it, dest, protocolNumber);
459  }
460  }
461  ret = success;
462  }
463  else
464  {
465  if (packet->GetSize () < m_compressionThreshold)
466  {
467  NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
468  packet = origPacket;
469  SixLowPanIpv6 ipv6UncompressedHdr;
470  packet->AddHeader (ipv6UncompressedHdr);
471  }
472 
474  if (doSendFrom)
475  {
476  NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
477  ret = m_netDevice->SendFrom (packet, src, dest, protocolNumber);
478  }
479  else
480  {
481  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
482  ret = m_netDevice->Send (packet, dest, protocolNumber);
483  }
484  }
485 
486  return ret;
487 }
488 
490 {
491  NS_LOG_FUNCTION (this);
492  return m_node;
493 }
494 
496 {
497  NS_LOG_FUNCTION (this << node);
498  m_node = node;
499 }
500 
502 {
503  NS_LOG_FUNCTION (this);
504  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
505 
506  return m_netDevice->NeedsArp ();
507 }
508 
510 {
511  NS_LOG_FUNCTION (this << &cb);
512  m_rxCallback = cb;
513 }
514 
516 {
517  NS_LOG_FUNCTION (this << &cb);
518  m_promiscRxCallback = cb;
519 }
520 
522 {
523  NS_LOG_FUNCTION (this);
524  return true;
525 }
526 
527 uint32_t
529 {
530  NS_LOG_FUNCTION (this << *packet << src << dst);
531 
532  Ipv6Header ipHeader;
533  SixLowPanHc1 hc1Header;
534  uint32_t size = 0;
535 
536  if ( packet->PeekHeader (ipHeader) != 0 )
537  {
538  packet->RemoveHeader (ipHeader);
539  size += ipHeader.GetSerializedSize ();
540 
541  hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
542 
543  uint8_t bufOne[16];
544  uint8_t bufTwo[16];
545  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
546  srcAddr.GetBytes (bufOne);
547  Ipv6Address mySrcAddr = MakeLinkLocalAddressFromMac (src);
548 
549  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
550 
551  mySrcAddr.GetBytes (bufTwo);
552  bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
553 
554  if (srcAddr.IsLinkLocal () && isSrcSrc )
555  {
557  }
558  else if (srcAddr.IsLinkLocal () )
559  {
561  hc1Header.SetSrcInterface (bufOne + 8);
562  }
563  else if ( isSrcSrc )
564  {
566  hc1Header.SetSrcPrefix (bufOne);
567  }
568  else
569  {
571  hc1Header.SetSrcInterface (bufOne + 8);
572  hc1Header.SetSrcPrefix (bufOne);
573  }
574 
575  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
576  dstAddr.GetBytes (bufOne);
577  Ipv6Address myDstAddr = MakeLinkLocalAddressFromMac (dst);
578 
579  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
580 
581  myDstAddr.GetBytes (bufTwo);
582  bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
583 
584  if (dstAddr.IsLinkLocal () && isDstDst )
585  {
587  }
588  else if (dstAddr.IsLinkLocal () )
589  {
591  hc1Header.SetDstInterface (bufOne + 8);
592  }
593  else if ( isDstDst )
594  {
596  hc1Header.SetDstPrefix (bufOne);
597  }
598  else
599  {
601  hc1Header.SetDstInterface (bufOne + 8);
602  hc1Header.SetDstPrefix (bufOne);
603  }
604 
605  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
606  {
607  hc1Header.SetTcflCompression (true);
608  }
609  else
610  {
611  hc1Header.SetTcflCompression (false);
612  hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
613  hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
614  }
615 
616  uint8_t nextHeader = ipHeader.GetNextHeader ();
617  hc1Header.SetNextHeader (nextHeader);
618 
619  // \todo implement HC2 compression
620  hc1Header.SetHc2HeaderPresent (false);
621 
622  NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
623  NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
624 
625  packet->AddHeader (hc1Header);
626 
627  return size;
628  }
629 
630  return 0;
631 }
632 
633 void
635 {
636  NS_LOG_FUNCTION (this << *packet << src << dst);
637 
638  Ipv6Header ipHeader;
639  SixLowPanHc1 encoding;
640 
641  uint32_t ret = packet->RemoveHeader (encoding);
642  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
643  NS_UNUSED (ret);
644 
645  ipHeader.SetHopLimit (encoding.GetHopLimit ());
646 
647  switch (encoding.GetSrcCompression ())
648  {
649  const uint8_t* interface;
650  const uint8_t* prefix;
651  uint8_t address[16];
652 
654  prefix = encoding.GetSrcPrefix ();
655  interface = encoding.GetSrcInterface ();
656  for (int j = 0; j < 8; j++)
657  {
658  address[j + 8] = interface[j];
659  address[j] = prefix[j];
660  }
661  ipHeader.SetSourceAddress ( Ipv6Address (address) );
662  break;
664  prefix = encoding.GetSrcPrefix ();
665  for (int j = 0; j < 8; j++)
666  {
667  address[j + 8] = 0;
668  address[j] = prefix[j];
669  }
670  ipHeader.SetSourceAddress ( MakeGlobalAddressFromMac (src, Ipv6Address (address)));
671  break;
673  interface = encoding.GetSrcInterface ();
674  address[0] = 0xfe;
675  address[1] = 0x80;
676  for (int j = 0; j < 8; j++)
677  {
678  address[j + 8] = interface[j];
679  }
680  ipHeader.SetSourceAddress ( Ipv6Address (address) );
681  break;
684  break;
685  }
686 
687  switch (encoding.GetDstCompression ())
688  {
689  const uint8_t* interface;
690  const uint8_t* prefix;
691  uint8_t address[16];
692 
694  prefix = encoding.GetDstPrefix ();
695  interface = encoding.GetDstInterface ();
696  for (int j = 0; j < 8; j++)
697  {
698  address[j + 8] = interface[j];
699  address[j] = prefix[j];
700  }
701  ipHeader.SetDestinationAddress ( Ipv6Address (address) );
702  break;
704  prefix = encoding.GetDstPrefix ();
705  for (int j = 0; j < 8; j++)
706  {
707  address[j + 8] = 0;
708  address[j] = prefix[j];
709  }
710  ipHeader.SetDestinationAddress ( MakeGlobalAddressFromMac (dst, Ipv6Address (address)));
711  break;
713  interface = encoding.GetDstInterface ();
714  address[0] = 0xfe;
715  address[1] = 0x80;
716  for (int j = 0; j < 8; j++)
717  {
718  address[j + 8] = interface[j];
719  }
720  ipHeader.SetDestinationAddress ( Ipv6Address (address) );
721  break;
724  break;
725  }
726 
727  if ( !encoding.IsTcflCompression () )
728  {
729  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
730  ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
731  }
732  else
733  {
734  ipHeader.SetFlowLabel (0);
735  ipHeader.SetTrafficClass (0);
736  }
737 
738  ipHeader.SetNextHeader (encoding.GetNextHeader ());
739 
740  ipHeader.SetPayloadLength (packet->GetSize ());
741 
742  NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
743  "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
744 
745  packet->AddHeader (ipHeader);
746 
747  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
748 }
749 
750 uint32_t
752 {
753  NS_LOG_FUNCTION (this << *packet << src << dst);
754 
755  Ipv6Header ipHeader;
756  SixLowPanIphc iphcHeader;
757  uint32_t size = 0;
758 
759 
760  if ( packet->PeekHeader (ipHeader) != 0 )
761  {
762  packet->RemoveHeader (ipHeader);
763  size += ipHeader.GetSerializedSize ();
764 
765  // Set the TF field
766  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
767  {
768  iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
769  }
770  else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
771  {
772  iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
773  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
774  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
775  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
776  }
777  else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
778  {
779  iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
780  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
781  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
782  }
783  else
784  {
786  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
787  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
788  }
789 
790  // Set the NH field and NextHeader
791 
792  uint8_t nextHeader = ipHeader.GetNextHeader ();
793  if (CanCompressLowPanNhc (nextHeader))
794  {
795  if (nextHeader == Ipv6Header::IPV6_UDP)
796  {
797  iphcHeader.SetNh (true);
798  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
799  }
800  else if (nextHeader == Ipv6Header::IPV6_IPV6)
801  {
802  iphcHeader.SetNh (true);
803  size += CompressLowPanIphc (packet, src, dst);
804  }
805  else
806  {
807  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
808  // the compression might fail due to Extension header size.
809  if (sizeNhc)
810  {
811  iphcHeader.SetNh (true);
812  size += sizeNhc;
813  }
814  else
815  {
816  iphcHeader.SetNh (false);
817  iphcHeader.SetNextHeader (nextHeader);
818  }
819  }
820  }
821  else
822  {
823  iphcHeader.SetNh (false);
824  iphcHeader.SetNextHeader (nextHeader);
825  }
826 
827 
828  // Set the HLIM field
829  if (ipHeader.GetHopLimit () == 1)
830  {
832  }
833  else if (ipHeader.GetHopLimit () == 0x40)
834  {
836  }
837  else if (ipHeader.GetHopLimit () == 0xFF)
838  {
840  }
841  else
842  {
843  iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
844  // Set the HopLimit
845  iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
846  }
847 
848  // \todo Add the check of CID if there is context-based compression
849  // Set the CID field
850  iphcHeader.SetCid (false);
851 
852  // \todo Add the check of SAC if there is context-based compression
853  // Set the SAC field
854  iphcHeader.SetSac (false);
855 
856  uint8_t addressBuf[16];
857  uint8_t unicastAddrCheckerBuf[16];
858  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
859  srcAddr.GetBytes (addressBuf);
860 
861  Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
862  checker.GetBytes (unicastAddrCheckerBuf);
863 
864  // \todo Add the check of SAC if there is context-based compression
865  // Set the Source Address
866  iphcHeader.SetSrcAddress (srcAddr);
867 
868  Ipv6Address mySrcAddr = MakeLinkLocalAddressFromMac (src);
869  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
870 
871  if ( mySrcAddr == srcAddr )
872  {
873  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
874  }
875  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
876  {
877  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
878  }
879  else if ( srcAddr.IsLinkLocal () )
880  {
881  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
882  }
883  else
884  {
885  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
886  }
887 
888  // Set the M field
889  if (ipHeader.GetDestinationAddress ().IsMulticast ())
890  {
891  iphcHeader.SetM (true);
892  }
893  else
894  {
895  iphcHeader.SetM (false);
896  }
897 
898  // \todo Add the check of DAC if there is context-based compression
899  // Set the DAC field
900  iphcHeader.SetDac (false);
901 
902  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
903  dstAddr.GetBytes (addressBuf);
904 
905  // \todo Add the check of DAC if there is context-based compression
906  // Set the Destination Address
907  iphcHeader.SetDstAddress (dstAddr);
908 
909  Ipv6Address myDstAddr = MakeLinkLocalAddressFromMac (dst);
910  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
911 
912  if ( !iphcHeader.GetM () )
913  // Unicast address
914  {
915  if ( myDstAddr == dstAddr )
916  {
917  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
918  }
919  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
920  {
921  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
922  }
923  else if ( dstAddr.IsLinkLocal () )
924  {
925  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
926  }
927  else
928  {
929  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
930  }
931  }
932  else
933  {
934  // Multicast address
935  uint8_t multicastAddrCheckerBuf[16];
936  Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
937  multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
938 
939  // The address takes the form ff02::00XX.
940  if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
941  {
942  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
943  }
944  // The address takes the form ffXX::00XX:XXXX.
945  // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
946  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
947  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) ) )
948  {
949  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
950  }
951  // The address takes the form ffXX::00XX:XXXX:XXXX.
952  // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
953  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
954  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) ) )
955  {
956  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
957  }
958  else
959  {
960  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
961  }
962  }
963 
964  NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
965  NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
966 
967  packet->AddHeader (iphcHeader);
968 
969  NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
970 
971  return size;
972  }
973 
974  return 0;
975 }
976 
977 bool
979 {
980  bool ret = false;
981 
982  switch (nextHeader)
983  {
989  ret = true;
990  break;
992  default:
993  ret = false;
994  }
995  return ret;
996 }
997 
998 void
1000 {
1001  NS_LOG_FUNCTION (this << *packet << src << dst);
1002 
1003  Ipv6Header ipHeader;
1004  SixLowPanIphc encoding;
1005 
1006  uint32_t ret = packet->RemoveHeader (encoding);
1007  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1008  NS_UNUSED (ret);
1009 
1010  // Hop Limit
1011  ipHeader.SetHopLimit (encoding.GetHopLimit ());
1012 
1013  // Source address
1014  if ( encoding.GetSac () )
1015  {
1016  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1017  {
1018  ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
1019  }
1020  else
1021  {
1022  NS_ABORT_MSG ("SAC option not yet implemented");
1023  }
1024  }
1025  else
1026  {
1027  if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_0 )
1028  {
1030  }
1031  else
1032  {
1033  ipHeader.SetSourceAddress ( encoding.GetSrcAddress () );
1034  }
1035  }
1036  // Destination address
1037  if ( encoding.GetDac () )
1038  {
1039  if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1040  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1041  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1042  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1043  {
1044  NS_ABORT_MSG ("Reserved code found");
1045  }
1046  else
1047  {
1048  NS_ABORT_MSG ("DAC option not yet implemented");
1049  }
1050  }
1051  else
1052  {
1053  if ( !encoding.GetM () && encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 )
1054  {
1056  }
1057  else
1058  {
1059  ipHeader.SetDestinationAddress ( encoding.GetDstAddress () );
1060  }
1061  }
1062 
1063  // Traffic class and Flow Label
1064  uint8_t traf = 0x00;
1065  switch (encoding.GetTf ())
1066  {
1068  traf |= encoding.GetEcn ();
1069  traf = ( traf << 6 ) | encoding.GetDscp ();
1070  ipHeader.SetTrafficClass (traf);
1071  ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1072  break;
1074  traf |= encoding.GetEcn ();
1075  traf <<= 2; // Add 2-bit pad
1076  ipHeader.SetTrafficClass (traf);
1077  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1078  break;
1080  traf |= encoding.GetEcn ();
1081  traf = ( traf << 6 ) | encoding.GetDscp ();
1082  ipHeader.SetTrafficClass (traf);
1083  ipHeader.SetFlowLabel (0);
1084  break;
1086  ipHeader.SetFlowLabel (0);
1087  ipHeader.SetTrafficClass (0);
1088  break;
1089  }
1090 
1091  if ( encoding.GetNh () )
1092  {
1093  // Next Header
1094  uint8_t dispatchRawVal = 0;
1096 
1097  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1098  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1099 
1100  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1101  {
1103  DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1104  }
1105  else
1106  {
1107  ipHeader.SetNextHeader (DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ()));
1108  }
1109  }
1110  else
1111  {
1112  ipHeader.SetNextHeader (encoding.GetNextHeader ());
1113  }
1114 
1115  ipHeader.SetPayloadLength (packet->GetSize ());
1116 
1117  packet->AddHeader (ipHeader);
1118 
1119  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1120 
1121 }
1122 
1123 uint32_t
1124 SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1125 {
1126  NS_LOG_FUNCTION (this << *packet << int(headerType));
1127 
1128  SixLowPanNhcExtension nhcHeader;
1129  uint32_t size = 0;
1130  Buffer blob;
1131 
1132  if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1133  {
1134  Ipv6ExtensionHopByHopHeader hopHeader;
1135  packet->PeekHeader (hopHeader);
1136  if (hopHeader.GetLength () >= 0xff)
1137  {
1138  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1139  "that have more than 255 octets following the Length field after compression. "
1140  "Packet uncompressed.");
1141  return 0;
1142  }
1143 
1144  size += packet->RemoveHeader (hopHeader);
1146 
1147  // recursively compress other headers
1148  uint8_t nextHeader = hopHeader.GetNextHeader ();
1149  if (CanCompressLowPanNhc (nextHeader))
1150  {
1151  if (nextHeader == Ipv6Header::IPV6_UDP)
1152  {
1153  nhcHeader.SetNh (true);
1154  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1155  }
1156  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1157  {
1158  nhcHeader.SetNh (true);
1159  size += CompressLowPanIphc (packet, src, dst);
1160  }
1161  else
1162  {
1163  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1164  // the compression might fail due to Extension header size.
1165  if (sizeNhc)
1166  {
1167  nhcHeader.SetNh (true);
1168  size += sizeNhc;
1169  }
1170  else
1171  {
1172  nhcHeader.SetNh (false);
1173  nhcHeader.SetNextHeader (nextHeader);
1174  }
1175  }
1176  }
1177  else
1178  {
1179  nhcHeader.SetNh (false);
1180  nhcHeader.SetNextHeader (nextHeader);
1181  }
1182 
1183  uint32_t blobSize = hopHeader.GetSerializedSize ();
1184  blob.AddAtStart (blobSize);
1185  hopHeader.Serialize (blob.Begin ());
1186  blob.RemoveAtStart (2);
1187  blobSize = blob.GetSize ();
1188  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1189  }
1190  else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1191  {
1192  Ipv6ExtensionRoutingHeader routingHeader;
1193  packet->PeekHeader (routingHeader);
1194  if (routingHeader.GetLength () >= 0xff)
1195  {
1196  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1197  "that have more than 255 octets following the Length field after compression. "
1198  "Packet uncompressed.");
1199  return 0;
1200  }
1201 
1202  size += packet->RemoveHeader (routingHeader);
1204 
1205  // recursively compress other headers
1206  uint8_t nextHeader = routingHeader.GetNextHeader ();
1207  if (CanCompressLowPanNhc (nextHeader))
1208  {
1209  if (nextHeader == Ipv6Header::IPV6_UDP)
1210  {
1211  nhcHeader.SetNh (true);
1212  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1213  }
1214  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1215  {
1216  nhcHeader.SetNh (true);
1217  size += CompressLowPanIphc (packet, src, dst);
1218  }
1219  else
1220  {
1221  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1222  // the compression might fail due to Extension header size.
1223  if (sizeNhc)
1224  {
1225  nhcHeader.SetNh (true);
1226  size += sizeNhc;
1227  }
1228  else
1229  {
1230  nhcHeader.SetNh (false);
1231  nhcHeader.SetNextHeader (nextHeader);
1232  }
1233  }
1234  }
1235  else
1236  {
1237  nhcHeader.SetNh (false);
1238  nhcHeader.SetNextHeader (nextHeader);
1239  }
1240 
1241  uint32_t blobSize = routingHeader.GetSerializedSize ();
1242  blob.AddAtStart (blobSize);
1243  routingHeader.Serialize (blob.Begin ());
1244  blob.RemoveAtStart (2);
1245  blobSize = blob.GetSize ();
1246  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1247  }
1248  else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1249  {
1250  Ipv6ExtensionFragmentHeader fragHeader;
1251  packet->PeekHeader (fragHeader);
1252  if (fragHeader.GetLength () >= 0xff)
1253  {
1254  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1255  "that have more than 255 octets following the Length field after compression. "
1256  "Packet uncompressed.");
1257  return 0;
1258  }
1259  size += packet->RemoveHeader (fragHeader);
1261 
1262  // recursively compress other headers
1263  uint8_t nextHeader = fragHeader.GetNextHeader ();
1264  if (CanCompressLowPanNhc (nextHeader))
1265  {
1266  if (nextHeader == Ipv6Header::IPV6_UDP)
1267  {
1268  nhcHeader.SetNh (true);
1269  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1270  }
1271  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1272  {
1273  nhcHeader.SetNh (true);
1274  size += CompressLowPanIphc (packet, src, dst);
1275  }
1276  else
1277  {
1278  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1279  // the compression might fail due to Extension header size.
1280  if (sizeNhc)
1281  {
1282  nhcHeader.SetNh (true);
1283  size += sizeNhc;
1284  }
1285  else
1286  {
1287  nhcHeader.SetNh (false);
1288  nhcHeader.SetNextHeader (nextHeader);
1289  }
1290  }
1291  }
1292  else
1293  {
1294  nhcHeader.SetNh (false);
1295  nhcHeader.SetNextHeader (nextHeader);
1296  }
1297 
1298  uint32_t blobSize = fragHeader.GetSerializedSize ();
1299  blob.AddAtStart (blobSize);
1300  fragHeader.Serialize (blob.Begin ());
1301  blob.RemoveAtStart (2);
1302  blobSize = blob.GetSize ();
1303  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1304  }
1305  else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1306  {
1307  Ipv6ExtensionDestinationHeader destHeader;
1308  packet->PeekHeader (destHeader);
1309  if (destHeader.GetLength () >= 0xff)
1310  {
1311  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1312  "that have more than 255 octets following the Length field after compression. "
1313  "Packet uncompressed.");
1314  return 0;
1315  }
1316  size += packet->RemoveHeader (destHeader);
1318 
1319  // recursively compress other headers
1320  uint8_t nextHeader = destHeader.GetNextHeader ();
1321  if (CanCompressLowPanNhc (nextHeader))
1322  {
1323  if (nextHeader == Ipv6Header::IPV6_UDP)
1324  {
1325  nhcHeader.SetNh (true);
1326  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1327  }
1328  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1329  {
1330  nhcHeader.SetNh (true);
1331  size += CompressLowPanIphc (packet, src, dst);
1332  }
1333  else
1334  {
1335  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1336  // the compression might fail due to Extension header size.
1337  if (sizeNhc)
1338  {
1339  nhcHeader.SetNh (true);
1340  size += sizeNhc;
1341  }
1342  else
1343  {
1344  nhcHeader.SetNh (false);
1345  nhcHeader.SetNextHeader (nextHeader);
1346  }
1347  }
1348  }
1349  else
1350  {
1351  nhcHeader.SetNh (false);
1352  nhcHeader.SetNextHeader (nextHeader);
1353  }
1354 
1355  uint32_t blobSize = destHeader.GetSerializedSize ();
1356  blob.AddAtStart (blobSize);
1357  destHeader.Serialize (blob.Begin ());
1358  blob.RemoveAtStart (2);
1359  blobSize = blob.GetSize ();
1360  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1361  }
1362  else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1363  {
1364  // \todo: IPv6 Mobility Header is not supported in ns-3
1365  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1366  return 0;
1367  }
1368  else
1369  {
1370  NS_ABORT_MSG ("Unexpected Extension Header");
1371  }
1372 
1373  NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1374  NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1375 
1376  packet->AddHeader (nhcHeader);
1377 
1378  NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1379  return size;
1380 }
1381 
1382 uint8_t
1383 SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1384 {
1385  NS_LOG_FUNCTION (this << *packet);
1386 
1387  SixLowPanNhcExtension encoding;
1388 
1389  uint32_t ret = packet->RemoveHeader (encoding);
1390  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1391  NS_UNUSED (ret);
1392 
1393  Ipv6ExtensionHopByHopHeader hopHeader;
1394  Ipv6ExtensionRoutingHeader routingHeader;
1395  Ipv6ExtensionFragmentHeader fragHeader;
1396  Ipv6ExtensionDestinationHeader destHeader;
1397 
1398  uint32_t blobSize;
1399  uint8_t blobData[260];
1400  blobSize = encoding.CopyBlob (blobData + 2, 260);
1401  uint8_t paddingSize = 0;
1402 
1403  uint8_t actualEncodedHeaderType = encoding.GetEid ();
1404  uint8_t actualHeaderType;
1405  Buffer blob;
1406 
1407  switch (actualEncodedHeaderType)
1408  {
1410  actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1411  if ( encoding.GetNh () )
1412  {
1413  // Next Header
1414  uint8_t dispatchRawVal = 0;
1416 
1417  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1418  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1419 
1420  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1421  {
1422  blobData [0] = Ipv6Header::IPV6_UDP;
1423  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1424  }
1425  else
1426  {
1427  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1428  }
1429  }
1430  else
1431  {
1432  blobData [0] = encoding.GetNextHeader ();
1433  }
1434 
1435  // manually add some padding if needed
1436  if ((blobSize + 2) % 8 > 0)
1437  {
1438  paddingSize = 8 - (blobSize + 2) % 8;
1439  }
1440  if (paddingSize == 1)
1441  {
1442  blobData[blobSize + 2] = 0;
1443  }
1444  else if (paddingSize > 1)
1445  {
1446  blobData[blobSize + 2] = 1;
1447  blobData[blobSize + 2 + 1] = paddingSize - 2;
1448  for (uint8_t i = 0; i < paddingSize - 2; i++)
1449  {
1450  blobData[blobSize + 2 + 2 + i] = 0;
1451  }
1452  }
1453  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1454  blob.AddAtStart (blobSize + 2 + paddingSize);
1455  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1456  hopHeader.Deserialize (blob.Begin ());
1457 
1458  packet->AddHeader (hopHeader);
1459  break;
1460 
1462  actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1463  if ( encoding.GetNh () )
1464  {
1465  // Next Header
1466  uint8_t dispatchRawVal = 0;
1468 
1469  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1470  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1471 
1472  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1473  {
1474  blobData [0] = Ipv6Header::IPV6_UDP;
1475  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1476  }
1477  else
1478  {
1479  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1480  }
1481  }
1482  else
1483  {
1484  blobData [0] = encoding.GetNextHeader ();
1485  }
1486  blobData [1] = ((blobSize + 2) >> 3) - 1;
1487  blob.AddAtStart (blobSize + 2);
1488  blob.Begin ().Write (blobData, blobSize + 2);
1489  routingHeader.Deserialize (blob.Begin ());
1490  packet->AddHeader (routingHeader);
1491  break;
1492 
1494  actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
1495  if ( encoding.GetNh () )
1496  {
1497  // Next Header
1498  uint8_t dispatchRawVal = 0;
1500 
1501  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1502  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1503 
1504  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1505  {
1506  blobData [0] = Ipv6Header::IPV6_UDP;
1507  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1508  }
1509  else
1510  {
1511  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1512  }
1513  }
1514  else
1515  {
1516  blobData [0] = encoding.GetNextHeader ();
1517  }
1518  blobData [1] = 0;
1519  fragHeader.Deserialize (blob.Begin ());
1520  packet->AddHeader (fragHeader);
1521  break;
1522 
1524  actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
1525  if ( encoding.GetNh () )
1526  {
1527  // Next Header
1528  uint8_t dispatchRawVal = 0;
1530 
1531  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1532  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1533 
1534  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1535  {
1536  blobData [0] = Ipv6Header::IPV6_UDP;
1537  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1538  }
1539  else
1540  {
1541  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1542  }
1543  }
1544  else
1545  {
1546  blobData [0] = encoding.GetNextHeader ();
1547  }
1548 
1549  // manually add some padding if needed
1550  if ((blobSize + 2) % 8 > 0)
1551  {
1552  paddingSize = 8 - (blobSize + 2) % 8;
1553  }
1554  if (paddingSize == 1)
1555  {
1556  blobData[blobSize + 2] = 0;
1557  }
1558  else if (paddingSize > 1)
1559  {
1560  blobData[blobSize + 2] = 1;
1561  blobData[blobSize + 2 + 1] = paddingSize - 2;
1562  for (uint8_t i = 0; i < paddingSize - 2; i++)
1563  {
1564  blobData[blobSize + 2 + 2 + i] = 0;
1565  }
1566  }
1567  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1568  blob.AddAtStart (blobSize + 2 + paddingSize);
1569  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1570  destHeader.Deserialize (blob.Begin ());
1571 
1572  packet->AddHeader (destHeader);
1573  break;
1575  // \todo: IPv6 Mobility Header is not supported in ns-3
1576  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1577  break;
1579  actualHeaderType = Ipv6Header::IPV6_IPV6;
1580  DecompressLowPanIphc (packet, src, dst);
1581  break;
1582  default:
1583  NS_ABORT_MSG ("Trying to decode unknown Extension Header");
1584  break;
1585  }
1586 
1587  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1588  return actualHeaderType;
1589 }
1590 
1591 uint32_t
1593 {
1594  NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
1595 
1596  UdpHeader udpHeader;
1597  SixLowPanUdpNhcExtension udpNhcHeader;
1598  uint32_t size = 0;
1599 
1600  NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
1601 
1602  size += packet->RemoveHeader (udpHeader);
1603 
1604  // Set the C field and checksum
1605  udpNhcHeader.SetC (false);
1606  uint16_t checksum = udpHeader.GetChecksum ();
1607  udpNhcHeader.SetChecksum (checksum);
1608 
1609  if (omitChecksum && udpHeader.IsChecksumOk ())
1610  {
1611  udpNhcHeader.SetC (true);
1612  }
1613 
1614  // Set the value of the ports
1615  udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
1616  udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
1617 
1618  //Set the P field
1619  if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
1620  {
1622  }
1623  else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
1624  {
1626  }
1627  else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
1628  {
1630  }
1631  else
1632  {
1634  }
1635 
1636  NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
1637  NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
1638 
1639  packet->AddHeader (udpNhcHeader);
1640 
1641  NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
1642 
1643  return size;
1644 }
1645 
1646 void
1648 {
1649  NS_LOG_FUNCTION (this << *packet);
1650 
1651  UdpHeader udpHeader;
1652  SixLowPanUdpNhcExtension encoding;
1653 
1654  uint32_t ret = packet->RemoveHeader (encoding);
1655  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1656  NS_UNUSED (ret);
1657 
1658  // Set the value of the ports
1659  switch ( encoding.GetPorts () )
1660  {
1661  uint16_t temp;
1663  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1664  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1665  break;
1667  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1668  temp = 0xf0;
1669  temp |= (temp << 8) | encoding.GetDstPort ();
1670  udpHeader.SetDestinationPort (temp);
1671  break;
1673  temp = 0xf0;
1674  temp |= (temp << 8) | encoding.GetSrcPort ();
1675  udpHeader.SetSourcePort (temp);
1676  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1677  break;
1679  temp = 0xf0b;
1680  temp |= (temp << 4) | encoding.GetSrcPort ();
1681  udpHeader.SetSourcePort (temp);
1682  temp = 0xf0b;
1683  temp |= (temp << 4) | encoding.GetDstPort ();
1684  udpHeader.SetDestinationPort (temp);
1685  break;
1686  }
1687 
1688  // Get the C field and checksum
1689  if (Node::ChecksumEnabled ())
1690  {
1691  if ( encoding.GetC () )
1692  {
1693  NS_LOG_LOGIC ("Recalculating UDP Checksum");
1694  udpHeader.EnableChecksums ();
1695  udpHeader.InitializeChecksum (saddr,
1696  daddr,
1698  packet->AddHeader (udpHeader);
1699  }
1700  else
1701  {
1702  NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
1703  udpHeader.ForceChecksum (encoding.GetChecksum ());
1704  packet->AddHeader (udpHeader);
1705  NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
1706  }
1707  }
1708  else
1709  {
1710  packet->AddHeader (udpHeader);
1711  }
1712 
1713  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1714 }
1715 
1717  uint32_t origPacketSize,
1718  uint32_t origHdrSize,
1719  std::list<Ptr<Packet> >& listFragments)
1720 {
1721  NS_LOG_FUNCTION (this << *packet);
1722 
1723  Ptr<Packet> p = packet->Copy ();
1724 
1725  uint16_t offsetData = 0;
1726  uint16_t offset = 0;
1727  uint16_t l2Mtu = m_netDevice->GetMtu ();
1728  uint32_t packetSize = packet->GetSize ();
1729  uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
1730 
1731  uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
1732  NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
1733 
1734  // first fragment
1735  SixLowPanFrag1 frag1Hdr;
1736  frag1Hdr.SetDatagramTag (tag);
1737 
1738  uint32_t size;
1739  NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
1740  "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
1741 
1742  size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize;
1743  size -= size % 8;
1744  size += compressedHeaderSize;
1745 
1746  frag1Hdr.SetDatagramSize (origPacketSize);
1747 
1748  Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
1749  offset += size + origHdrSize - compressedHeaderSize;
1750  offsetData += size;
1751 
1752  fragment1->AddHeader (frag1Hdr);
1753  listFragments.push_back (fragment1);
1754 
1755  bool moreFrag = true;
1756  do
1757  {
1758  SixLowPanFragN fragNHdr;
1759  fragNHdr.SetDatagramTag (tag);
1760  fragNHdr.SetDatagramSize (origPacketSize);
1761  fragNHdr.SetDatagramOffset ((offset) >> 3);
1762 
1763  size = l2Mtu - fragNHdr.GetSerializedSize ();
1764  size -= size % 8;
1765 
1766  if ( (offsetData + size) > packetSize )
1767  {
1768  size = packetSize - offsetData;
1769  moreFrag = false;
1770  }
1771 
1772  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
1773  Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
1774  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1775 
1776  offset += size;
1777  offsetData += size;
1778 
1779  fragment->AddHeader (fragNHdr);
1780  listFragments.push_back (fragment);
1781 
1782  }
1783  while (moreFrag);
1784 
1785  return;
1786 }
1787 
1788 bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
1789 {
1790  NS_LOG_FUNCTION ( this << *packet );
1791  SixLowPanFrag1 frag1Header;
1792  SixLowPanFragN fragNHeader;
1793  FragmentKey key;
1794  uint16_t packetSize;
1795  key.first = std::pair<Address, Address> (src, dst);
1796 
1797  Ptr<Packet> p = packet->Copy ();
1798  uint16_t offset = 0;
1799 
1800  /* Implementation note:
1801  *
1802  * The fragment offset is relative to the *uncompressed* packet.
1803  * On the other hand, the packet can not be uncompressed correctly without all
1804  * its fragments, as the UDP checksum can not be computed otherwise.
1805  *
1806  * As a consequence we must uncompress the packet twice, and save its first
1807  * fragment for the final one.
1808  */
1809 
1810  if ( isFirst )
1811  {
1812  uint8_t dispatchRawValFrag1 = 0;
1813  SixLowPanDispatch::Dispatch_e dispatchValFrag1;
1814 
1815  p->RemoveHeader (frag1Header);
1816  packetSize = frag1Header.GetDatagramSize ();
1817  p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
1818  dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
1819  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
1820  NS_LOG_DEBUG ( "Packet: " << *p );
1821 
1822  switch ( dispatchValFrag1 )
1823  {
1825  {
1826  SixLowPanIpv6 uncompressedHdr;
1827  p->RemoveHeader(uncompressedHdr);
1828  }
1829  break;
1831  DecompressLowPanHc1 (p, src, dst);
1832  break;
1834  DecompressLowPanIphc (p, src, dst);
1835  break;
1836  default:
1837  NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
1838  break;
1839  }
1840 
1841  key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
1842  }
1843  else
1844  {
1845  p->RemoveHeader (fragNHeader);
1846  packetSize = fragNHeader.GetDatagramSize ();
1847  offset = fragNHeader.GetDatagramOffset () << 3;
1848  key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
1849  }
1850 
1851  Ptr<Fragments> fragments;
1852 
1853  MapFragments_t::iterator it = m_fragments.find (key);
1854  if (it == m_fragments.end ())
1855  {
1856  // erase the oldest packet.
1858  {
1859  MapFragmentsTimers_t::iterator iter;
1860  MapFragmentsTimers_t::iterator iterFound = m_fragmentsTimers.begin ();
1861  for ( iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
1862  {
1863  if ( iter->second.GetTs () < iterFound->second.GetTs () )
1864  {
1865  iterFound = iter;
1866  }
1867  }
1868  FragmentKey oldestKey = iterFound->first;
1869 
1870  std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
1871  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
1872  fragIter != storedFragments.end (); fragIter++)
1873  {
1875  }
1876 
1877  m_fragmentsTimers[oldestKey].Cancel ();
1878  m_fragmentsTimers.erase (oldestKey);
1879  m_fragments[oldestKey] = 0;
1880  m_fragments.erase (oldestKey);
1881 
1882  }
1883  fragments = Create<Fragments> ();
1884  fragments->SetPacketSize (packetSize);
1885  m_fragments.insert (std::make_pair (key, fragments));
1886  uint32_t ifIndex = GetIfIndex ();
1889  key, ifIndex);
1890  }
1891  else
1892  {
1893  fragments = it->second;
1894  }
1895 
1896  fragments->AddFragment (p, offset);
1897 
1898  // add the very first fragment so we can correctly decode the packet once is rebuilt.
1899  // this is needed because otherwise the UDP header length and checksum can not be calculated.
1900  if ( isFirst )
1901  {
1902  fragments->AddFirstFragment (packet);
1903  }
1904 
1905  if ( fragments->IsEntire () )
1906  {
1907  packet = fragments->GetPacket ();
1908  NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
1909 
1910  SixLowPanFrag1 frag1Header;
1911  packet->RemoveHeader (frag1Header);
1912 
1913  NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
1914  fragments = 0;
1915  m_fragments.erase (key);
1916  if (m_fragmentsTimers[key].IsRunning ())
1917  {
1918  NS_LOG_LOGIC ("Stopping 6LoWPAN WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1919  m_fragmentsTimers[key].Cancel ();
1920  }
1921  m_fragmentsTimers.erase (key);
1922  return true;
1923  }
1924 
1925  return false;
1926 }
1927 
1929 {
1930  NS_LOG_FUNCTION (this);
1931  m_packetSize = 0;
1932 }
1933 
1935 {
1936  NS_LOG_FUNCTION (this);
1937 }
1938 
1939 void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
1940 {
1941  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
1942 
1943  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1944  bool duplicate = false;
1945 
1946  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1947  {
1948  if (it->second > fragmentOffset)
1949  {
1950  break;
1951  }
1952  if (it->second == fragmentOffset)
1953  {
1954  duplicate = true;
1955  NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
1956  break;
1957  }
1958  }
1959  if (!duplicate)
1960  {
1961  m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
1962  }
1963 }
1964 
1966 {
1967  NS_LOG_FUNCTION (this << *fragment);
1968 
1969  m_firstFragment = fragment;
1970 }
1971 
1973 {
1974  NS_LOG_FUNCTION (this);
1975 
1976  bool ret = m_fragments.size () > 0;
1977  uint16_t lastEndOffset = 0;
1978 
1979  if (ret)
1980  {
1981  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1982  {
1983  // overlapping fragments should not exist
1984  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1985 
1986  if (lastEndOffset < it->second)
1987  {
1988  ret = false;
1989  break;
1990  }
1991  // fragments might overlap in strange ways
1992  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1993  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1994  }
1995  }
1996 
1997  if ( ret && (lastEndOffset == m_packetSize))
1998  {
1999  return true;
2000  }
2001  return false;
2002 }
2003 
2005 {
2006  NS_LOG_FUNCTION (this);
2007 
2008  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2009 
2010  Ptr<Packet> p = Create<Packet> ();
2011  uint16_t lastEndOffset = 0;
2012 
2013  p->AddAtEnd (m_firstFragment);
2014  it = m_fragments.begin ();
2015  lastEndOffset = it->first->GetSize ();
2016 
2017  for ( it++; it != m_fragments.end (); it++)
2018  {
2019  if ( lastEndOffset > it->second )
2020  {
2021  NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2022  }
2023  else
2024  {
2025  NS_LOG_LOGIC ("Adding: " << *(it->first) );
2026  p->AddAtEnd (it->first);
2027  }
2028  lastEndOffset += it->first->GetSize ();
2029  }
2030 
2031  return p;
2032 }
2033 
2035 {
2036  NS_LOG_FUNCTION (this << packetSize);
2037  m_packetSize = packetSize;
2038 }
2039 
2040 std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2041 {
2042  std::list< Ptr<Packet> > fragments;
2043  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2044  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter ++)
2045  {
2046  fragments.push_back (iter->first);
2047  }
2048  return fragments;
2049 }
2050 
2052 {
2053  NS_LOG_FUNCTION (this);
2054 
2055  MapFragments_t::iterator it = m_fragments.find (key);
2056  std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2057  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2058  fragIter != storedFragments.end (); fragIter++)
2059  {
2061  }
2062  // clear the buffers
2063  it->second = 0;
2064 
2065  m_fragments.erase (key);
2066  m_fragmentsTimers.erase (key);
2067 }
2068 
2070 {
2071  Ipv6Address ipv6Addr = Ipv6Address::GetAny ();
2072 
2074  {
2076  }
2077  else
2078  {
2079  if (Mac64Address::IsMatchingType (addr))
2080  {
2082  }
2083  else if (Mac16Address::IsMatchingType (addr))
2084  {
2086  }
2087  }
2088  if (ipv6Addr.IsAny ())
2089  {
2090  NS_ABORT_MSG ("Unknown address type");
2091  }
2092  return ipv6Addr;
2093 }
2094 
2096 {
2097  Ipv6Address ipv6Addr = Ipv6Address::GetAny ();
2098 
2100  {
2102  }
2103  else
2104  {
2105  if (Mac64Address::IsMatchingType (addr))
2106  {
2108  }
2109  else if (Mac16Address::IsMatchingType (addr))
2110  {
2112  }
2113  }
2114  if (ipv6Addr.IsAny ())
2115  {
2116  NS_ABORT_MSG ("Unknown address type");
2117  }
2118  return ipv6Addr;
2119 }
2120 
2121 }
2122 
2123 // namespace ns3
bool IsAny() const
If the IPv6 address is the "Any" address.
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:51
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
uint8_t GetNextHeader(void) const
Get the Next Header field.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
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.
Definition: ipv6-header.cc:81
Ports_e GetPorts(void) const
Get the compressed Src and Dst Ports.
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:66
NhcDispatch_e
Dispatch values for Next Header compression.
void SetTcflCompression(bool tcflCompression)
Set the Traffic Class and Flow Labels as compressed.
Doxygen introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint8_t GetNextHeader() const
Get the Next Header value.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
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...
Hold a bool native type.
Definition: boolean.h:38
void SetHopLimit(uint8_t hopLimit)
Set the Hop Limit field.
#define NS_ABORT_MSG(msg)
Abnormal program termination.
Definition: abort.h:44
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 the class in the ns-3 factory.
Definition: object-base.h:38
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
6LoWPAN IPv6 uncomprssed header - see RFC 4944
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:456
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
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 bool IsMatchingType(const Address &address)
Doxygen introspection did not find any typical Config paths.
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static bool ChecksumEnabled(void)
Definition: node.cc:268
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
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:393
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual bool IsMulticast(void) const
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1018
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
uint16_t GetDatagramSize(void) const
Get the datagram size.
static TypeId GetTypeId(void)
Get the type ID.
static Ipv6Address MakeAutoconfiguredAddress(Mac16Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address with Mac16Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
uint16_t GetDatagramSize(void) const
Get the datagram size.
virtual Ptr< Channel > GetChannel(void) const
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:76
LOWPAN_NHC Extension Header Encoding - see RFC 6282.
std::pair< std::pair< Address, Address >, std::pair< uint16_t, uint16_t > > FragmentKey
Fragment identifier type: src/dst address src/dst port.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
uint16_t m_fragmentReassemblyListSize
How many packets can be rebuilt at the same time.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
void SetDatagramOffset(uint8_t datagramOffset)
Set the datagram offset.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
void SetSam(HeaderCompression_e samField)
Set the SAM (Source Address Mode) compression.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
6LoWPAN FRAGN header - see RFC 4944
TrafficClassFlowLabel_e GetTf(void) const
Get the TF (Traffic Class, Flow Label) compression.
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
bool IsChecksumOk(void) const
Is the UDP checksum correct ?
Definition: udp-header.cc:136
virtual bool SetMtu(const uint16_t mtu)
void SetNetDevice(Ptr< NetDevice > device)
Setup SixLowPan to be a proxy for the specified NetDevice.
bool IsTcflCompression() const
Check if the Traffic Class and Flow Labels are compressed.
bool GetM(void) const
Get the M (Multicast) compression.
void SetTrafficClass(uint8_t trafficClass)
Set the Traffic Class value.
Doxygen introspection did not find any typical Config paths.
a polymophic address class
Definition: address.h:86
uint16_t GetDstPort() const
Get the Destination Port.
bool GetNh(void) const
Get the Next Header field value.
std::map< FragmentKey, EventId >::iterator MapFragmentsTimersI_t
Container Iterator for fragment key -> exiration event.
void ForceChecksum(uint16_t checksum)
Force the UDP checksum to a given value.
Definition: udp-header.cc:142
uint8_t GetDscp(void) const
Get the DSCP.
void SetHlim(Hlim_e hlimField)
Set the HLIM (Hop Limit) compression.
virtual uint32_t GetIfIndex(void) const
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:228
uint32_t CompressLowPanNhc(Ptr< Packet > packet, uint8_t headerType, Address const &src, Address const &dst)
Compress the headers according to NHC compression.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
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:317
Ptr< Node > m_node
Smart pointer to the Node.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
Ipv6Address GetSrcAddress() const
Get the Source Address.
uint16_t GetSrcPort() const
Get the Destination Port.
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.
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
hold objects of type ns3::Time
Definition: nstime.h:1008
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:49
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
uint8_t GetTrafficClass() const
Get the Traffic Class value.
Hold an unsigned integer type.
Definition: uinteger.h:46
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
void SetSac(bool sacField)
Set the SAC (Source Address Compression) compression.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
bool IsHc2HeaderPresent() const
Check if there is a HC2 compressed header.
Ptr< NetDevice > GetNetDevice() const
Returns a smart pointer to the underlying NetDevice.
uint32_t GetFlowLabel(void) const
Get the "Flow label" field.
Definition: ipv6-header.cc:61
uint8_t const * PeekData(void) const
Definition: buffer.cc:733
void SetNh(bool nhField)
Set the NH (Next Header) compression.
Ipv6Address GetDstAddress() const
Get the Destination Address.
void SetChecksum(uint16_t checksum)
Set the Checksum field values.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
uint8_t GetHopLimit(void) const
Get the Hop Limit field.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1242
LowPanHc1Addr_e GetDstCompression() const
Get Destination Compression type.
uint8_t GetEcn(void) const
Get the ECN.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
void SetDstPort(uint16_t port)
Set the Destination Port.
virtual bool IsLinkUp(void) const
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
bool GetNh(void) const
Get the NH (Next Header) compression.
HeaderCompression_e GetDam(void) const
Get the DAM (Destination Address Mode) compression.
TracedCallback< DropReason, Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_dropTrace
Callback to trace drop packets.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
Buffer::Iterator Begin(void) const
Definition: buffer.h:1076
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
#define list
void SetSrcPort(uint16_t port)
Set the Destination Port.
HeaderCompression_e GetSam(void) const
Get the SAM (Source Address Mode) compression.
static Mac48Address ConvertFrom(const Address &address)
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint16_t GetChecksum()
Return the checksum (only known after a Deserialize)
Definition: udp-header.cc:240
Time m_fragmentExpirationTimeout
Time limit for fragment rebuilding.
virtual bool NeedsArp(void) const
virtual bool IsBroadcast(void) const
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
bool m_forceEtherType
Force the EtherType number.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:277
std::map< FragmentKey, Ptr< Fragments > >::iterator MapFragmentsI_t
Container Iterator for fragment key -> fragments.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:91
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual void SetNode(Ptr< Node > node)
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field.
std::list< Ptr< Packet > > GetFraments() const
Get a list of the current stored fragments.
uint32_t m_compressionThreshold
Minimum L2 payload size.
Shim performing 6LoWPAN compression, decompression and fragmentation.
uint32_t GetFlowLabel() const
Get the Flow Label value.
Ipv6Address MakeLinkLocalAddressFromMac(Address const &addr)
make a link-local address from a MAC address.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
bool IsEntire() const
If all fragments have been added.
bool GetC(void) const
Get the C (Checksum).
virtual Ptr< Node > GetNode(void) const
MapFragmentsTimers_t m_fragmentsTimers
Timers related to fragment rebuilding.
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
virtual Address GetBroadcast(void) const
Packet header for UDP packets.
Definition: udp-header.h:39
bool GetSac(void) const
Get the SAC (Source Address Compression) compression.
virtual void AddLinkChangeCallback(Callback< void > callback)
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
void SetSrcAddress(Ipv6Address srcAddress)
Set the Source Address.
bool GetDac(void) const
Get the DAC (Destination Address Compression) compression.
const uint8_t * GetDstPrefix() const
Get the destination prefix.
void DoFragmentation(Ptr< Packet > packet, uint32_t origPacketSize, uint32_t origHdrSize, std::list< Ptr< Packet > > &listFragments)
Return the instance type identifier.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
uint32_t GetSize(void) const
Definition: buffer.h:1070
uint8_t GetNextHeader(void) const
Get the Next Header field value.
6LoWPAN HC1 header - see RFC 4944
virtual bool IsBridge(void) const
Return true if the net device is acting as a bridge.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Ptr< Packet > GetPacket() const
Get the entire packet.
void SetDac(bool dacField)
Set the DAC (Destination Address Compression) compression.
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:219
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
#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:84
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:96
void SetSrcInterface(const uint8_t *srcInterface)
Set the source interface.
uint16_t m_etherType
EtherType number (used only if m_forceEtherType is true)
uint8_t GetNextHeader() const
Get the next header.
void SetDstPrefix(const uint8_t *dstPrefix)
Set the destination prefix.
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Mac16Address mac)
Make the autoconfigured link-local IPv6 address with Mac16Address.
Describes an IPv6 address.
Definition: ipv6-address.h:46
void DecompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Decompress the headers according to IPHC compression.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
SixLowPanNetDevice()
Constructor for the SixLowPanNetDevice.
Ipv6Address MakeGlobalAddressFromMac(Address const &addr, Ipv6Address prefix)
make a global address from a MAC address.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:86
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label (20bits).
Eid_e GetEid(void) const
Get the Extension Header Type.
uint32_t GetId(void) const
Definition: node.cc:106
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.
static Mac64Address ConvertFrom(const Address &address)
Network layer to device interface.
Definition: net-device.h:75
virtual bool SupportsSendFrom() const
const uint8_t * GetSrcPrefix() const
Get the source prefix.
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
Doxygen introspection did not find any typical Config paths.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
virtual Address GetAddress(void) const
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:213
void SetFlowLabel(uint32_t flow)
Set the "Flow label" field.
Definition: ipv6-header.cc:56
uint32_t GetFlowLabel(void) const
Get the Flow Label.
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetEid(Eid_e extensionHeaderType)
Set the Extension Header Type.
Doxygen introspection did not find any typical Config paths.
bool CanCompressLowPanNhc(uint8_t headerType)
Checks if the next header can be compressed using NHC.
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:982
bool m_omitUdpChecksum
Omit UDP checksum in NC1 encoding.
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:441
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
Definition: ipv6-header.cc:46
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:381
virtual uint16_t GetMtu(void) const
Returns the link-layer MTU for this interface.
void SetNh(bool nhField)
Set the NH field values.
void SetTf(TrafficClassFlowLabel_e tfField)
Set the TF (Traffic Class, Flow Label) compression.
#define NS_UNUSED(x)
Definition: unused.h:5
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
Dispatch_e
Dispatch values, as defined in RFC4944 and RFC6282.
uint32_t CopyBlob(uint8_t *blob, uint32_t size) const
Get the option header data blob.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
void SetDstAddress(Ipv6Address dstAddress)
Set the Destination Address.
Ptr< NetDevice > m_netDevice
Smart pointer to the underlying NetDevice.
void HandleFragmentsTimeout(FragmentKey key, uint32_t iif)
Process the timeout for packet fragments.
bool AddAtStart(uint32_t start)
Definition: buffer.cc:309
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset)
Add a fragment to the pool.
tuple address
Definition: first.py:37
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:274
void SetSrcPrefix(const uint8_t *srcPrefix)
Set the source prefix.
uint16_t GetLength() const
Get the length of the extension.
static bool IsMatchingType(const Address &address)
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
void SetEcn(uint8_t ecn)
Set the ECN (2bits).
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.
uint8_t GetDatagramOffset(void) const
Get the datagram offset.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
Ptr< T > GetObject(void) const
Definition: object.h:362
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
LowPanHc1Addr_e GetSrcCompression() const
Get Source Compression type.
a unique identifier for an interface.
Definition: type-id.h:49
static const uint8_t PROT_NUMBER
protocol number (0x11)
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
uint32_t m_ifIndex
Interface index.
UDP LOWPAN_NHC Extension Header Encoding - see RFC 6282.
void SetC(bool cField)
Set the C (Checksum).
uint8_t DecompressLowPanNhc(Ptr< Packet > packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
Decompress the headers according to NHC compression.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
virtual void SetAddress(Address address)
Set the address of this interface.
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.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
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 SetFlowLabel(uint32_t flowLabel)
Set the Flow Label value.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
uint16_t GetChecksum(void) const
Get the Checksum field value.