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  if (m_useIphc)
339  {
341  return;
342  }
343  DecompressLowPanHc1 (copyPkt, realSrc, realDst);
344  isPktDecompressed = true;
345  break;
347  if (!m_useIphc)
348  {
350  return;
351  }
352  DecompressLowPanIphc (copyPkt, realSrc, realDst);
353  isPktDecompressed = true;
354  break;
355  default:
356  NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
358  break;
359  }
360 
361  if ( !isPktDecompressed )
362  {
363  return;
364  }
365 
366  NS_LOG_DEBUG ( "Packet decompressed length: " << copyPkt->GetSize () );
367  NS_LOG_DEBUG ( "Packet decompressed received: " << *copyPkt );
368 
369  if (!m_promiscRxCallback.IsNull ())
370  {
371  m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc, realDst, packetType);
372  }
373 
374  m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc);
375 
376  return;
377 }
378 
379 void SixLowPanNetDevice::SetIfIndex (const uint32_t index)
380 {
381  NS_LOG_FUNCTION (this << index);
382  m_ifIndex = index;
383 }
384 
385 uint32_t SixLowPanNetDevice::GetIfIndex (void) const
386 {
387  NS_LOG_FUNCTION (this);
388  return m_ifIndex;
389 }
390 
392 {
393  NS_LOG_FUNCTION (this);
394  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
395 
396  return m_netDevice->GetChannel ();
397 }
398 
400 {
401  NS_LOG_FUNCTION (this << address);
402  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
403 
404  m_netDevice->SetAddress (address);
405 }
406 
408 {
409  NS_LOG_FUNCTION (this);
410  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
411 
412  return m_netDevice->GetAddress ();
413 }
414 
415 bool SixLowPanNetDevice::SetMtu (const uint16_t mtu)
416 {
417  NS_LOG_FUNCTION (this << mtu);
418  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
419 
420  return m_netDevice->SetMtu (mtu);
421 }
422 
423 uint16_t SixLowPanNetDevice::GetMtu (void) const
424 {
425  NS_LOG_FUNCTION (this);
426 
427  uint16_t mtu = m_netDevice->GetMtu ();
428 
429  // RFC 4944, section 4.
430  if (mtu < 1280)
431  {
432  mtu = 1280;
433  }
434  return mtu;
435 }
436 
438 {
439  NS_LOG_FUNCTION (this);
440  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
441 
442  return m_netDevice->IsLinkUp ();
443 }
444 
446 {
447  NS_LOG_FUNCTION (this);
448  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
449 
450  return m_netDevice->AddLinkChangeCallback (callback);
451 }
452 
454 {
455  NS_LOG_FUNCTION (this);
456  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
457 
458  return m_netDevice->IsBroadcast ();
459 }
460 
462 {
463  NS_LOG_FUNCTION (this);
464  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
465 
466  return m_netDevice->GetBroadcast ();
467 }
468 
470 {
471  NS_LOG_FUNCTION (this);
472  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
473 
474  return m_netDevice->IsMulticast ();
475 }
476 
478 {
479  NS_LOG_FUNCTION (this << multicastGroup);
480  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
481 
482  return m_netDevice->GetMulticast (multicastGroup);
483 }
484 
486 {
487  NS_LOG_FUNCTION (this << addr);
488  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
489 
490  return m_netDevice->GetMulticast (addr);
491 }
492 
494 {
495  NS_LOG_FUNCTION (this);
496  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
497 
498  return m_netDevice->IsPointToPoint ();
499 }
500 
502 {
503  NS_LOG_FUNCTION (this);
504  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
505 
506  return m_netDevice->IsBridge ();
507 }
508 
510  const Address& dest,
511  uint16_t protocolNumber)
512 {
513  NS_LOG_FUNCTION (this << *packet << dest << protocolNumber);
514  bool ret = false;
515  Address src;
516 
517  ret = DoSend (packet, src, dest, protocolNumber, false);
518  return ret;
519 }
520 
522  const Address& src,
523  const Address& dest,
524  uint16_t protocolNumber)
525 {
526  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber);
527  bool ret = false;
528 
529  ret = DoSend (packet, src, dest, protocolNumber, true);
530  return ret;
531 }
532 
534  const Address& src,
535  const Address& dest,
536  uint16_t protocolNumber,
537  bool doSendFrom)
538 {
539  NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber << doSendFrom);
540  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
541 
542  Ptr<Packet> origPacket = packet->Copy ();
543  uint32_t origHdrSize = 0;
544  uint32_t origPacketSize = packet->GetSize ();
545  bool ret = false;
546 
547  Address destination = dest;
548 
549  bool useMesh = m_meshUnder;
550 
551  if (m_forceEtherType)
552  {
553  protocolNumber = m_etherType;
554  }
555 
556  if (m_useIphc)
557  {
558  NS_LOG_LOGIC ("Compressing packet using IPHC");
559  origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), destination);
560  }
561  else
562  {
563  NS_LOG_LOGIC ("Compressing packet using HC1");
564  origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), destination);
565  }
566 
567  uint16_t pktSize = packet->GetSize ();
568 
569  SixLowPanMesh meshHdr;
570  SixLowPanBc0 bc0Hdr;
571  if (useMesh)
572  {
573  Address source = src;
574  if (!doSendFrom)
575  {
576  source = m_netDevice->GetAddress ();
577  }
578 
579  if (Mac48Address::IsMatchingType (source))
580  {
581  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
582  source = Get16MacFrom48Mac (source);
583  }
584  if (Mac48Address::IsMatchingType (destination))
585  {
586  // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
587  destination = Get16MacFrom48Mac (destination);
588  }
589 
590  meshHdr.SetOriginator (source);
591  meshHdr.SetFinalDst (destination);
593  destination = m_netDevice->GetBroadcast ();
594  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
595  }
596 
598  {
599  NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
600  packet = origPacket;
601  SixLowPanIpv6 ipv6UncompressedHdr;
602  packet->AddHeader (ipv6UncompressedHdr);
603  pktSize = packet->GetSize ();
604  if (useMesh)
605  {
606  pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
607  }
608  }
609 
610 
611  if (pktSize > m_netDevice->GetMtu ())
612  {
613  NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
614  // fragment
615  std::list<Ptr<Packet> > fragmentList;
616  DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
617  std::list<Ptr<Packet> >::iterator it;
618  bool success = true;
619  for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
620  {
621  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
623 
624  if (useMesh)
625  {
626  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
627  (*it)->AddHeader (bc0Hdr);
628  (*it)->AddHeader (meshHdr);
629  }
630  if (doSendFrom)
631  {
632  success &= m_netDevice->SendFrom (*it, src, destination, protocolNumber);
633  }
634  else
635  {
636  success &= m_netDevice->Send (*it, destination, protocolNumber);
637  }
638  }
639  ret = success;
640  }
641  else
642  {
644 
645  if (useMesh)
646  {
647  bc0Hdr.SetSequenceNumber (m_bc0Serial++);
648  packet->AddHeader (bc0Hdr);
649  packet->AddHeader (meshHdr);
650  }
651 
652  if (doSendFrom)
653  {
654  NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
655  ret = m_netDevice->SendFrom (packet, src, destination, protocolNumber);
656  }
657  else
658  {
659  NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
660  ret = m_netDevice->Send (packet, destination, protocolNumber);
661  }
662  }
663 
664  return ret;
665 }
666 
668 {
669  NS_LOG_FUNCTION (this);
670  return m_node;
671 }
672 
674 {
675  NS_LOG_FUNCTION (this << node);
676  m_node = node;
677 }
678 
680 {
681  NS_LOG_FUNCTION (this);
682  NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
683 
684  return m_netDevice->NeedsArp ();
685 }
686 
688 {
689  NS_LOG_FUNCTION (this << &cb);
690  m_rxCallback = cb;
691 }
692 
694 {
695  NS_LOG_FUNCTION (this << &cb);
696  m_promiscRxCallback = cb;
697 }
698 
700 {
701  NS_LOG_FUNCTION (this);
702  return true;
703 }
704 
705 uint32_t
707 {
708  NS_LOG_FUNCTION (this << *packet << src << dst);
709 
710  Ipv6Header ipHeader;
711  SixLowPanHc1 hc1Header;
712  uint32_t size = 0;
713 
714  if ( packet->PeekHeader (ipHeader) != 0 )
715  {
716  packet->RemoveHeader (ipHeader);
717  size += ipHeader.GetSerializedSize ();
718 
719  hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
720 
721  uint8_t bufOne[16];
722  uint8_t bufTwo[16];
723  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
724  srcAddr.GetBytes (bufOne);
726 
727  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
728 
729  mySrcAddr.GetBytes (bufTwo);
730  bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
731 
732  if (srcAddr.IsLinkLocal () && isSrcSrc )
733  {
735  }
736  else if (srcAddr.IsLinkLocal () )
737  {
739  hc1Header.SetSrcInterface (bufOne + 8);
740  }
741  else if ( isSrcSrc )
742  {
744  hc1Header.SetSrcPrefix (bufOne);
745  }
746  else
747  {
749  hc1Header.SetSrcInterface (bufOne + 8);
750  hc1Header.SetSrcPrefix (bufOne);
751  }
752 
753  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
754  dstAddr.GetBytes (bufOne);
756 
757  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
758 
759  myDstAddr.GetBytes (bufTwo);
760  bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
761 
762  if (dstAddr.IsLinkLocal () && isDstDst )
763  {
765  }
766  else if (dstAddr.IsLinkLocal () )
767  {
769  hc1Header.SetDstInterface (bufOne + 8);
770  }
771  else if ( isDstDst )
772  {
774  hc1Header.SetDstPrefix (bufOne);
775  }
776  else
777  {
779  hc1Header.SetDstInterface (bufOne + 8);
780  hc1Header.SetDstPrefix (bufOne);
781  }
782 
783  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
784  {
785  hc1Header.SetTcflCompression (true);
786  }
787  else
788  {
789  hc1Header.SetTcflCompression (false);
790  hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
791  hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
792  }
793 
794  uint8_t nextHeader = ipHeader.GetNextHeader ();
795  hc1Header.SetNextHeader (nextHeader);
796 
797  // \todo implement HC2 compression
798  hc1Header.SetHc2HeaderPresent (false);
799 
800  NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
801  NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
802 
803  packet->AddHeader (hc1Header);
804 
805  return size;
806  }
807 
808  return 0;
809 }
810 
811 void
813 {
814  NS_LOG_FUNCTION (this << *packet << src << dst);
815 
816  Ipv6Header ipHeader;
817  SixLowPanHc1 encoding;
818 
819  uint32_t ret = packet->RemoveHeader (encoding);
820  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
821  NS_UNUSED (ret);
822 
823  ipHeader.SetHopLimit (encoding.GetHopLimit ());
824 
825  switch (encoding.GetSrcCompression ())
826  {
827  const uint8_t* interface;
828  const uint8_t* prefix;
829  uint8_t address[16];
830 
832  prefix = encoding.GetSrcPrefix ();
833  interface = encoding.GetSrcInterface ();
834  for (int j = 0; j < 8; j++)
835  {
836  address[j + 8] = interface[j];
837  address[j] = prefix[j];
838  }
839  ipHeader.SetSourceAddress ( Ipv6Address (address) );
840  break;
842  prefix = encoding.GetSrcPrefix ();
843  for (int j = 0; j < 8; j++)
844  {
845  address[j + 8] = 0;
846  address[j] = prefix[j];
847  }
849  break;
851  interface = encoding.GetSrcInterface ();
852  address[0] = 0xfe;
853  address[1] = 0x80;
854  for (int j = 0; j < 8; j++)
855  {
856  address[j + 8] = interface[j];
857  }
858  ipHeader.SetSourceAddress ( Ipv6Address (address) );
859  break;
862  break;
863  }
864 
865  switch (encoding.GetDstCompression ())
866  {
867  const uint8_t* interface;
868  const uint8_t* prefix;
869  uint8_t address[16];
870 
872  prefix = encoding.GetDstPrefix ();
873  interface = encoding.GetDstInterface ();
874  for (int j = 0; j < 8; j++)
875  {
876  address[j + 8] = interface[j];
877  address[j] = prefix[j];
878  }
880  break;
882  prefix = encoding.GetDstPrefix ();
883  for (int j = 0; j < 8; j++)
884  {
885  address[j + 8] = 0;
886  address[j] = prefix[j];
887  }
889  break;
891  interface = encoding.GetDstInterface ();
892  address[0] = 0xfe;
893  address[1] = 0x80;
894  for (int j = 0; j < 8; j++)
895  {
896  address[j + 8] = interface[j];
897  }
899  break;
902  break;
903  }
904 
905  if ( !encoding.IsTcflCompression () )
906  {
907  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
908  ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
909  }
910  else
911  {
912  ipHeader.SetFlowLabel (0);
913  ipHeader.SetTrafficClass (0);
914  }
915 
916  ipHeader.SetNextHeader (encoding.GetNextHeader ());
917 
918  ipHeader.SetPayloadLength (packet->GetSize ());
919 
920  NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
921  "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
922 
923  packet->AddHeader (ipHeader);
924 
925  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
926 }
927 
928 uint32_t
930 {
931  NS_LOG_FUNCTION (this << *packet << src << dst);
932 
933  Ipv6Header ipHeader;
934  SixLowPanIphc iphcHeader;
935  uint32_t size = 0;
936 
937 
938  if ( packet->PeekHeader (ipHeader) != 0 )
939  {
940  packet->RemoveHeader (ipHeader);
941  size += ipHeader.GetSerializedSize ();
942 
943  // Set the TF field
944  if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
945  {
946  iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
947  }
948  else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
949  {
950  iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
951  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
952  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
953  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
954  }
955  else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
956  {
957  iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
958  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
959  iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
960  }
961  else
962  {
964  iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
965  iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
966  }
967 
968  // Set the NH field and NextHeader
969 
970  uint8_t nextHeader = ipHeader.GetNextHeader ();
971  if (CanCompressLowPanNhc (nextHeader))
972  {
973  if (nextHeader == Ipv6Header::IPV6_UDP)
974  {
975  iphcHeader.SetNh (true);
976  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
977  }
978  else if (nextHeader == Ipv6Header::IPV6_IPV6)
979  {
980  iphcHeader.SetNh (true);
981  size += CompressLowPanIphc (packet, src, dst);
982  }
983  else
984  {
985  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
986  // the compression might fail due to Extension header size.
987  if (sizeNhc)
988  {
989  iphcHeader.SetNh (true);
990  size += sizeNhc;
991  }
992  else
993  {
994  iphcHeader.SetNh (false);
995  iphcHeader.SetNextHeader (nextHeader);
996  }
997  }
998  }
999  else
1000  {
1001  iphcHeader.SetNh (false);
1002  iphcHeader.SetNextHeader (nextHeader);
1003  }
1004 
1005 
1006  // Set the HLIM field
1007  if (ipHeader.GetHopLimit () == 1)
1008  {
1009  iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_1);
1010  }
1011  else if (ipHeader.GetHopLimit () == 0x40)
1012  {
1014  }
1015  else if (ipHeader.GetHopLimit () == 0xFF)
1016  {
1018  }
1019  else
1020  {
1021  iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
1022  // Set the HopLimit
1023  iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
1024  }
1025 
1026  // \todo Add the check of CID if there is context-based compression
1027  // Set the CID field
1028  iphcHeader.SetCid (false);
1029 
1030  // \todo Add the check of SAC if there is context-based compression
1031  // Set the SAC field
1032  iphcHeader.SetSac (false);
1033 
1034  uint8_t addressBuf[16];
1035  uint8_t unicastAddrCheckerBuf[16];
1036  Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
1037  srcAddr.GetBytes (addressBuf);
1038 
1039  Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
1040  checker.GetBytes (unicastAddrCheckerBuf);
1041 
1042  // \todo Add the check of SAC if there is context-based compression
1043  // Set the Source Address
1044  iphcHeader.SetSrcAddress (srcAddr);
1045 
1047  NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
1048 
1049  if ( mySrcAddr == srcAddr )
1050  {
1051  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1052  }
1053  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1054  {
1055  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
1056  }
1057  else if ( srcAddr.IsLinkLocal () )
1058  {
1059  iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
1060  }
1061  else
1062  {
1063  iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1064  }
1065 
1066  // Set the M field
1067  if (ipHeader.GetDestinationAddress ().IsMulticast ())
1068  {
1069  iphcHeader.SetM (true);
1070  }
1071  else
1072  {
1073  iphcHeader.SetM (false);
1074  }
1075 
1076  // \todo Add the check of DAC if there is context-based compression
1077  // Set the DAC field
1078  iphcHeader.SetDac (false);
1079 
1080  Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
1081  dstAddr.GetBytes (addressBuf);
1082 
1083  // \todo Add the check of DAC if there is context-based compression
1084  // Set the Destination Address
1085  iphcHeader.SetDstAddress (dstAddr);
1086 
1088  NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
1089 
1090  if ( !iphcHeader.GetM () )
1091  // Unicast address
1092  {
1093  if ( myDstAddr == dstAddr )
1094  {
1095  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1096  }
1097  else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1098  {
1099  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1100  }
1101  else if ( dstAddr.IsLinkLocal () )
1102  {
1103  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1104  }
1105  else
1106  {
1107  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1108  }
1109  }
1110  else
1111  {
1112  // Multicast address
1113  uint8_t multicastAddrCheckerBuf[16];
1114  Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
1115  multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
1116 
1117  // The address takes the form ff02::00XX.
1118  if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
1119  {
1120  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1121  }
1122  // The address takes the form ffXX::00XX:XXXX.
1123  // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1124  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1125  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
1126  {
1127  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
1128  }
1129  // The address takes the form ffXX::00XX:XXXX:XXXX.
1130  // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1131  else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1132  && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
1133  {
1134  iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
1135  }
1136  else
1137  {
1138  iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1139  }
1140  }
1141 
1142  NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
1143  NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
1144 
1145  packet->AddHeader (iphcHeader);
1146 
1147  NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
1148 
1149  return size;
1150  }
1151 
1152  return 0;
1153 }
1154 
1155 bool
1157 {
1158  bool ret = false;
1159 
1160  switch (nextHeader)
1161  {
1162  case Ipv6Header::IPV6_UDP:
1166  case Ipv6Header::IPV6_IPV6:
1167  ret = true;
1168  break;
1170  default:
1171  ret = false;
1172  }
1173  return ret;
1174 }
1175 
1176 void
1178 {
1179  NS_LOG_FUNCTION (this << *packet << src << dst);
1180 
1181  Ipv6Header ipHeader;
1182  SixLowPanIphc encoding;
1183 
1184  uint32_t ret = packet->RemoveHeader (encoding);
1185  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1186  NS_UNUSED (ret);
1187 
1188  // Hop Limit
1189  ipHeader.SetHopLimit (encoding.GetHopLimit ());
1190 
1191  // Source address
1192  if ( encoding.GetSac () )
1193  {
1194  if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1195  {
1196  ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
1197  }
1198  else
1199  {
1200  NS_ABORT_MSG ("SAC option not yet implemented");
1201  }
1202  }
1203  else
1204  {
1205  if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_0 )
1206  {
1208  }
1209  else
1210  {
1211  ipHeader.SetSourceAddress ( encoding.GetSrcAddress () );
1212  }
1213  }
1214  // Destination address
1215  if ( encoding.GetDac () )
1216  {
1217  if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1218  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1219  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1220  || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1221  {
1222  NS_ABORT_MSG ("Reserved code found");
1223  }
1224  else
1225  {
1226  NS_ABORT_MSG ("DAC option not yet implemented");
1227  }
1228  }
1229  else
1230  {
1231  if ( !encoding.GetM () && encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 )
1232  {
1234  }
1235  else
1236  {
1237  ipHeader.SetDestinationAddress ( encoding.GetDstAddress () );
1238  }
1239  }
1240 
1241  // Traffic class and Flow Label
1242  uint8_t traf = 0x00;
1243  switch (encoding.GetTf ())
1244  {
1246  traf |= encoding.GetEcn ();
1247  traf = ( traf << 6 ) | encoding.GetDscp ();
1248  ipHeader.SetTrafficClass (traf);
1249  ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1250  break;
1252  traf |= encoding.GetEcn ();
1253  traf <<= 2; // Add 2-bit pad
1254  ipHeader.SetTrafficClass (traf);
1255  ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1256  break;
1258  traf |= encoding.GetEcn ();
1259  traf = ( traf << 6 ) | encoding.GetDscp ();
1260  ipHeader.SetTrafficClass (traf);
1261  ipHeader.SetFlowLabel (0);
1262  break;
1264  ipHeader.SetFlowLabel (0);
1265  ipHeader.SetTrafficClass (0);
1266  break;
1267  }
1268 
1269  if ( encoding.GetNh () )
1270  {
1271  // Next Header
1272  uint8_t dispatchRawVal = 0;
1274 
1275  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1276  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1277 
1278  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1279  {
1281  DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
1282  }
1283  else
1284  {
1285  ipHeader.SetNextHeader (DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ()));
1286  }
1287  }
1288  else
1289  {
1290  ipHeader.SetNextHeader (encoding.GetNextHeader ());
1291  }
1292 
1293  ipHeader.SetPayloadLength (packet->GetSize ());
1294 
1295  packet->AddHeader (ipHeader);
1296 
1297  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1298 
1299 }
1300 
1301 uint32_t
1302 SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1303 {
1304  NS_LOG_FUNCTION (this << *packet << int(headerType));
1305 
1306  SixLowPanNhcExtension nhcHeader;
1307  uint32_t size = 0;
1308  Buffer blob;
1309 
1310  if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1311  {
1312  Ipv6ExtensionHopByHopHeader hopHeader;
1313  packet->PeekHeader (hopHeader);
1314  if (hopHeader.GetLength () >= 0xff)
1315  {
1316  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1317  "that have more than 255 octets following the Length field after compression. "
1318  "Packet uncompressed.");
1319  return 0;
1320  }
1321 
1322  size += packet->RemoveHeader (hopHeader);
1324 
1325  // recursively compress other headers
1326  uint8_t nextHeader = hopHeader.GetNextHeader ();
1327  if (CanCompressLowPanNhc (nextHeader))
1328  {
1329  if (nextHeader == Ipv6Header::IPV6_UDP)
1330  {
1331  nhcHeader.SetNh (true);
1332  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1333  }
1334  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1335  {
1336  nhcHeader.SetNh (true);
1337  size += CompressLowPanIphc (packet, src, dst);
1338  }
1339  else
1340  {
1341  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1342  // the compression might fail due to Extension header size.
1343  if (sizeNhc)
1344  {
1345  nhcHeader.SetNh (true);
1346  size += sizeNhc;
1347  }
1348  else
1349  {
1350  nhcHeader.SetNh (false);
1351  nhcHeader.SetNextHeader (nextHeader);
1352  }
1353  }
1354  }
1355  else
1356  {
1357  nhcHeader.SetNh (false);
1358  nhcHeader.SetNextHeader (nextHeader);
1359  }
1360 
1361  uint32_t blobSize = hopHeader.GetSerializedSize ();
1362  blob.AddAtStart (blobSize);
1363  hopHeader.Serialize (blob.Begin ());
1364  blob.RemoveAtStart (2);
1365  blobSize = blob.GetSize ();
1366  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1367  }
1368  else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1369  {
1370  Ipv6ExtensionRoutingHeader routingHeader;
1371  packet->PeekHeader (routingHeader);
1372  if (routingHeader.GetLength () >= 0xff)
1373  {
1374  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1375  "that have more than 255 octets following the Length field after compression. "
1376  "Packet uncompressed.");
1377  return 0;
1378  }
1379 
1380  size += packet->RemoveHeader (routingHeader);
1382 
1383  // recursively compress other headers
1384  uint8_t nextHeader = routingHeader.GetNextHeader ();
1385  if (CanCompressLowPanNhc (nextHeader))
1386  {
1387  if (nextHeader == Ipv6Header::IPV6_UDP)
1388  {
1389  nhcHeader.SetNh (true);
1390  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1391  }
1392  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1393  {
1394  nhcHeader.SetNh (true);
1395  size += CompressLowPanIphc (packet, src, dst);
1396  }
1397  else
1398  {
1399  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1400  // the compression might fail due to Extension header size.
1401  if (sizeNhc)
1402  {
1403  nhcHeader.SetNh (true);
1404  size += sizeNhc;
1405  }
1406  else
1407  {
1408  nhcHeader.SetNh (false);
1409  nhcHeader.SetNextHeader (nextHeader);
1410  }
1411  }
1412  }
1413  else
1414  {
1415  nhcHeader.SetNh (false);
1416  nhcHeader.SetNextHeader (nextHeader);
1417  }
1418 
1419  uint32_t blobSize = routingHeader.GetSerializedSize ();
1420  blob.AddAtStart (blobSize);
1421  routingHeader.Serialize (blob.Begin ());
1422  blob.RemoveAtStart (2);
1423  blobSize = blob.GetSize ();
1424  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1425  }
1426  else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1427  {
1428  Ipv6ExtensionFragmentHeader fragHeader;
1429  packet->PeekHeader (fragHeader);
1430  if (fragHeader.GetLength () >= 0xff)
1431  {
1432  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1433  "that have more than 255 octets following the Length field after compression. "
1434  "Packet uncompressed.");
1435  return 0;
1436  }
1437  size += packet->RemoveHeader (fragHeader);
1439 
1440  // recursively compress other headers
1441  uint8_t nextHeader = fragHeader.GetNextHeader ();
1442  if (CanCompressLowPanNhc (nextHeader))
1443  {
1444  if (nextHeader == Ipv6Header::IPV6_UDP)
1445  {
1446  nhcHeader.SetNh (true);
1447  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1448  }
1449  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1450  {
1451  nhcHeader.SetNh (true);
1452  size += CompressLowPanIphc (packet, src, dst);
1453  }
1454  else
1455  {
1456  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1457  // the compression might fail due to Extension header size.
1458  if (sizeNhc)
1459  {
1460  nhcHeader.SetNh (true);
1461  size += sizeNhc;
1462  }
1463  else
1464  {
1465  nhcHeader.SetNh (false);
1466  nhcHeader.SetNextHeader (nextHeader);
1467  }
1468  }
1469  }
1470  else
1471  {
1472  nhcHeader.SetNh (false);
1473  nhcHeader.SetNextHeader (nextHeader);
1474  }
1475 
1476  uint32_t blobSize = fragHeader.GetSerializedSize ();
1477  blob.AddAtStart (blobSize);
1478  fragHeader.Serialize (blob.Begin ());
1479  blob.RemoveAtStart (2);
1480  blobSize = blob.GetSize ();
1481  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1482  }
1483  else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1484  {
1485  Ipv6ExtensionDestinationHeader destHeader;
1486  packet->PeekHeader (destHeader);
1487  if (destHeader.GetLength () >= 0xff)
1488  {
1489  NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1490  "that have more than 255 octets following the Length field after compression. "
1491  "Packet uncompressed.");
1492  return 0;
1493  }
1494  size += packet->RemoveHeader (destHeader);
1496 
1497  // recursively compress other headers
1498  uint8_t nextHeader = destHeader.GetNextHeader ();
1499  if (CanCompressLowPanNhc (nextHeader))
1500  {
1501  if (nextHeader == Ipv6Header::IPV6_UDP)
1502  {
1503  nhcHeader.SetNh (true);
1504  size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1505  }
1506  else if (nextHeader == Ipv6Header::IPV6_IPV6)
1507  {
1508  nhcHeader.SetNh (true);
1509  size += CompressLowPanIphc (packet, src, dst);
1510  }
1511  else
1512  {
1513  uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1514  // the compression might fail due to Extension header size.
1515  if (sizeNhc)
1516  {
1517  nhcHeader.SetNh (true);
1518  size += sizeNhc;
1519  }
1520  else
1521  {
1522  nhcHeader.SetNh (false);
1523  nhcHeader.SetNextHeader (nextHeader);
1524  }
1525  }
1526  }
1527  else
1528  {
1529  nhcHeader.SetNh (false);
1530  nhcHeader.SetNextHeader (nextHeader);
1531  }
1532 
1533  uint32_t blobSize = destHeader.GetSerializedSize ();
1534  blob.AddAtStart (blobSize);
1535  destHeader.Serialize (blob.Begin ());
1536  blob.RemoveAtStart (2);
1537  blobSize = blob.GetSize ();
1538  nhcHeader.SetBlob (blob.PeekData (), blobSize);
1539  }
1540  else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1541  {
1542  // \todo: IPv6 Mobility Header is not supported in ns-3
1543  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1544  return 0;
1545  }
1546  else
1547  {
1548  NS_ABORT_MSG ("Unexpected Extension Header");
1549  }
1550 
1551  NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1552  NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1553 
1554  packet->AddHeader (nhcHeader);
1555 
1556  NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1557  return size;
1558 }
1559 
1560 uint8_t
1561 SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1562 {
1563  NS_LOG_FUNCTION (this << *packet);
1564 
1565  SixLowPanNhcExtension encoding;
1566 
1567  uint32_t ret = packet->RemoveHeader (encoding);
1568  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1569  NS_UNUSED (ret);
1570 
1571  Ipv6ExtensionHopByHopHeader hopHeader;
1572  Ipv6ExtensionRoutingHeader routingHeader;
1573  Ipv6ExtensionFragmentHeader fragHeader;
1574  Ipv6ExtensionDestinationHeader destHeader;
1575 
1576  uint32_t blobSize;
1577  uint8_t blobData[260];
1578  blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
1579  uint8_t paddingSize = 0;
1580 
1581  uint8_t actualEncodedHeaderType = encoding.GetEid ();
1582  uint8_t actualHeaderType;
1583  Buffer blob;
1584 
1585  switch (actualEncodedHeaderType)
1586  {
1588  actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1589  if ( encoding.GetNh () )
1590  {
1591  // Next Header
1592  uint8_t dispatchRawVal = 0;
1594 
1595  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1596  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1597 
1598  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1599  {
1600  blobData [0] = Ipv6Header::IPV6_UDP;
1601  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1602  }
1603  else
1604  {
1605  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1606  }
1607  }
1608  else
1609  {
1610  blobData [0] = encoding.GetNextHeader ();
1611  }
1612 
1613  // manually add some padding if needed
1614  if ((blobSize + 2) % 8 > 0)
1615  {
1616  paddingSize = 8 - (blobSize + 2) % 8;
1617  }
1618  if (paddingSize == 1)
1619  {
1620  blobData[blobSize + 2] = 0;
1621  }
1622  else if (paddingSize > 1)
1623  {
1624  blobData[blobSize + 2] = 1;
1625  blobData[blobSize + 2 + 1] = paddingSize - 2;
1626  for (uint8_t i = 0; i < paddingSize - 2; i++)
1627  {
1628  blobData[blobSize + 2 + 2 + i] = 0;
1629  }
1630  }
1631  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1632  blob.AddAtStart (blobSize + 2 + paddingSize);
1633  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1634  hopHeader.Deserialize (blob.Begin ());
1635 
1636  packet->AddHeader (hopHeader);
1637  break;
1638 
1640  actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1641  if ( encoding.GetNh () )
1642  {
1643  // Next Header
1644  uint8_t dispatchRawVal = 0;
1646 
1647  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1648  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1649 
1650  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1651  {
1652  blobData [0] = Ipv6Header::IPV6_UDP;
1653  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1654  }
1655  else
1656  {
1657  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1658  }
1659  }
1660  else
1661  {
1662  blobData [0] = encoding.GetNextHeader ();
1663  }
1664  blobData [1] = ((blobSize + 2) >> 3) - 1;
1665  blob.AddAtStart (blobSize + 2);
1666  blob.Begin ().Write (blobData, blobSize + 2);
1667  routingHeader.Deserialize (blob.Begin ());
1668  packet->AddHeader (routingHeader);
1669  break;
1670 
1672  actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
1673  if ( encoding.GetNh () )
1674  {
1675  // Next Header
1676  uint8_t dispatchRawVal = 0;
1678 
1679  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1680  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1681 
1682  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1683  {
1684  blobData [0] = Ipv6Header::IPV6_UDP;
1685  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1686  }
1687  else
1688  {
1689  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1690  }
1691  }
1692  else
1693  {
1694  blobData [0] = encoding.GetNextHeader ();
1695  }
1696  blobData [1] = 0;
1697 
1698  blob.AddAtStart (blobSize + 2);
1699  blob.Begin ().Write (blobData, blobSize + 2);
1700 
1701  fragHeader.Deserialize (blob.Begin ());
1702  packet->AddHeader (fragHeader);
1703  break;
1704 
1706  actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
1707  if ( encoding.GetNh () )
1708  {
1709  // Next Header
1710  uint8_t dispatchRawVal = 0;
1712 
1713  packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1714  dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1715 
1716  if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1717  {
1718  blobData [0] = Ipv6Header::IPV6_UDP;
1719  DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1720  }
1721  else
1722  {
1723  blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
1724  }
1725  }
1726  else
1727  {
1728  blobData [0] = encoding.GetNextHeader ();
1729  }
1730 
1731  // manually add some padding if needed
1732  if ((blobSize + 2) % 8 > 0)
1733  {
1734  paddingSize = 8 - (blobSize + 2) % 8;
1735  }
1736  if (paddingSize == 1)
1737  {
1738  blobData[blobSize + 2] = 0;
1739  }
1740  else if (paddingSize > 1)
1741  {
1742  blobData[blobSize + 2] = 1;
1743  blobData[blobSize + 2 + 1] = paddingSize - 2;
1744  for (uint8_t i = 0; i < paddingSize - 2; i++)
1745  {
1746  blobData[blobSize + 2 + 2 + i] = 0;
1747  }
1748  }
1749  blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1750  blob.AddAtStart (blobSize + 2 + paddingSize);
1751  blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1752  destHeader.Deserialize (blob.Begin ());
1753 
1754  packet->AddHeader (destHeader);
1755  break;
1757  // \todo: IPv6 Mobility Header is not supported in ns-3
1758  NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1759  break;
1761  actualHeaderType = Ipv6Header::IPV6_IPV6;
1762  DecompressLowPanIphc (packet, src, dst);
1763  break;
1764  default:
1765  NS_ABORT_MSG ("Trying to decode unknown Extension Header");
1766  break;
1767  }
1768 
1769  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1770  return actualHeaderType;
1771 }
1772 
1773 uint32_t
1775 {
1776  NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
1777 
1778  UdpHeader udpHeader;
1779  SixLowPanUdpNhcExtension udpNhcHeader;
1780  uint32_t size = 0;
1781 
1782  NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
1783 
1784  size += packet->RemoveHeader (udpHeader);
1785 
1786  // Set the C field and checksum
1787  udpNhcHeader.SetC (false);
1788  uint16_t checksum = udpHeader.GetChecksum ();
1789  udpNhcHeader.SetChecksum (checksum);
1790 
1791  if (omitChecksum && udpHeader.IsChecksumOk ())
1792  {
1793  udpNhcHeader.SetC (true);
1794  }
1795 
1796  // Set the value of the ports
1797  udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
1798  udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
1799 
1800  //Set the P field
1801  if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
1802  {
1804  }
1805  else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
1806  {
1808  }
1809  else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
1810  {
1812  }
1813  else
1814  {
1816  }
1817 
1818  NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
1819  NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
1820 
1821  packet->AddHeader (udpNhcHeader);
1822 
1823  NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
1824 
1825  return size;
1826 }
1827 
1828 void
1830 {
1831  NS_LOG_FUNCTION (this << *packet);
1832 
1833  UdpHeader udpHeader;
1834  SixLowPanUdpNhcExtension encoding;
1835 
1836  uint32_t ret = packet->RemoveHeader (encoding);
1837  NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1838  NS_UNUSED (ret);
1839 
1840  // Set the value of the ports
1841  switch ( encoding.GetPorts () )
1842  {
1843  uint16_t temp;
1845  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1846  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1847  break;
1849  udpHeader.SetSourcePort (encoding.GetSrcPort ());
1850  temp = 0xf0;
1851  temp |= (temp << 8) | encoding.GetDstPort ();
1852  udpHeader.SetDestinationPort (temp);
1853  break;
1855  temp = 0xf0;
1856  temp |= (temp << 8) | encoding.GetSrcPort ();
1857  udpHeader.SetSourcePort (temp);
1858  udpHeader.SetDestinationPort (encoding.GetDstPort ());
1859  break;
1861  temp = 0xf0b;
1862  temp |= (temp << 4) | encoding.GetSrcPort ();
1863  udpHeader.SetSourcePort (temp);
1864  temp = 0xf0b;
1865  temp |= (temp << 4) | encoding.GetDstPort ();
1866  udpHeader.SetDestinationPort (temp);
1867  break;
1868  }
1869 
1870  // Get the C field and checksum
1871  if (Node::ChecksumEnabled ())
1872  {
1873  if ( encoding.GetC () )
1874  {
1875  NS_LOG_LOGIC ("Recalculating UDP Checksum");
1876  udpHeader.EnableChecksums ();
1877  udpHeader.InitializeChecksum (saddr,
1878  daddr,
1880  packet->AddHeader (udpHeader);
1881  }
1882  else
1883  {
1884  NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
1885  udpHeader.ForceChecksum (encoding.GetChecksum ());
1886  packet->AddHeader (udpHeader);
1887  NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
1888  }
1889  }
1890  else
1891  {
1892  packet->AddHeader (udpHeader);
1893  }
1894 
1895  NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1896 }
1897 
1899  uint32_t origPacketSize,
1900  uint32_t origHdrSize,
1901  std::list<Ptr<Packet> >& listFragments)
1902 {
1903  NS_LOG_FUNCTION (this << *packet);
1904 
1905  Ptr<Packet> p = packet->Copy ();
1906 
1907  uint16_t offsetData = 0;
1908  uint16_t offset = 0;
1909  uint16_t l2Mtu = m_netDevice->GetMtu ();
1910  uint32_t packetSize = packet->GetSize ();
1911  uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
1912 
1913  uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
1914  NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
1915 
1916  // first fragment
1917  SixLowPanFrag1 frag1Hdr;
1918  frag1Hdr.SetDatagramTag (tag);
1919 
1920  uint32_t size;
1921  NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
1922  "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
1923 
1924  size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize;
1925  size -= size % 8;
1926  size += compressedHeaderSize;
1927 
1928  frag1Hdr.SetDatagramSize (origPacketSize);
1929 
1930  Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
1931  offset += size + origHdrSize - compressedHeaderSize;
1932  offsetData += size;
1933 
1934  fragment1->AddHeader (frag1Hdr);
1935  listFragments.push_back (fragment1);
1936 
1937  bool moreFrag = true;
1938  do
1939  {
1940  SixLowPanFragN fragNHdr;
1941  fragNHdr.SetDatagramTag (tag);
1942  fragNHdr.SetDatagramSize (origPacketSize);
1943  fragNHdr.SetDatagramOffset ((offset) >> 3);
1944 
1945  size = l2Mtu - fragNHdr.GetSerializedSize ();
1946  size -= size % 8;
1947 
1948  if ( (offsetData + size) > packetSize )
1949  {
1950  size = packetSize - offsetData;
1951  moreFrag = false;
1952  }
1953 
1954  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
1955  Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
1956  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1957 
1958  offset += size;
1959  offsetData += size;
1960 
1961  fragment->AddHeader (fragNHdr);
1962  listFragments.push_back (fragment);
1963 
1964  }
1965  while (moreFrag);
1966 
1967  return;
1968 }
1969 
1970 bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
1971 {
1972  NS_LOG_FUNCTION ( this << *packet );
1973  SixLowPanFrag1 frag1Header;
1974  SixLowPanFragN fragNHeader;
1975  FragmentKey_t key;
1976  uint16_t packetSize;
1977  key.first = std::pair<Address, Address> (src, dst);
1978 
1979  Ptr<Packet> p = packet->Copy ();
1980  uint16_t offset = 0;
1981 
1982  /* Implementation note:
1983  *
1984  * The fragment offset is relative to the *uncompressed* packet.
1985  * On the other hand, the packet can not be uncompressed correctly without all
1986  * its fragments, as the UDP checksum can not be computed otherwise.
1987  *
1988  * As a consequence we must uncompress the packet twice, and save its first
1989  * fragment for the final one.
1990  */
1991 
1992  if ( isFirst )
1993  {
1994  uint8_t dispatchRawValFrag1 = 0;
1995  SixLowPanDispatch::Dispatch_e dispatchValFrag1;
1996 
1997  p->RemoveHeader (frag1Header);
1998  packetSize = frag1Header.GetDatagramSize ();
1999  p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
2000  dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
2001  NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
2002  NS_LOG_DEBUG ( "Packet: " << *p );
2003 
2004  switch ( dispatchValFrag1 )
2005  {
2007  {
2008  SixLowPanIpv6 uncompressedHdr;
2009  p->RemoveHeader (uncompressedHdr);
2010  }
2011  break;
2013  DecompressLowPanHc1 (p, src, dst);
2014  break;
2016  DecompressLowPanIphc (p, src, dst);
2017  break;
2018  default:
2019  NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
2020  break;
2021  }
2022 
2023  key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
2024  }
2025  else
2026  {
2027  p->RemoveHeader (fragNHeader);
2028  packetSize = fragNHeader.GetDatagramSize ();
2029  offset = fragNHeader.GetDatagramOffset () << 3;
2030  key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
2031  }
2032 
2033  Ptr<Fragments> fragments;
2034 
2035  MapFragments_t::iterator it = m_fragments.find (key);
2036  if (it == m_fragments.end ())
2037  {
2038  // erase the oldest packet.
2040  {
2042  FragmentKey_t oldestKey = std::get<1> (*iter);
2043 
2044  std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
2045  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2046  fragIter != storedFragments.end (); fragIter++)
2047  {
2049  }
2050 
2051  m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
2052  m_fragments[oldestKey] = 0;
2053  m_fragments.erase (oldestKey);
2054 
2055  }
2056  fragments = Create<Fragments> ();
2057  fragments->SetPacketSize (packetSize);
2058  m_fragments.insert (std::make_pair (key, fragments));
2059  uint32_t ifIndex = GetIfIndex ();
2060 
2061  FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
2062  fragments->SetTimeoutIter (iter);
2063  }
2064  else
2065  {
2066  fragments = it->second;
2067  }
2068 
2069  fragments->AddFragment (p, offset);
2070 
2071  // add the very first fragment so we can correctly decode the packet once is rebuilt.
2072  // this is needed because otherwise the UDP header length and checksum can not be calculated.
2073  if ( isFirst )
2074  {
2075  fragments->AddFirstFragment (packet);
2076  }
2077 
2078  if ( fragments->IsEntire () )
2079  {
2080  packet = fragments->GetPacket ();
2081  NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
2082 
2083  SixLowPanFrag1 frag1Header;
2084  packet->RemoveHeader (frag1Header);
2085 
2086  NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
2087  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
2088  fragments = 0;
2089  m_fragments.erase (key);
2090  return true;
2091  }
2092 
2093  return false;
2094 }
2095 
2097 {
2098  NS_LOG_FUNCTION (this);
2099  m_packetSize = 0;
2100 }
2101 
2103 {
2104  NS_LOG_FUNCTION (this);
2105 }
2106 
2107 void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
2108 {
2109  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
2110 
2111  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
2112  bool duplicate = false;
2113 
2114  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
2115  {
2116  if (it->second > fragmentOffset)
2117  {
2118  break;
2119  }
2120  if (it->second == fragmentOffset)
2121  {
2122  duplicate = true;
2123  NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
2124  break;
2125  }
2126  }
2127  if (!duplicate)
2128  {
2129  m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
2130  }
2131 }
2132 
2134 {
2135  NS_LOG_FUNCTION (this << *fragment);
2136 
2137  m_firstFragment = fragment;
2138 }
2139 
2141 {
2142  NS_LOG_FUNCTION (this);
2143 
2144  bool ret = m_fragments.size () > 0;
2145  uint16_t lastEndOffset = 0;
2146 
2147  if (ret)
2148  {
2149  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
2150  {
2151  // overlapping fragments should not exist
2152  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
2153 
2154  if (lastEndOffset < it->second)
2155  {
2156  ret = false;
2157  break;
2158  }
2159  // fragments might overlap in strange ways
2160  uint16_t fragmentEnd = it->first->GetSize () + it->second;
2161  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
2162  }
2163  }
2164 
2165  if ( ret && (lastEndOffset == m_packetSize))
2166  {
2167  return true;
2168  }
2169  return false;
2170 }
2171 
2173 {
2174  NS_LOG_FUNCTION (this);
2175 
2176  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2177 
2178  Ptr<Packet> p = Create<Packet> ();
2179  uint16_t lastEndOffset = 0;
2180 
2181  p->AddAtEnd (m_firstFragment);
2182  it = m_fragments.begin ();
2183  lastEndOffset = it->first->GetSize ();
2184 
2185  for ( it++; it != m_fragments.end (); it++)
2186  {
2187  if ( lastEndOffset > it->second )
2188  {
2189  NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2190  }
2191  else
2192  {
2193  NS_LOG_LOGIC ("Adding: " << *(it->first) );
2194  p->AddAtEnd (it->first);
2195  }
2196  lastEndOffset += it->first->GetSize ();
2197  }
2198 
2199  return p;
2200 }
2201 
2203 {
2204  NS_LOG_FUNCTION (this << packetSize);
2205  m_packetSize = packetSize;
2206 }
2207 
2208 std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2209 {
2210  std::list< Ptr<Packet> > fragments;
2211  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2212  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
2213  {
2214  fragments.push_back (iter->first);
2215  }
2216  return fragments;
2217 }
2218 
2219 void
2221 {
2222  m_timeoutIter = iter;
2223  return;
2224 }
2225 
2228 {
2229  return m_timeoutIter;
2230 }
2231 
2233 {
2234  NS_LOG_FUNCTION (this);
2235 
2236  MapFragments_t::iterator it = m_fragments.find (key);
2237  std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2238  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2239  fragIter != storedFragments.end (); fragIter++)
2240  {
2242  }
2243  // clear the buffers
2244  it->second = 0;
2245 
2246  m_fragments.erase (key);
2247 }
2248 
2250 {
2251  NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
2252 
2253  uint8_t buf[6];
2254  addr.CopyTo (buf);
2255 
2256  Mac16Address shortAddr;
2257  shortAddr.CopyFrom (buf + 4);
2258 
2259  return shortAddr;
2260 }
2261 
2263 {
2264  if (m_timeoutEventList.empty ())
2265  {
2267  }
2268  m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, iif);
2269 
2271 
2272  return (iter);
2273 }
2274 
2276 {
2277  Time now = Simulator::Now ();
2278 
2279  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
2280  {
2281  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
2282  std::get<2> (*m_timeoutEventList.begin ()));
2283  m_timeoutEventList.pop_front ();
2284  }
2285 
2286  if (m_timeoutEventList.empty ())
2287  {
2288  return;
2289  }
2290 
2291  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
2293 
2294  return;
2295 }
2296 
2297 }
2298 
2299 // namespace ns3
uint8_t GetEcn(void) const
Get the ECN.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
void DecompressLowPanUdpNhc(Ptr< Packet > packet, Ipv6Address saddr, Ipv6Address daddr)
Decompress the headers according to NHC compression.
static bool IsMatchingType(const Address &address)
uint8_t GetNextHeader(void) const
Get the Next Header field value.
Address GetOriginator(void) const
Get the "Originator" address.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
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:103
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:109
void SetDstCompression(LowPanHc1Addr_e dstCompression)
Set Destination Compression type.
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
uint8_t GetHopsLeft(void) const
Get the "Hops Left" field.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
EventId m_timeoutEvent
Event for the next scheduled timeout.
6LoWPAN IPv6 uncompressed header - see RFC 4944.
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:438
uint8_t GetDscp(void) const
Get the DSCP.
uint16_t GetDstPort() const
Get the Destination Port.
Hold variables of type string.
Definition: string.h:41
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
uint8_t GetSequenceNumber(void) const
Get the "Sequence Number" field.
virtual void SetIfIndex(const uint32_t index)
static Mac16Address ConvertFrom(const Address &address)
void SetPacketSize(uint32_t packetSize)
Set the packet-to-be-defragmented size.
void AddFirstFragment(Ptr< Packet > fragment)
Add the first packet fragment.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
static const uint32_t packetSize
Header of IPv6 Extension Routing.
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:85
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static bool ChecksumEnabled(void)
Definition: node.cc:278
LOWPAN_IPHC base Encoding - see RFC 6282.
automatically resized byte buffer
Definition: buffer.h:92
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:55
static Ipv6Address MakeAutoconfiguredAddress(Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address from a Mac address.
uint8_t GetNextHeader() const
Get the next header.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
void CopyFrom(const uint8_t buffer[2])
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static TypeId GetTypeId(void)
Get the type ID.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
virtual bool IsBroadcast(void) const
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
HeaderCompression_e GetSam(void) const
Get the SAM (Source Address Mode) compression.
uint16_t GetLength() const
Get the length of the extension.
std::list< std::tuple< Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
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:165
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.
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
#define max(a, b)
Definition: 80211b.c:43
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
Address GetFinalDst(void) const
Get the "Final Destination" address.
AttributeValue implementation for Time.
Definition: nstime.h:1353
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:49
std::map< Address, std::list< uint8_t > > m_seenPkts
Seen packets, memorized by OriginatorAdddress, SequenceNumber.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Ptr< Packet > GetPacket() const
Get the entire packet.
Ptr< RandomVariableStream > m_meshUnderJitter
Random variable for the mesh-under packet retransmission.
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
bool GetNh(void) const
Get the NH (Next Header) compression.
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
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
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
#define list
void SetSrcPort(uint16_t port)
Set the Source Port.
virtual Ptr< Channel > GetChannel(void) const
uint16_t GetChecksum()
Return the checksum (only known after a Deserialize)
Definition: udp-header.cc:241
Time m_fragmentExpirationTimeout
Time limit for fragment rebuilding.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
bool m_forceEtherType
Force the EtherType number.
virtual bool NeedsArp(void) const
virtual uint32_t GetIfIndex(void) const
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.
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:1354
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:195
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.
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:229
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
void SetSrcInterface(const uint8_t *srcInterface)
Set the source interface.
uint16_t m_etherType
EtherType number (used only if m_forceEtherType is true).
void 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:1289
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void SetFlowLabel(uint32_t flow)
Set the "Flow label" field.
Definition: ipv6-header.cc:55
LowPanHc1Addr_e GetSrcCompression() const
Get Source Compression type.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
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)
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
Definition: ipv6-header.cc:45
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
void SetNh(bool nhField)
Set the NH field values.
void SetTf(TrafficClassFlowLabel_e tfField)
Set the TF (Traffic Class, Flow Label) compression.
uint16_t m_meshCacheLength
length of the cache for each source.
uint16_t GetDatagramSize(void) const
Get the datagram size.
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:1386
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
uint32_t CopyBlob(uint8_t *blob, uint32_t size) const
Get the option header data blob.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:83
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
void SetEcn(uint8_t ecn)
Set the ECN (2bits).
bool GetC(void) const
Get the C (Checksum).
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
6LoWPAN FRAG1 header - see RFC 4944.
uint32_t CompressLowPanHc1(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to HC1 compression.
virtual Address GetBroadcast(void) const
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
a unique identifier for an interface.
Definition: type-id.h:58
bool GetDac(void) const
Get the DAC (Destination Address Compression) compression.
static const uint8_t PROT_NUMBER
protocol number (0x11)
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
uint8_t m_meshUnderHopsLeft
Start value for mesh-under hops left.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
uint32_t m_ifIndex
Interface index.
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
UDP LOWPAN_NHC Extension Header Encoding - see RFC 6282.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void SetC(bool cField)
Set the C (Checksum).
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.