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