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