A Discrete-Event Network Simulator
API
sixlowpan-net-device.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 Universita' di Firenze, Italy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19  * Michele Muccio <michelemuccio@virgilio.it>
20  */
21 
22 #include <algorithm>
23 
24 #include "ns3/node.h"
25 #include "ns3/channel.h"
26 #include "ns3/packet.h"
27 #include "ns3/log.h"
28 #include "ns3/boolean.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/simulator.h"
31 #include "ns3/mac16-address.h"
32 #include "ns3/mac48-address.h"
33 #include "ns3/mac64-address.h"
34 #include "ns3/ipv6-l3-protocol.h"
35 #include "ns3/ipv6-extension-header.h"
36 #include "ns3/udp-header.h"
37 #include "ns3/udp-l4-protocol.h"
38 #include "ns3/string.h"
39 #include "ns3/pointer.h"
40 #include "sixlowpan-net-device.h"
41 #include "sixlowpan-header.h"
42 
43 NS_LOG_COMPONENT_DEFINE ("SixLowPanNetDevice");
44 
45 namespace ns3 {
46 
47 NS_OBJECT_ENSURE_REGISTERED (SixLowPanNetDevice);
48 
50 {
51  static TypeId tid = TypeId ("ns3::SixLowPanNetDevice")
52  .SetParent<NetDevice> ()
53  .SetGroupName ("SixLowPan")
54  .AddConstructor<SixLowPanNetDevice> ()
55  .AddAttribute ("Rfc6282", "Use RFC6282 (IPHC) if true, RFC4944 (HC1) otherwise.",
56  BooleanValue (true),
59  .AddAttribute ("OmitUdpChecksum",
60  "Omit the UDP checksum in IPHC compression.",
61  BooleanValue (true),
64  .AddAttribute ("FragmentReassemblyListSize", "The maximum size of the reassembly buffer (in packets). Zero meaning infinite.",
65  UintegerValue (0),
67  MakeUintegerChecker<uint16_t> ())
68  .AddAttribute ("FragmentExpirationTimeout",
69  "When this timeout expires, the fragments will be cleared from the buffer.",
70  TimeValue (Seconds (60)),
72  MakeTimeChecker ())
73  .AddAttribute ("CompressionThreshold",
74  "The minimum MAC layer payload size.",
75  UintegerValue (0x0),
77  MakeUintegerChecker<uint32_t> ())
78  .AddAttribute ("ForceEtherType",
79  "Force a specific EtherType in L2 frames.",
80  BooleanValue (false),
83  .AddAttribute ("EtherType",
84  "The specific EtherType to be used in L2 frames.",
85  UintegerValue (0xFFFF),
87  MakeUintegerChecker<uint16_t> ())
88  .AddAttribute ("UseMeshUnder",
89  "Use a mesh-under routing protocol.",
90  BooleanValue (false),
93  .AddAttribute ("MeshUnderRadius",
94  "Hops Left to use in mesh-under.",
95  UintegerValue (10),
97  MakeUintegerChecker<uint8_t> ())
98  .AddAttribute ("MeshCacheLength",
99  "Length of the cache for each source.",
100  UintegerValue (10),
102  MakeUintegerChecker<uint16_t> ())
103  .AddAttribute ("MeshUnderJitter",
104  "The jitter in ms a node uses to forward mesh-under packets - used to prevent collisions",
105  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
107  MakePointerChecker<RandomVariableStream> ())
108  .AddTraceSource ("Tx",
109  "Send - packet (including 6LoWPAN header), "
110  "SixLoWPanNetDevice Ptr, interface index.",
112  "ns3::SixLowPanNetDevice::RxTxTracedCallback")
113  .AddTraceSource ("Rx",
114  "Receive - packet (including 6LoWPAN header), "
115  "SixLoWPanNetDevice Ptr, interface index.",
117  "ns3::SixLowPanNetDevice::RxTxTracedCallback")
118  .AddTraceSource ("Drop",
119  "Drop - DropReason, packet (including 6LoWPAN header), "
120  "SixLoWPanNetDevice Ptr, interface index.",
122  "ns3::SixLowPanNetDevice::DropTracedCallback")
123  ;
124  return tid;
125 }
126 
128  : m_node (0),
129  m_netDevice (0),
130  m_ifIndex (0)
131 {
132  NS_LOG_FUNCTION (this);
133  m_netDevice = 0;
134  m_rng = CreateObject<UniformRandomVariable> ();
135  m_bc0Serial = 0;
136 }
137 
139 {
140  NS_LOG_FUNCTION (this);
141  return m_netDevice;
142 }
143 
145 {
146  NS_LOG_FUNCTION (this << device);
147  m_netDevice = device;
148 
149  NS_LOG_DEBUG ("RegisterProtocolHandler for " << device->GetInstanceTypeId ().GetName ());
150 
151  uint16_t protocolType = 0;
152  if ( m_forceEtherType )
153  {
154  protocolType = m_etherType;
155  }
157  this),
158  protocolType, device, false);
159 }
160 
161 int64_t SixLowPanNetDevice::AssignStreams (int64_t stream)
162 {
163  NS_LOG_FUNCTION (this << stream);
164  m_rng->SetStream (stream);
165  m_meshUnderJitter->SetStream (stream + 1);
166  return 2;
167 }
168 
170 {
171  NS_LOG_FUNCTION (this);
172 
173  m_netDevice = 0;
174  m_node = 0;
175 
176  m_timeoutEventList.clear ();
177  if (m_timeoutEvent.IsRunning ())
178  {
180  }
181 
182  for (MapFragmentsI_t iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
183  {
184  iter->second = 0;
185  }
186  m_fragments.clear ();
187 
189 }
190 
192  Ptr<const Packet> packet,
193  uint16_t protocol,
194  Address const &src,
195  Address const &dst,
196  PacketType packetType)
197 {
198  NS_LOG_FUNCTION (this << incomingPort << packet << protocol << src << dst);
199  NS_LOG_DEBUG ("UID is " << packet->GetUid ());
200 
201  uint8_t dispatchRawVal = 0;
202  SixLowPanDispatch::Dispatch_e dispatchVal;
203  Ptr<Packet> copyPkt = packet->Copy ();
204 
206 
207  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
208  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
209  bool isPktDecompressed = false;
210  bool fragmented = false;
211 
212  NS_LOG_DEBUG ( "Packet received: " << *copyPkt );
213  NS_LOG_DEBUG ( "Packet length: " << copyPkt->GetSize () );
214  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal) );
215 
216  SixLowPanMesh meshHdr;
217  SixLowPanBc0 bc0Hdr;
218  bool hasMesh = false;
219  bool hasBc0 = false;
220 
221  if ( dispatchVal == SixLowPanDispatch::LOWPAN_MESH )
222  {
223  hasMesh = true;
224  copyPkt->RemoveHeader (meshHdr);
225  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
226  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
227  }
228  if ( dispatchVal == SixLowPanDispatch::LOWPAN_BC0 )
229  {
230  hasBc0 = true;
231  copyPkt->RemoveHeader (bc0Hdr);
232  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
233  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
234  }
235 
236  if (hasMesh)
237  {
238  if (!hasBc0)
239  {
240  NS_LOG_LOGIC ("Dropped packet - we only support mesh if it is paired with a BC0");
242  return;
243  }
244 
245  if (find (m_seenPkts[meshHdr.GetOriginator ()].begin (),
246  m_seenPkts[meshHdr.GetOriginator ()].end (),
247  bc0Hdr.GetSequenceNumber ()) != m_seenPkts[meshHdr.GetOriginator ()].end ())
248  {
249  NS_LOG_LOGIC ("We have already seen this, no further processing.");
250  return;
251  }
252 
253  m_seenPkts[meshHdr.GetOriginator ()].push_back (bc0Hdr.GetSequenceNumber ());
254  if (m_seenPkts[meshHdr.GetOriginator ()].size () > m_meshCacheLength)
255  {
256  m_seenPkts[meshHdr.GetOriginator ()].pop_front ();
257  }
258 
259  NS_ABORT_MSG_IF (!Mac16Address::IsMatchingType (meshHdr.GetFinalDst ()), "SixLowPan mesh-under flooding can not currently handle extended address final destinations: " << meshHdr.GetFinalDst ());
260  NS_ABORT_MSG_IF (!Mac48Address::IsMatchingType (m_netDevice->GetAddress ()), "SixLowPan mesh-under flooding can not currently handle devices using extended addresses: " << m_netDevice->GetAddress ());
261 
262  Mac16Address finalDst = Mac16Address::ConvertFrom (meshHdr.GetFinalDst ());
263 
264  // See if the packet is for others than me. In case forward it.
265  if (meshHdr.GetFinalDst () != Get16MacFrom48Mac (m_netDevice->GetAddress ())
266  || finalDst.IsBroadcast ()
267  || finalDst.IsMulticast ()
268  )
269  {
270  uint8_t hopsLeft = meshHdr.GetHopsLeft ();
271 
272  if (hopsLeft == 0)
273  {
274  NS_LOG_LOGIC ("Not forwarding packet -- hop limit reached");
275  }
276  else if (meshHdr.GetOriginator () == Get16MacFrom48Mac (m_netDevice->GetAddress ()))
277  {
278  NS_LOG_LOGIC ("Not forwarding packet -- I am the originator");
279  }
280  else
281  {
282  meshHdr.SetHopsLeft (hopsLeft - 1);
283  Ptr<Packet> sendPkt = copyPkt->Copy ();
284  sendPkt->AddHeader (bc0Hdr);
285  sendPkt->AddHeader (meshHdr);
286  Simulator::Schedule (Time (MilliSeconds (m_meshUnderJitter->GetValue ())), &NetDevice::Send, m_netDevice, sendPkt, m_netDevice->GetBroadcast (), protocol);
287  }
288 
289  if (!finalDst.IsBroadcast () && !finalDst.IsMulticast ())
290  {
291  return;
292  }
293  }
294  }
295 
296  Address realDst = dst;
297  Address realSrc = src;
298  if (hasMesh)
299  {
300  realSrc = meshHdr.GetOriginator ();
301  realDst = meshHdr.GetFinalDst ();
302  }
303 
304  if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1 )
305  {
306  isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, true);
307  fragmented = true;
308  }
309  else if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN )
310  {
311  isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, false);
312  fragmented = true;
313  }
314  if ( fragmented )
315  {
316  if ( !isPktDecompressed )
317  {
318  return;
319  }
320  else
321  {
322  copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
323  dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
324  }
325  }
326 
327  switch ( dispatchVal )
328  {
330  NS_LOG_DEBUG ( "Packet without compression. Length: " << copyPkt->GetSize () );
331  {
332  SixLowPanIpv6 uncompressedHdr;
333  copyPkt->RemoveHeader (uncompressedHdr);
334  isPktDecompressed = true;
335  }
336  break;
338  DecompressLowPanHc1 (copyPkt, realSrc, realDst);
339  isPktDecompressed = true;
340  break;
342  DecompressLowPanIphc (copyPkt, realSrc, realDst);
343  isPktDecompressed = true;
344  break;
345  default:
346  NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
348  break;
349  }
350 
351  if ( !isPktDecompressed )
352  {
353  return;
354  }
355 
356  NS_LOG_DEBUG ( "Packet decompressed length: " << copyPkt->GetSize () );
357  NS_LOG_DEBUG ( "Packet decompressed received: " << *copyPkt );
358 
359  if (!m_promiscRxCallback.IsNull ())
360  {
361  m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc, realDst, packetType);
362  }
363 
364  m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc);
365 
366  return;
367 }
368 
369 void SixLowPanNetDevice::SetIfIndex (const uint32_t index)
370 {
371  NS_LOG_FUNCTION (this << index);
372  m_ifIndex = index;
373 }
374 
375 uint32_t SixLowPanNetDevice::GetIfIndex (void) const
376 {
377  NS_LOG_FUNCTION (this);
378  return m_ifIndex;
379 }
380 
382 {
383  NS_LOG_FUNCTION (this);
384  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
385 
386  return m_netDevice->GetChannel ();
387 }
388 
390 {
391  NS_LOG_FUNCTION (this << address);
392  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
393 
394  m_netDevice->SetAddress (address);
395 }
396 
398 {
399  NS_LOG_FUNCTION (this);
400  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
401 
402  return m_netDevice->GetAddress ();
403 }
404 
405 bool SixLowPanNetDevice::SetMtu (const uint16_t mtu)
406 {
407  NS_LOG_FUNCTION (this << mtu);
408  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
409 
410  return m_netDevice->SetMtu (mtu);
411 }
412 
413 uint16_t SixLowPanNetDevice::GetMtu (void) const
414 {
415  NS_LOG_FUNCTION (this);
416 
417  uint16_t mtu = m_netDevice->GetMtu ();
418 
419  // RFC 4944, section 4.
420  if (mtu < 1280)
421  {
422  mtu = 1280;
423  }
424  return mtu;
425 }
426 
428 {
429  NS_LOG_FUNCTION (this);
430  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
431 
432  return m_netDevice->IsLinkUp ();
433 }
434 
436 {
437  NS_LOG_FUNCTION (this);
438  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
439 
440  return m_netDevice->AddLinkChangeCallback (callback);
441 }
442 
444 {
445  NS_LOG_FUNCTION (this);
446  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
447 
448  return m_netDevice->IsBroadcast ();
449 }
450 
452 {
453  NS_LOG_FUNCTION (this);
454  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
455 
456  return m_netDevice->GetBroadcast ();
457 }
458 
460 {
461  NS_LOG_FUNCTION (this);
462  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
463 
464  return m_netDevice->IsMulticast ();
465 }
466 
468 {
469  NS_LOG_FUNCTION (this << multicastGroup);
470  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
471 
472  return m_netDevice->GetMulticast (multicastGroup);
473 }
474 
476 {
477  NS_LOG_FUNCTION (this << addr);
478  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
479 
480  return m_netDevice->GetMulticast (addr);
481 }
482 
484 {
485  NS_LOG_FUNCTION (this);
486  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
487 
488  return m_netDevice->IsPointToPoint ();
489 }
490 
492 {
493  NS_LOG_FUNCTION (this);
494  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
495 
496  return m_netDevice->IsBridge ();
497 }
498 
500  const Address& dest,
501  uint16_t protocolNumber)
502 {
503  NS_LOG_FUNCTION (this << *packet << dest << protocolNumber);
504  bool ret = false;
505  Address src;
506 
507  ret = DoSend (packet, src, dest, protocolNumber, false);
508  return ret;
509 }
510 
512  const Address& src,
513  const Address& dest,
514  uint16_t protocolNumber)
515 {
516  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber);
517  bool ret = false;
518 
519  ret = DoSend (packet, src, dest, protocolNumber, true);
520  return ret;
521 }
522 
524  const Address& src,
525  const Address& dest,
526  uint16_t protocolNumber,
527  bool doSendFrom)
528 {
529  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber << doSendFrom);
530  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
531 
532  Ptr<Packet> origPacket = packet->Copy ();
533  uint32_t origHdrSize = 0;
534  uint32_t origPacketSize = packet->GetSize ();
535  bool ret = false;
536 
537  Address destination = dest;
538 
539  bool useMesh = m_meshUnder;
540 
541  if (m_forceEtherType)
542  {
543  protocolNumber = m_etherType;
544  }
545 
546  if (m_useIphc)
547  {
548  NS_LOG_LOGIC ("Compressing packet using IPHC");
549  origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), destination);
550  }
551  else
552  {
553  NS_LOG_LOGIC ("Compressing packet using HC1");
554  origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), destination);
555  }
556 
557  uint16_t pktSize = packet->GetSize ();
558 
559  SixLowPanMesh meshHdr;
560  SixLowPanBc0 bc0Hdr;
561  if (useMesh)
562  {
563  Address source = src;
564  if (!doSendFrom)
565  {
566  source = m_netDevice->GetAddress ();
567  }
568 
569  if (Mac48Address::IsMatchingType (source))
570  {
571  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
572  source = Get16MacFrom48Mac (source);
573  }
574  if (Mac48Address::IsMatchingType (destination))
575  {
576  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
577  destination = Get16MacFrom48Mac (destination);
578  }
579 
580  meshHdr.SetOriginator (source);
581  meshHdr.SetFinalDst (destination);
583  destination = m_netDevice->GetBroadcast ();
584  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
585  }
586 
587  if (pktSize < m_compressionThreshold)
588  {
589  NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
590  packet = origPacket;
591  SixLowPanIpv6 ipv6UncompressedHdr;
592  packet->AddHeader (ipv6UncompressedHdr);
593  pktSize = packet->GetSize ();
594  if (useMesh)
595  {
596  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
597  }
598  }
599 
600 
601  if (pktSize > m_netDevice->GetMtu ())
602  {
603  NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
604  // fragment
605  std::list<Ptr<Packet> > fragmentList;
606  DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
607  std::list<Ptr<Packet> >::iterator it;
608  bool success = true;
609  for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
610  {
611  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
613 
614  if (useMesh)
615  {
616  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
617  (*it)->AddHeader (bc0Hdr);
618  (*it)->AddHeader (meshHdr);
619  }
620  if (doSendFrom)
621  {
622  success &= m_netDevice->SendFrom (*it, src, destination, protocolNumber);
623  }
624  else
625  {
626  success &= m_netDevice->Send (*it, destination, protocolNumber);
627  }
628  }
629  ret = success;
630  }
631  else
632  {
634 
635  if (useMesh)
636  {
637  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
638  packet->AddHeader (bc0Hdr);
639  packet->AddHeader (meshHdr);
640  }
641 
642  if (doSendFrom)
643  {
644  NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
645  ret = m_netDevice->SendFrom (packet, src, destination, protocolNumber);
646  }
647  else
648  {
649  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
650  ret = m_netDevice->Send (packet, destination, protocolNumber);
651  }
652  }
653 
654  return ret;
655 }
656 
658 {
659  NS_LOG_FUNCTION (this);
660  return m_node;
661 }
662 
664 {
665  NS_LOG_FUNCTION (this << node);
666  m_node = node;
667 }
668 
670 {
671  NS_LOG_FUNCTION (this);
672  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
673 
674  return m_netDevice->NeedsArp ();
675 }
676 
678 {
679  NS_LOG_FUNCTION (this << &cb);
680  m_rxCallback = cb;
681 }
682 
684 {
685  NS_LOG_FUNCTION (this << &cb);
686  m_promiscRxCallback = cb;
687 }
688 
690 {
691  NS_LOG_FUNCTION (this);
692  return true;
693 }
694 
695 uint32_t
697 {
698  NS_LOG_FUNCTION (this << *packet << src << dst);
699 
700  Ipv6Header ipHeader;
701  SixLowPanHc1 hc1Header;
702  uint32_t size = 0;
703 
704  if ( packet->PeekHeader (ipHeader) != 0 )
705  {
706  packet->RemoveHeader (ipHeader);
707  size += ipHeader.GetSerializedSize ();
708 
709  hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
710 
711  uint8_t bufOne[16];
712  uint8_t bufTwo[16];
713  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
714  srcAddr.GetBytes (bufOne);
716 
717  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
718 
719  mySrcAddr.GetBytes (bufTwo);
720  bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
721 
722  if (srcAddr.IsLinkLocal () && isSrcSrc )
723  {
725  }
726  else if (srcAddr.IsLinkLocal () )
727  {
729  hc1Header.SetSrcInterface (bufOne + 8);
730  }
731  else if ( isSrcSrc )
732  {
734  hc1Header.SetSrcPrefix (bufOne);
735  }
736  else
737  {
739  hc1Header.SetSrcInterface (bufOne + 8);
740  hc1Header.SetSrcPrefix (bufOne);
741  }
742 
743  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
744  dstAddr.GetBytes (bufOne);
746 
747  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
748 
749  myDstAddr.GetBytes (bufTwo);
750  bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
751 
752  if (dstAddr.IsLinkLocal () && isDstDst )
753  {
755  }
756  else if (dstAddr.IsLinkLocal () )
757  {
759  hc1Header.SetDstInterface (bufOne + 8);
760  }
761  else if ( isDstDst )
762  {
764  hc1Header.SetDstPrefix (bufOne);
765  }
766  else
767  {
769  hc1Header.SetDstInterface (bufOne + 8);
770  hc1Header.SetDstPrefix (bufOne);
771  }
772 
773  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
774  {
775  hc1Header.SetTcflCompression (true);
776  }
777  else
778  {
779  hc1Header.SetTcflCompression (false);
780  hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
781  hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
782  }
783 
784  uint8_t nextHeader = ipHeader.GetNextHeader ();
785  hc1Header.SetNextHeader (nextHeader);
786 
787  // \todo implement HC2 compression
788  hc1Header.SetHc2HeaderPresent (false);
789 
790  NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
791  NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
792 
793  packet->AddHeader (hc1Header);
794 
795  return size;
796  }
797 
798  return 0;
799 }
800 
801 void
803 {
804  NS_LOG_FUNCTION (this << *packet << src << dst);
805 
806  Ipv6Header ipHeader;
807  SixLowPanHc1 encoding;
808 
809  uint32_t ret = packet->RemoveHeader (encoding);
810  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
811  NS_UNUSED (ret);
812 
813  ipHeader.SetHopLimit (encoding.GetHopLimit ());
814 
815  switch (encoding.GetSrcCompression ())
816  {
817  const uint8_t* interface;
818  const uint8_t* prefix;
819  uint8_t address[16];
820 
822  prefix = encoding.GetSrcPrefix ();
823  interface = encoding.GetSrcInterface ();
824  for (int j = 0; j < 8; j++)
825  {
826  address[j + 8] = interface[j];
827  address[j] = prefix[j];
828  }
829  ipHeader.SetSourceAddress ( Ipv6Address (address) );
830  break;
832  prefix = encoding.GetSrcPrefix ();
833  for (int j = 0; j < 8; j++)
834  {
835  address[j + 8] = 0;
836  address[j] = prefix[j];
837  }
839  break;
841  interface = encoding.GetSrcInterface ();
842  address[0] = 0xfe;
843  address[1] = 0x80;
844  for (int j = 0; j < 8; j++)
845  {
846  address[j + 8] = interface[j];
847  }
848  ipHeader.SetSourceAddress ( Ipv6Address (address) );
849  break;
852  break;
853  }
854 
855  switch (encoding.GetDstCompression ())
856  {
857  const uint8_t* interface;
858  const uint8_t* prefix;
859  uint8_t address[16];
860 
862  prefix = encoding.GetDstPrefix ();
863  interface = encoding.GetDstInterface ();
864  for (int j = 0; j < 8; j++)
865  {
866  address[j + 8] = interface[j];
867  address[j] = prefix[j];
868  }
870  break;
872  prefix = encoding.GetDstPrefix ();
873  for (int j = 0; j < 8; j++)
874  {
875  address[j + 8] = 0;
876  address[j] = prefix[j];
877  }
879  break;
881  interface = encoding.GetDstInterface ();
882  address[0] = 0xfe;
883  address[1] = 0x80;
884  for (int j = 0; j < 8; j++)
885  {
886  address[j + 8] = interface[j];
887  }
889  break;
892  break;
893  }
894 
895  if ( !encoding.IsTcflCompression () )
896  {
897  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
898  ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
899  }
900  else
901  {
902  ipHeader.SetFlowLabel (0);
903  ipHeader.SetTrafficClass (0);
904  }
905 
906  ipHeader.SetNextHeader (encoding.GetNextHeader ());
907 
908  ipHeader.SetPayloadLength (packet->GetSize ());
909 
910  NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
911  "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
912 
913  packet->AddHeader (ipHeader);
914 
915  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
916 }
917 
918 uint32_t
920 {
921  NS_LOG_FUNCTION (this << *packet << src << dst);
922 
923  Ipv6Header ipHeader;
924  SixLowPanIphc iphcHeader;
925  uint32_t size = 0;
926 
927 
928  if ( packet->PeekHeader (ipHeader) != 0 )
929  {
930  packet->RemoveHeader (ipHeader);
931  size += ipHeader.GetSerializedSize ();
932 
933  // Set the TF field
934  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
935  {
936  iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
937  }
938  else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
939  {
940  iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
941  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
942  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
943  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
944  }
945  else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
946  {
947  iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
948  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
949  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
950  }
951  else
952  {
954  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
955  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
956  }
957 
958  // Set the NH field and NextHeader
959 
960  uint8_t nextHeader = ipHeader.GetNextHeader ();
961  if (CanCompressLowPanNhc (nextHeader))
962  {
963  if (nextHeader == Ipv6Header::IPV6_UDP)
964  {
965  iphcHeader.SetNh (true);
966  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
967  }
968  else if (nextHeader == Ipv6Header::IPV6_IPV6)
969  {
970  iphcHeader.SetNh (true);
971  size += CompressLowPanIphc (packet, src, dst);
972  }
973  else
974  {
975  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
976  // the compression might fail due to Extension header size.
977  if (sizeNhc)
978  {
979  iphcHeader.SetNh (true);
980  size += sizeNhc;
981  }
982  else
983  {
984  iphcHeader.SetNh (false);
985  iphcHeader.SetNextHeader (nextHeader);
986  }
987  }
988  }
989  else
990  {
991  iphcHeader.SetNh (false);
992  iphcHeader.SetNextHeader (nextHeader);
993  }
994 
995 
996  // Set the HLIM field
997  if (ipHeader.GetHopLimit () == 1)
998  {
1000  }
1001  else if (ipHeader.GetHopLimit () == 0x40)
1002  {
1004  }
1005  else if (ipHeader.GetHopLimit () == 0xFF)
1006  {
1008  }
1009  else
1010  {
1011  iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
1012  // Set the HopLimit
1013  iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
1014  }
1015 
1016  // \todo Add the check of CID if there is context-based compression
1017  // Set the CID field
1018  iphcHeader.SetCid (false);
1019 
1020  // \todo Add the check of SAC if there is context-based compression
1021  // Set the SAC field
1022  iphcHeader.SetSac (false);
1023 
1024  uint8_t addressBuf[16];
1025  uint8_t unicastAddrCheckerBuf[16];
1026  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
1027  srcAddr.GetBytes (addressBuf);
1028 
1029  Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
1030  checker.GetBytes (unicastAddrCheckerBuf);
1031 
1032  // \todo Add the check of SAC if there is context-based compression
1033  // Set the Source Address
1034  iphcHeader.SetSrcAddress (srcAddr);
1035 
1037  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
1038 
1039  if ( mySrcAddr == srcAddr )
1040  {
1041  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1042  }
1043  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1044  {
1045  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1046  }
1047  else if ( srcAddr.IsLinkLocal () )
1048  {
1049  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1050  }
1051  else
1052  {
1053  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1054  }
1055 
1056  // Set the M field
1057  if (ipHeader.GetDestinationAddress ().IsMulticast ())
1058  {
1059  iphcHeader.SetM (true);
1060  }
1061  else
1062  {
1063  iphcHeader.SetM (false);
1064  }
1065 
1066  // \todo Add the check of DAC if there is context-based compression
1067  // Set the DAC field
1068  iphcHeader.SetDac (false);
1069 
1070  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
1071  dstAddr.GetBytes (addressBuf);
1072 
1073  // \todo Add the check of DAC if there is context-based compression
1074  // Set the Destination Address
1075  iphcHeader.SetDstAddress (dstAddr);
1076 
1078  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
1079 
1080  if ( !iphcHeader.GetM () )
1081  // Unicast address
1082  {
1083  if ( myDstAddr == dstAddr )
1084  {
1085  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1086  }
1087  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1088  {
1089  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1090  }
1091  else if ( dstAddr.IsLinkLocal () )
1092  {
1093  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1094  }
1095  else
1096  {
1097  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1098  }
1099  }
1100  else
1101  {
1102  // Multicast address
1103  uint8_t multicastAddrCheckerBuf[16];
1104  Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
1105  multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
1106 
1107  // The address takes the form ff02::00XX.
1108  if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
1109  {
1110  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1111  }
1112  // The address takes the form ffXX::00XX:XXXX.
1113  // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1114  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1115  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
1116  {
1117  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1118  }
1119  // The address takes the form ffXX::00XX:XXXX:XXXX.
1120  // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1121  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1122  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
1123  {
1124  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1125  }
1126  else
1127  {
1128  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1129  }
1130  }
1131 
1132  NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
1133  NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
1134 
1135  packet->AddHeader (iphcHeader);
1136 
1137  NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
1138 
1139  return size;
1140  }
1141 
1142  return 0;
1143 }
1144 
1145 bool
1147 {
1148  bool ret = false;
1149 
1150  switch (nextHeader)
1151  {
1152  case Ipv6Header::IPV6_UDP:
1156  case Ipv6Header::IPV6_IPV6:
1157  ret = true;
1158  break;
1160  default:
1161  ret = false;
1162  }
1163  return ret;
1164 }
1165 
1166 void
1168 {
1169  NS_LOG_FUNCTION (this << *packet << src << dst);
1170 
1171  Ipv6Header ipHeader;
1172  SixLowPanIphc encoding;
1173 
1174  uint32_t ret = packet->RemoveHeader (encoding);
1175  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1176  NS_UNUSED (ret);
1177 
1178  // Hop Limit
1179  ipHeader.SetHopLimit (encoding.GetHopLimit ());
1180 
1181  // Source address
1182  if ( encoding.GetSac () )
1183  {
1184  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1185  {
1186  ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
1187  }
1188  else
1189  {
1190  NS_ABORT_MSG ("SAC option not yet implemented");
1191  }
1192  }
1193  else
1194  {
1195  if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_0 )
1196  {
1198  }
1199  else
1200  {
1201  ipHeader.SetSourceAddress ( encoding.GetSrcAddress () );
1202  }
1203  }
1204  // Destination address
1205  if ( encoding.GetDac () )
1206  {
1207  if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1208  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1209  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1210  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1211  {
1212  NS_ABORT_MSG ("Reserved code found");
1213  }
1214  else
1215  {
1216  NS_ABORT_MSG ("DAC option not yet implemented");
1217  }
1218  }
1219  else
1220  {
1221  if ( !encoding.GetM () && encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 )
1222  {
1224  }
1225  else
1226  {
1227  ipHeader.SetDestinationAddress ( encoding.GetDstAddress () );
1228  }
1229  }
1230 
1231  // Traffic class and Flow Label
1232  uint8_t traf = 0x00;
1233  switch (encoding.GetTf ())
1234  {
1236  traf |= encoding.GetEcn ();
1237  traf = ( traf << 6 ) | encoding.GetDscp ();
1238  ipHeader.SetTrafficClass (traf);
1239  ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1240  break;
1242  traf |= encoding.GetEcn ();
1243  traf <<= 2; // Add 2-bit pad
1244  ipHeader.SetTrafficClass (traf);
1245  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1246  break;
1248  traf |= encoding.GetEcn ();
1249  traf = ( traf << 6 ) | encoding.GetDscp ();
1250  ipHeader.SetTrafficClass (traf);
1251  ipHeader.SetFlowLabel (0);
1252  break;
1254  ipHeader.SetFlowLabel (0);
1255  ipHeader.SetTrafficClass (0);
1256  break;
1257  }
1258 
1259  if ( encoding.GetNh () )
1260  {
1261  // Next Header
1262  uint8_t dispatchRawVal = 0;
1264 
1265  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1266  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1267 
1268  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1269  {
1271  DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1272  }
1273  else
1274  {
1275  ipHeader.SetNextHeader (DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ()));
1276  }
1277  }
1278  else
1279  {
1280  ipHeader.SetNextHeader (encoding.GetNextHeader ());
1281  }
1282 
1283  ipHeader.SetPayloadLength (packet->GetSize ());
1284 
1285  packet->AddHeader (ipHeader);
1286 
1287  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1288 
1289 }
1290 
1291 uint32_t
1292 SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1293 {
1294  NS_LOG_FUNCTION (this << *packet << int(headerType));
1295 
1296  SixLowPanNhcExtension nhcHeader;
1297  uint32_t size = 0;
1298  Buffer blob;
1299 
1300  if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1301  {
1302  Ipv6ExtensionHopByHopHeader hopHeader;
1303  packet->PeekHeader (hopHeader);
1304  if (hopHeader.GetLength () >= 0xff)
1305  {
1306  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1307  "that have more than 255 octets following the Length field after compression. "
1308  "Packet uncompressed.");
1309  return 0;
1310  }
1311 
1312  size += packet->RemoveHeader (hopHeader);
1314 
1315  // recursively compress other headers
1316  uint8_t nextHeader = hopHeader.GetNextHeader ();
1317  if (CanCompressLowPanNhc (nextHeader))
1318  {
1319  if (nextHeader == Ipv6Header::IPV6_UDP)
1320  {
1321  nhcHeader.SetNh (true);
1322  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1323  }
1324  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1325  {
1326  nhcHeader.SetNh (true);
1327  size += CompressLowPanIphc (packet, src, dst);
1328  }
1329  else
1330  {
1331  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1332  // the compression might fail due to Extension header size.
1333  if (sizeNhc)
1334  {
1335  nhcHeader.SetNh (true);
1336  size += sizeNhc;
1337  }
1338  else
1339  {
1340  nhcHeader.SetNh (false);
1341  nhcHeader.SetNextHeader (nextHeader);
1342  }
1343  }
1344  }
1345  else
1346  {
1347  nhcHeader.SetNh (false);
1348  nhcHeader.SetNextHeader (nextHeader);
1349  }
1350 
1351  uint32_t blobSize = hopHeader.GetSerializedSize ();
1352  blob.AddAtStart (blobSize);
1353  hopHeader.Serialize (blob.Begin ());
1354  blob.RemoveAtStart (2);
1355  blobSize = blob.GetSize ();
1356  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1357  }
1358  else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1359  {
1360  Ipv6ExtensionRoutingHeader routingHeader;
1361  packet->PeekHeader (routingHeader);
1362  if (routingHeader.GetLength () >= 0xff)
1363  {
1364  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1365  "that have more than 255 octets following the Length field after compression. "
1366  "Packet uncompressed.");
1367  return 0;
1368  }
1369 
1370  size += packet->RemoveHeader (routingHeader);
1372 
1373  // recursively compress other headers
1374  uint8_t nextHeader = routingHeader.GetNextHeader ();
1375  if (CanCompressLowPanNhc (nextHeader))
1376  {
1377  if (nextHeader == Ipv6Header::IPV6_UDP)
1378  {
1379  nhcHeader.SetNh (true);
1380  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1381  }
1382  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1383  {
1384  nhcHeader.SetNh (true);
1385  size += CompressLowPanIphc (packet, src, dst);
1386  }
1387  else
1388  {
1389  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1390  // the compression might fail due to Extension header size.
1391  if (sizeNhc)
1392  {
1393  nhcHeader.SetNh (true);
1394  size += sizeNhc;
1395  }
1396  else
1397  {
1398  nhcHeader.SetNh (false);
1399  nhcHeader.SetNextHeader (nextHeader);
1400  }
1401  }
1402  }
1403  else
1404  {
1405  nhcHeader.SetNh (false);
1406  nhcHeader.SetNextHeader (nextHeader);
1407  }
1408 
1409  uint32_t blobSize = routingHeader.GetSerializedSize ();
1410  blob.AddAtStart (blobSize);
1411  routingHeader.Serialize (blob.Begin ());
1412  blob.RemoveAtStart (2);
1413  blobSize = blob.GetSize ();
1414  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1415  }
1416  else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1417  {
1418  Ipv6ExtensionFragmentHeader fragHeader;
1419  packet->PeekHeader (fragHeader);
1420  if (fragHeader.GetLength () >= 0xff)
1421  {
1422  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1423  "that have more than 255 octets following the Length field after compression. "
1424  "Packet uncompressed.");
1425  return 0;
1426  }
1427  size += packet->RemoveHeader (fragHeader);
1429 
1430  // recursively compress other headers
1431  uint8_t nextHeader = fragHeader.GetNextHeader ();
1432  if (CanCompressLowPanNhc (nextHeader))
1433  {
1434  if (nextHeader == Ipv6Header::IPV6_UDP)
1435  {
1436  nhcHeader.SetNh (true);
1437  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1438  }
1439  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1440  {
1441  nhcHeader.SetNh (true);
1442  size += CompressLowPanIphc (packet, src, dst);
1443  }
1444  else
1445  {
1446  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1447  // the compression might fail due to Extension header size.
1448  if (sizeNhc)
1449  {
1450  nhcHeader.SetNh (true);
1451  size += sizeNhc;
1452  }
1453  else
1454  {
1455  nhcHeader.SetNh (false);
1456  nhcHeader.SetNextHeader (nextHeader);
1457  }
1458  }
1459  }
1460  else
1461  {
1462  nhcHeader.SetNh (false);
1463  nhcHeader.SetNextHeader (nextHeader);
1464  }
1465 
1466  uint32_t blobSize = fragHeader.GetSerializedSize ();
1467  blob.AddAtStart (blobSize);
1468  fragHeader.Serialize (blob.Begin ());
1469  blob.RemoveAtStart (2);
1470  blobSize = blob.GetSize ();
1471  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1472  }
1473  else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1474  {
1475  Ipv6ExtensionDestinationHeader destHeader;
1476  packet->PeekHeader (destHeader);
1477  if (destHeader.GetLength () >= 0xff)
1478  {
1479  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1480  "that have more than 255 octets following the Length field after compression. "
1481  "Packet uncompressed.");
1482  return 0;
1483  }
1484  size += packet->RemoveHeader (destHeader);
1486 
1487  // recursively compress other headers
1488  uint8_t nextHeader = destHeader.GetNextHeader ();
1489  if (CanCompressLowPanNhc (nextHeader))
1490  {
1491  if (nextHeader == Ipv6Header::IPV6_UDP)
1492  {
1493  nhcHeader.SetNh (true);
1494  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1495  }
1496  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1497  {
1498  nhcHeader.SetNh (true);
1499  size += CompressLowPanIphc (packet, src, dst);
1500  }
1501  else
1502  {
1503  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1504  // the compression might fail due to Extension header size.
1505  if (sizeNhc)
1506  {
1507  nhcHeader.SetNh (true);
1508  size += sizeNhc;
1509  }
1510  else
1511  {
1512  nhcHeader.SetNh (false);
1513  nhcHeader.SetNextHeader (nextHeader);
1514  }
1515  }
1516  }
1517  else
1518  {
1519  nhcHeader.SetNh (false);
1520  nhcHeader.SetNextHeader (nextHeader);
1521  }
1522 
1523  uint32_t blobSize = destHeader.GetSerializedSize ();
1524  blob.AddAtStart (blobSize);
1525  destHeader.Serialize (blob.Begin ());
1526  blob.RemoveAtStart (2);
1527  blobSize = blob.GetSize ();
1528  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1529  }
1530  else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1531  {
1532  // \todo: IPv6 Mobility Header is not supported in ns-3
1533  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1534  return 0;
1535  }
1536  else
1537  {
1538  NS_ABORT_MSG ("Unexpected Extension Header");
1539  }
1540 
1541  NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1542  NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1543 
1544  packet->AddHeader (nhcHeader);
1545 
1546  NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1547  return size;
1548 }
1549 
1550 uint8_t
1551 SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1552 {
1553  NS_LOG_FUNCTION (this << *packet);
1554 
1555  SixLowPanNhcExtension encoding;
1556 
1557  uint32_t ret = packet->RemoveHeader (encoding);
1558  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1559  NS_UNUSED (ret);
1560 
1561  Ipv6ExtensionHopByHopHeader hopHeader;
1562  Ipv6ExtensionRoutingHeader routingHeader;
1563  Ipv6ExtensionFragmentHeader fragHeader;
1564  Ipv6ExtensionDestinationHeader destHeader;
1565 
1566  uint32_t blobSize;
1567  uint8_t blobData[260];
1568  blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
1569  uint8_t paddingSize = 0;
1570 
1571  uint8_t actualEncodedHeaderType = encoding.GetEid ();
1572  uint8_t actualHeaderType;
1573  Buffer blob;
1574 
1575  switch (actualEncodedHeaderType)
1576  {
1578  actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1579  if ( encoding.GetNh () )
1580  {
1581  // Next Header
1582  uint8_t dispatchRawVal = 0;
1584 
1585  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1586  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1587 
1588  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1589  {
1590  blobData [0] = Ipv6Header::IPV6_UDP;
1591  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1592  }
1593  else
1594  {
1595  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1596  }
1597  }
1598  else
1599  {
1600  blobData [0] = encoding.GetNextHeader ();
1601  }
1602 
1603  // manually add some padding if needed
1604  if ((blobSize + 2) % 8 > 0)
1605  {
1606  paddingSize = 8 - (blobSize + 2) % 8;
1607  }
1608  if (paddingSize == 1)
1609  {
1610  blobData[blobSize + 2] = 0;
1611  }
1612  else if (paddingSize > 1)
1613  {
1614  blobData[blobSize + 2] = 1;
1615  blobData[blobSize + 2 + 1] = paddingSize - 2;
1616  for (uint8_t i = 0; i < paddingSize - 2; i++)
1617  {
1618  blobData[blobSize + 2 + 2 + i] = 0;
1619  }
1620  }
1621  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1622  blob.AddAtStart (blobSize + 2 + paddingSize);
1623  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1624  hopHeader.Deserialize (blob.Begin ());
1625 
1626  packet->AddHeader (hopHeader);
1627  break;
1628 
1630  actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1631  if ( encoding.GetNh () )
1632  {
1633  // Next Header
1634  uint8_t dispatchRawVal = 0;
1636 
1637  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1638  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1639 
1640  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1641  {
1642  blobData [0] = Ipv6Header::IPV6_UDP;
1643  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1644  }
1645  else
1646  {
1647  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1648  }
1649  }
1650  else
1651  {
1652  blobData [0] = encoding.GetNextHeader ();
1653  }
1654  blobData [1] = ((blobSize + 2) >> 3) - 1;
1655  blob.AddAtStart (blobSize + 2);
1656  blob.Begin ().Write (blobData, blobSize + 2);
1657  routingHeader.Deserialize (blob.Begin ());
1658  packet->AddHeader (routingHeader);
1659  break;
1660 
1662  actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
1663  if ( encoding.GetNh () )
1664  {
1665  // Next Header
1666  uint8_t dispatchRawVal = 0;
1668 
1669  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1670  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1671 
1672  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1673  {
1674  blobData [0] = Ipv6Header::IPV6_UDP;
1675  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1676  }
1677  else
1678  {
1679  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1680  }
1681  }
1682  else
1683  {
1684  blobData [0] = encoding.GetNextHeader ();
1685  }
1686  blobData [1] = 0;
1687 
1688  blob.AddAtStart (blobSize + 2);
1689  blob.Begin ().Write (blobData, blobSize + 2);
1690 
1691  fragHeader.Deserialize (blob.Begin ());
1692  packet->AddHeader (fragHeader);
1693  break;
1694 
1696  actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
1697  if ( encoding.GetNh () )
1698  {
1699  // Next Header
1700  uint8_t dispatchRawVal = 0;
1702 
1703  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1704  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1705 
1706  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1707  {
1708  blobData [0] = Ipv6Header::IPV6_UDP;
1709  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1710  }
1711  else
1712  {
1713  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1714  }
1715  }
1716  else
1717  {
1718  blobData [0] = encoding.GetNextHeader ();
1719  }
1720 
1721  // manually add some padding if needed
1722  if ((blobSize + 2) % 8 > 0)
1723  {
1724  paddingSize = 8 - (blobSize + 2) % 8;
1725  }
1726  if (paddingSize == 1)
1727  {
1728  blobData[blobSize + 2] = 0;
1729  }
1730  else if (paddingSize > 1)
1731  {
1732  blobData[blobSize + 2] = 1;
1733  blobData[blobSize + 2 + 1] = paddingSize - 2;
1734  for (uint8_t i = 0; i < paddingSize - 2; i++)
1735  {
1736  blobData[blobSize + 2 + 2 + i] = 0;
1737  }
1738  }
1739  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1740  blob.AddAtStart (blobSize + 2 + paddingSize);
1741  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1742  destHeader.Deserialize (blob.Begin ());
1743 
1744  packet->AddHeader (destHeader);
1745  break;
1747  // \todo: IPv6 Mobility Header is not supported in ns-3
1748  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1749  break;
1751  actualHeaderType = Ipv6Header::IPV6_IPV6;
1752  DecompressLowPanIphc (packet, src, dst);
1753  break;
1754  default:
1755  NS_ABORT_MSG ("Trying to decode unknown Extension Header");
1756  break;
1757  }
1758 
1759  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1760  return actualHeaderType;
1761 }
1762 
1763 uint32_t
1765 {
1766  NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
1767 
1768  UdpHeader udpHeader;
1769  SixLowPanUdpNhcExtension udpNhcHeader;
1770  uint32_t size = 0;
1771 
1772  NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
1773 
1774  size += packet->RemoveHeader (udpHeader);
1775 
1776  // Set the C field and checksum
1777  udpNhcHeader.SetC (false);
1778  uint16_t checksum = udpHeader.GetChecksum ();
1779  udpNhcHeader.SetChecksum (checksum);
1780 
1781  if (omitChecksum && udpHeader.IsChecksumOk ())
1782  {
1783  udpNhcHeader.SetC (true);
1784  }
1785 
1786  // Set the value of the ports
1787  udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
1788  udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
1789 
1790  //Set the P field
1791  if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
1792  {
1794  }
1795  else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
1796  {
1798  }
1799  else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
1800  {
1802  }
1803  else
1804  {
1806  }
1807 
1808  NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
1809  NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
1810 
1811  packet->AddHeader (udpNhcHeader);
1812 
1813  NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
1814 
1815  return size;
1816 }
1817 
1818 void
1820 {
1821  NS_LOG_FUNCTION (this << *packet);
1822 
1823  UdpHeader udpHeader;
1824  SixLowPanUdpNhcExtension encoding;
1825 
1826  uint32_t ret = packet->RemoveHeader (encoding);
1827  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1828  NS_UNUSED (ret);
1829 
1830  // Set the value of the ports
1831  switch ( encoding.GetPorts () )
1832  {
1833  uint16_t temp;
1835  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1836  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1837  break;
1839  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1840  temp = 0xf0;
1841  temp |= (temp << 8) | encoding.GetDstPort ();
1842  udpHeader.SetDestinationPort (temp);
1843  break;
1845  temp = 0xf0;
1846  temp |= (temp << 8) | encoding.GetSrcPort ();
1847  udpHeader.SetSourcePort (temp);
1848  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1849  break;
1851  temp = 0xf0b;
1852  temp |= (temp << 4) | encoding.GetSrcPort ();
1853  udpHeader.SetSourcePort (temp);
1854  temp = 0xf0b;
1855  temp |= (temp << 4) | encoding.GetDstPort ();
1856  udpHeader.SetDestinationPort (temp);
1857  break;
1858  }
1859 
1860  // Get the C field and checksum
1861  if (Node::ChecksumEnabled ())
1862  {
1863  if ( encoding.GetC () )
1864  {
1865  NS_LOG_LOGIC ("Recalculating UDP Checksum");
1866  udpHeader.EnableChecksums ();
1867  udpHeader.InitializeChecksum (saddr,
1868  daddr,
1870  packet->AddHeader (udpHeader);
1871  }
1872  else
1873  {
1874  NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
1875  udpHeader.ForceChecksum (encoding.GetChecksum ());
1876  packet->AddHeader (udpHeader);
1877  NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
1878  }
1879  }
1880  else
1881  {
1882  packet->AddHeader (udpHeader);
1883  }
1884 
1885  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1886 }
1887 
1889  uint32_t origPacketSize,
1890  uint32_t origHdrSize,
1891  std::list<Ptr<Packet> >& listFragments)
1892 {
1893  NS_LOG_FUNCTION (this << *packet);
1894 
1895  Ptr<Packet> p = packet->Copy ();
1896 
1897  uint16_t offsetData = 0;
1898  uint16_t offset = 0;
1899  uint16_t l2Mtu = m_netDevice->GetMtu ();
1900  uint32_t packetSize = packet->GetSize ();
1901  uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
1902 
1903  uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
1904  NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
1905 
1906  // first fragment
1907  SixLowPanFrag1 frag1Hdr;
1908  frag1Hdr.SetDatagramTag (tag);
1909 
1910  uint32_t size;
1911  NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
1912  "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
1913 
1914  size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize;
1915  size -= size % 8;
1916  size += compressedHeaderSize;
1917 
1918  frag1Hdr.SetDatagramSize (origPacketSize);
1919 
1920  Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
1921  offset += size + origHdrSize - compressedHeaderSize;
1922  offsetData += size;
1923 
1924  fragment1->AddHeader (frag1Hdr);
1925  listFragments.push_back (fragment1);
1926 
1927  bool moreFrag = true;
1928  do
1929  {
1930  SixLowPanFragN fragNHdr;
1931  fragNHdr.SetDatagramTag (tag);
1932  fragNHdr.SetDatagramSize (origPacketSize);
1933  fragNHdr.SetDatagramOffset ((offset) >> 3);
1934 
1935  size = l2Mtu - fragNHdr.GetSerializedSize ();
1936  size -= size % 8;
1937 
1938  if ( (offsetData + size) > packetSize )
1939  {
1940  size = packetSize - offsetData;
1941  moreFrag = false;
1942  }
1943 
1944  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
1945  Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
1946  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1947 
1948  offset += size;
1949  offsetData += size;
1950 
1951  fragment->AddHeader (fragNHdr);
1952  listFragments.push_back (fragment);
1953 
1954  }
1955  while (moreFrag);
1956 
1957  return;
1958 }
1959 
1960 bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
1961 {
1962  NS_LOG_FUNCTION ( this << *packet );
1963  SixLowPanFrag1 frag1Header;
1964  SixLowPanFragN fragNHeader;
1965  FragmentKey_t key;
1966  uint16_t packetSize;
1967  key.first = std::pair<Address, Address> (src, dst);
1968 
1969  Ptr<Packet> p = packet->Copy ();
1970  uint16_t offset = 0;
1971 
1972  /* Implementation note:
1973  *
1974  * The fragment offset is relative to the *uncompressed* packet.
1975  * On the other hand, the packet can not be uncompressed correctly without all
1976  * its fragments, as the UDP checksum can not be computed otherwise.
1977  *
1978  * As a consequence we must uncompress the packet twice, and save its first
1979  * fragment for the final one.
1980  */
1981 
1982  if ( isFirst )
1983  {
1984  uint8_t dispatchRawValFrag1 = 0;
1985  SixLowPanDispatch::Dispatch_e dispatchValFrag1;
1986 
1987  p->RemoveHeader (frag1Header);
1988  packetSize = frag1Header.GetDatagramSize ();
1989  p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
1990  dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
1991  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
1992  NS_LOG_DEBUG ( "Packet: " << *p );
1993 
1994  switch ( dispatchValFrag1 )
1995  {
1997  {
1998  SixLowPanIpv6 uncompressedHdr;
1999  p->RemoveHeader (uncompressedHdr);
2000  }
2001  break;
2003  DecompressLowPanHc1 (p, src, dst);
2004  break;
2006  DecompressLowPanIphc (p, src, dst);
2007  break;
2008  default:
2009  NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
2010  break;
2011  }
2012 
2013  key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
2014  }
2015  else
2016  {
2017  p->RemoveHeader (fragNHeader);
2018  packetSize = fragNHeader.GetDatagramSize ();
2019  offset = fragNHeader.GetDatagramOffset () << 3;
2020  key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
2021  }
2022 
2023  Ptr<Fragments> fragments;
2024 
2025  MapFragments_t::iterator it = m_fragments.find (key);
2026  if (it == m_fragments.end ())
2027  {
2028  // erase the oldest packet.
2030  {
2032  FragmentKey_t oldestKey = std::get<1> (*iter);
2033 
2034  std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
2035  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2036  fragIter != storedFragments.end (); fragIter++)
2037  {
2039  }
2040 
2041  m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
2042  m_fragments[oldestKey] = 0;
2043  m_fragments.erase (oldestKey);
2044 
2045  }
2046  fragments = Create<Fragments> ();
2047  fragments->SetPacketSize (packetSize);
2048  m_fragments.insert (std::make_pair (key, fragments));
2049  uint32_t ifIndex = GetIfIndex ();
2050 
2051  FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
2052  fragments->SetTimeoutIter (iter);
2053  }
2054  else
2055  {
2056  fragments = it->second;
2057  }
2058 
2059  fragments->AddFragment (p, offset);
2060 
2061  // add the very first fragment so we can correctly decode the packet once is rebuilt.
2062  // this is needed because otherwise the UDP header length and checksum can not be calculated.
2063  if ( isFirst )
2064  {
2065  fragments->AddFirstFragment (packet);
2066  }
2067 
2068  if ( fragments->IsEntire () )
2069  {
2070  packet = fragments->GetPacket ();
2071  NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
2072 
2073  SixLowPanFrag1 frag1Header;
2074  packet->RemoveHeader (frag1Header);
2075 
2076  NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
2077  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
2078  fragments = 0;
2079  m_fragments.erase (key);
2080  return true;
2081  }
2082 
2083  return false;
2084 }
2085 
2087 {
2088  NS_LOG_FUNCTION (this);
2089  m_packetSize = 0;
2090 }
2091 
2093 {
2094  NS_LOG_FUNCTION (this);
2095 }
2096 
2097 void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
2098 {
2099  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
2100 
2101  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
2102  bool duplicate = false;
2103 
2104  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
2105  {
2106  if (it->second > fragmentOffset)
2107  {
2108  break;
2109  }
2110  if (it->second == fragmentOffset)
2111  {
2112  duplicate = true;
2113  NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
2114  break;
2115  }
2116  }
2117  if (!duplicate)
2118  {
2119  m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
2120  }
2121 }
2122 
2124 {
2125  NS_LOG_FUNCTION (this << *fragment);
2126 
2127  m_firstFragment = fragment;
2128 }
2129 
2131 {
2132  NS_LOG_FUNCTION (this);
2133 
2134  bool ret = m_fragments.size () > 0;
2135  uint16_t lastEndOffset = 0;
2136 
2137  if (ret)
2138  {
2139  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
2140  {
2141  // overlapping fragments should not exist
2142  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
2143 
2144  if (lastEndOffset < it->second)
2145  {
2146  ret = false;
2147  break;
2148  }
2149  // fragments might overlap in strange ways
2150  uint16_t fragmentEnd = it->first->GetSize () + it->second;
2151  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
2152  }
2153  }
2154 
2155  if ( ret && (lastEndOffset == m_packetSize))
2156  {
2157  return true;
2158  }
2159  return false;
2160 }
2161 
2163 {
2164  NS_LOG_FUNCTION (this);
2165 
2166  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2167 
2168  Ptr<Packet> p = Create<Packet> ();
2169  uint16_t lastEndOffset = 0;
2170 
2171  p->AddAtEnd (m_firstFragment);
2172  it = m_fragments.begin ();
2173  lastEndOffset = it->first->GetSize ();
2174 
2175  for ( it++; it != m_fragments.end (); it++)
2176  {
2177  if ( lastEndOffset > it->second )
2178  {
2179  NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2180  }
2181  else
2182  {
2183  NS_LOG_LOGIC ("Adding: " << *(it->first) );
2184  p->AddAtEnd (it->first);
2185  }
2186  lastEndOffset += it->first->GetSize ();
2187  }
2188 
2189  return p;
2190 }
2191 
2193 {
2194  NS_LOG_FUNCTION (this << packetSize);
2195  m_packetSize = packetSize;
2196 }
2197 
2198 std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2199 {
2200  std::list< Ptr<Packet> > fragments;
2201  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2202  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
2203  {
2204  fragments.push_back (iter->first);
2205  }
2206  return fragments;
2207 }
2208 
2209 void
2211 {
2212  m_timeoutIter = iter;
2213  return;
2214 }
2215 
2218 {
2219  return m_timeoutIter;
2220 }
2221 
2223 {
2224  NS_LOG_FUNCTION (this);
2225 
2226  MapFragments_t::iterator it = m_fragments.find (key);
2227  std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2228  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2229  fragIter != storedFragments.end (); fragIter++)
2230  {
2232  }
2233  // clear the buffers
2234  it->second = 0;
2235 
2236  m_fragments.erase (key);
2237 }
2238 
2240 {
2241  NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
2242 
2243  uint8_t buf[6];
2244  addr.CopyTo (buf);
2245 
2246  Mac16Address shortAddr;
2247  shortAddr.CopyFrom (buf + 4);
2248 
2249  return shortAddr;
2250 }
2251 
2253 {
2254  if (m_timeoutEventList.empty ())
2255  {
2257  }
2258  m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, iif);
2259 
2261 
2262  return (iter);
2263 }
2264 
2266 {
2267  Time now = Simulator::Now ();
2268 
2269  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
2270  {
2271  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
2272  std::get<2> (*m_timeoutEventList.begin ()));
2273  m_timeoutEventList.pop_front ();
2274  }
2275 
2276  if (m_timeoutEventList.empty ())
2277  {
2278  return;
2279  }
2280 
2281  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
2283 
2284  return;
2285 }
2286 
2287 }
2288 
2289 // namespace ns3
uint8_t GetEcn(void) const
Get the ECN.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
void DecompressLowPanUdpNhc(Ptr< Packet > packet, Ipv6Address saddr, Ipv6Address daddr)
Decompress the headers according to NHC compression.
static bool IsMatchingType(const Address &address)
uint8_t GetNextHeader(void) const
Get the Next Header field value.
Address GetOriginator(void) const
Get the "Originator" address.
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
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
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 "...
std::pair< std::pair< Address, Address >, std::pair< uint16_t, uint16_t > > FragmentKey_t
Fragment identifier type: src/dst address src/dst port.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
void HandleTimeout(void)
Handles a fragmented packet timeout.
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:75
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void SetHopLimit(uint8_t hopLimit)
Set the Hop Limit field.
Definition: second.py:1
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
uint32_t GetId(void) const
Definition: node.cc: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.
uint8_t GetHopsLeft(void) const
Get the "Hops Left" field.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
EventId m_timeoutEvent
Event for the next scheduled timeout.
6LoWPAN IPv6 uncompressed header - see RFC 4944.
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:438
uint8_t GetDscp(void) const
Get the DSCP.
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
uint16_t GetDstPort() const
Get the Destination Port.
Hold variables of type string.
Definition: string.h:41
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
uint8_t GetSequenceNumber(void) const
Get the "Sequence Number" field.
virtual void SetIfIndex(const uint32_t index)
static Mac16Address ConvertFrom(const Address &address)
void SetPacketSize(uint32_t packetSize)
Set the packet-to-be-defragmented size.
void AddFirstFragment(Ptr< Packet > fragment)
Add the first packet fragment.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
static const uint32_t packetSize
Header of IPv6 Extension Routing.
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:85
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static bool ChecksumEnabled(void)
Definition: node.cc: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 CopyFrom(const uint8_t buffer[2])
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static TypeId GetTypeId(void)
Get the type ID.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1072
virtual bool IsBroadcast(void) const
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
HeaderCompression_e GetSam(void) const
Get the SAM (Source Address Mode) compression.
uint16_t GetLength() const
Get the length of the extension.
std::list< std::tuple< Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
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.
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
void HandleFragmentsTimeout(FragmentKey_t key, uint32_t iif)
Process the timeout for packet fragments.
uint32_t GetFlowLabel(void) const
Get the Flow Label.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint8_t m_bc0Serial
Serial number used in BC0 header.
virtual bool SetMtu(const uint16_t mtu)
bool IsEntire() const
If all fragments have been added.
void SetNetDevice(Ptr< NetDevice > device)
Setup SixLowPan to be a proxy for the specified NetDevice.
void SetTrafficClass(uint8_t trafficClass)
Set the Traffic Class value.
Header of IPv6 Extension "Hop by Hop".
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
a polymophic address class
Definition: address.h:90
void SetSequenceNumber(uint8_t seqNumber)
Set the "Sequence Number" field.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:449
void SetHopsLeft(uint8_t hopsLeft)
Set the "Hops Left" field.
void ForceChecksum(uint16_t checksum)
Force the UDP checksum to a given value.
Definition: udp-header.cc:142
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetHlim(Hlim_e hlimField)
Set the HLIM (Hop Limit) compression.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual bool IsMulticast(void) const
uint32_t CompressLowPanNhc(Ptr< Packet > packet, uint8_t headerType, Address const &src, Address const &dst)
Compress the headers according to NHC compression.
bool m_useIphc
Use IPHC or HC1.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
Ptr< Node > m_node
Smart pointer to the Node.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
void SetBlob(const uint8_t *blob, uint32_t size)
Set the option header data blob.
uint32_t CompressLowPanUdpNhc(Ptr< Packet > packet, bool omitChecksum)
Compress the headers according to NHC compression.
uint32_t CompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to IPHC compression.
HeaderCompression_e GetDam(void) const
Get the DAM (Destination Address Mode) compression.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:227
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1390
#define max(a, b)
Definition: 80211b.c:43
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
Address GetFinalDst(void) const
Get the "Final Destination" address.
AttributeValue implementation for Time.
Definition: nstime.h:1126
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:49
std::map< Address, std::list< uint8_t > > m_seenPkts
Seen packets, memorized by OriginatorAdddress, SequenceNumber.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Ptr< Packet > GetPacket() const
Get the entire packet.
Ptr< RandomVariableStream > m_meshUnderJitter
Random variable for the mesh-under packet retransmission.
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
bool GetNh(void) const
Get the NH (Next Header) compression.
void SetOriginator(Address originator)
Set the "Originator" address.
void SetSac(bool sacField)
Set the SAC (Source Address Compression) compression.
std::list< Ptr< Packet > > GetFraments() const
Get a list of the current stored fragments.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
6LoWPAN BC0 header - see RFC 4944.
void SetNh(bool nhField)
Set the NH (Next Header) compression.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
void SetChecksum(uint16_t checksum)
Set the Checksum field values.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1610
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.
bool m_meshUnder
Use a mesh-under routing.
TracedCallback< DropReason, Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_dropTrace
Callback to trace drop packets.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
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:461
bool m_forceEtherType
Force the EtherType number.
virtual bool NeedsArp(void) const
virtual uint32_t GetIfIndex(void) const
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:44
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
uint32_t m_compressionThreshold
Minimum L2 payload size.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
Shim performing 6LoWPAN compression, decompression and fragmentation.
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.
Address Get16MacFrom48Mac(Address addr)
Get a Mac16 from its Mac48 pseudo-MAC.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
uint16_t GetSrcPort() const
Get the Source Port.
Packet header for UDP packets.
Definition: udp-header.h:39
virtual void AddLinkChangeCallback(Callback< void > callback)
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
LowPanHc1Addr_e GetDstCompression() const
Get Destination Compression type.
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.
This class can contain 16 bit addresses.
Definition: mac16-address.h:41
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:1127
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:41
SixLowPanNetDevice()
Constructor for the SixLowPanNetDevice.
virtual Ptr< Node > GetNode(void) const
uint32_t GetFlowLabel() const
Get the Flow Label value.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:85
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label (20bits).
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
void SetFinalDst(Address finalDst)
Set the "Final Destination" address.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
void ReceiveFromDevice(Ptr< NetDevice > device, Ptr< const Packet > packet, uint16_t protocol, Address const &source, Address const &destination, PacketType packetType)
Receives all the packets from a NetDevice for further processing.
Network layer to device interface.
Definition: net-device.h:95
uint8_t GetHopLimit(void) const
Get the Hop Limit field.
6LoWPAN Mesh header - see RFC 4944.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
Header of IPv6 Extension Destination.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1064
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.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
uint32_t GetSize(void) const
Definition: buffer.h:1063
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
void SetEid(Eid_e extensionHeaderType)
Set the Extension Header Type.
Header of IPv6 Extension Fragment.
std::map< FragmentKey_t, Ptr< Fragments > >::iterator MapFragmentsI_t
Container Iterator for fragment key -> fragments.
Eid_e GetEid(void) const
Get the Extension Header Type.
bool CanCompressLowPanNhc(uint8_t headerType)
Checks if the next header can be compressed using NHC.
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 m_meshCacheLength
length of the cache for each source.
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
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
void SetDstAddress(Ipv6Address dstAddress)
Set the Destination Address.
Ptr< NetDevice > m_netDevice
Smart pointer to the underlying NetDevice.
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset)
Add a fragment to the pool.
bool ProcessFragment(Ptr< Packet > &packet, Address const &src, Address const &dst, bool isFirst)
Process a packet fragment.
void SetM(bool mField)
Set the M (Multicast) compression.
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:296
void SetSrcPrefix(const uint8_t *srcPrefix)
Set the source prefix.
bool GetM(void) const
Get the M (Multicast) compression.
Ptr< NetDevice > GetNetDevice() const
Returns a smart pointer to the underlying NetDevice.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
virtual bool IsLinkUp(void) const
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual uint16_t GetMtu(void) const
Returns the link-layer MTU for this interface.
static bool IsMatchingType(const Address &address)
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1372
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
uint8_t m_meshUnderHopsLeft
Start value for mesh-under hops left.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
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.
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition: address.cc:82
bool IsChecksumOk(void) const
Is the UDP checksum correct ?
Definition: udp-header.cc:136
uint8_t GetNextHeader() const
Get the Next Header value.