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"
41#include "sixlowpan-header.h"
42
43NS_LOG_COMPONENT_DEFINE ("SixLowPanNetDevice");
44
45namespace ns3 {
46
47NS_OBJECT_ENSURE_REGISTERED (SixLowPanNetDevice);
48
50{
51 static TypeId tid = TypeId ("ns3::SixLowPanNetDevice")
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)),
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
161int64_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 ();
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
200 uint8_t dispatchRawVal = 0;
202 Ptr<Packet> copyPkt = packet->Copy ();
203
204 m_rxTrace (copyPkt, this, GetIfIndex ());
205
206 copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
207 dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
208 bool isPktDecompressed = false;
209 bool fragmented = false;
210
211 NS_LOG_DEBUG ( "Packet received: " << *copyPkt );
212 NS_LOG_DEBUG ( "Packet length: " << copyPkt->GetSize () );
213 NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal) );
214
215 SixLowPanMesh meshHdr;
216 SixLowPanBc0 bc0Hdr;
217 bool hasMesh = false;
218 bool hasBc0 = false;
219
220 if ( dispatchVal == SixLowPanDispatch::LOWPAN_MESH )
221 {
222 hasMesh = true;
223 copyPkt->RemoveHeader (meshHdr);
224 copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
225 dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
226 }
227 if ( dispatchVal == SixLowPanDispatch::LOWPAN_BC0 )
228 {
229 hasBc0 = true;
230 copyPkt->RemoveHeader (bc0Hdr);
231 copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
232 dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
233 }
234
235 if (hasMesh)
236 {
237 if (!hasBc0)
238 {
239 NS_LOG_LOGIC ("Dropped packet - we only support mesh if it is paired with a BC0");
240 m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, this, GetIfIndex ());
241 return;
242 }
243
244 if (find (m_seenPkts[meshHdr.GetOriginator ()].begin (),
245 m_seenPkts[meshHdr.GetOriginator ()].end (),
246 bc0Hdr.GetSequenceNumber ()) != m_seenPkts[meshHdr.GetOriginator ()].end ())
247 {
248 NS_LOG_LOGIC ("We have already seen this, no further processing.");
249 return;
250 }
251
252 m_seenPkts[meshHdr.GetOriginator ()].push_back (bc0Hdr.GetSequenceNumber ());
253 if (m_seenPkts[meshHdr.GetOriginator ()].size () > m_meshCacheLength)
254 {
255 m_seenPkts[meshHdr.GetOriginator ()].pop_front ();
256 }
257
258 NS_ABORT_MSG_IF (!Mac16Address::IsMatchingType (meshHdr.GetFinalDst ()), "SixLowPan mesh-under flooding can not currently handle extended address final destinations: " << meshHdr.GetFinalDst ());
259 NS_ABORT_MSG_IF (!Mac48Address::IsMatchingType (m_netDevice->GetAddress ()), "SixLowPan mesh-under flooding can not currently handle devices using extended addresses: " << m_netDevice->GetAddress ());
260
261 Mac16Address finalDst = Mac16Address::ConvertFrom (meshHdr.GetFinalDst ());
262
263 // See if the packet is for others than me. In case forward it.
265 || finalDst.IsBroadcast ()
266 || finalDst.IsMulticast ()
267 )
268 {
269 uint8_t hopsLeft = meshHdr.GetHopsLeft ();
270
271 if (hopsLeft == 0)
272 {
273 NS_LOG_LOGIC ("Not forwarding packet -- hop limit reached");
274 }
275 else if (meshHdr.GetOriginator () == Get16MacFrom48Mac (m_netDevice->GetAddress ()))
276 {
277 NS_LOG_LOGIC ("Not forwarding packet -- I am the originator");
278 }
279 else
280 {
281 meshHdr.SetHopsLeft (hopsLeft - 1);
282 Ptr<Packet> sendPkt = copyPkt->Copy ();
283 sendPkt->AddHeader (bc0Hdr);
284 sendPkt->AddHeader (meshHdr);
286 }
287
288 if (!finalDst.IsBroadcast () && !finalDst.IsMulticast ())
289 {
290 return;
291 }
292 }
293 }
294
295 Address realDst = dst;
296 Address realSrc = src;
297 if (hasMesh)
298 {
299 realSrc = meshHdr.GetOriginator ();
300 realDst = meshHdr.GetFinalDst ();
301 }
302
303 if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1 )
304 {
305 isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, true);
306 fragmented = true;
307 }
308 else if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN )
309 {
310 isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, false);
311 fragmented = true;
312 }
313 if ( fragmented )
314 {
315 if ( !isPktDecompressed )
316 {
317 return;
318 }
319 else
320 {
321 copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
322 dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
323 }
324 }
325
326 switch ( dispatchVal )
327 {
329 NS_LOG_DEBUG ( "Packet without compression. Length: " << copyPkt->GetSize () );
330 {
331 SixLowPanIpv6 uncompressedHdr;
332 copyPkt->RemoveHeader (uncompressedHdr);
333 isPktDecompressed = true;
334 }
335 break;
337 if (m_useIphc)
338 {
340 return;
341 }
342 DecompressLowPanHc1 (copyPkt, realSrc, realDst);
343 isPktDecompressed = true;
344 break;
346 if (!m_useIphc)
347 {
349 return;
350 }
351 if (DecompressLowPanIphc (copyPkt, realSrc, realDst))
352 {
354 }
355 else
356 {
357 isPktDecompressed = true;
358 }
359 break;
360 default:
361 NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
362 m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, this, GetIfIndex ());
363 break;
364 }
365
366 if ( !isPktDecompressed )
367 {
368 return;
369 }
370
371 NS_LOG_DEBUG ( "Packet decompressed length: " << copyPkt->GetSize () );
372 NS_LOG_DEBUG ( "Packet decompressed received: " << *copyPkt );
373
375 {
376 m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc, realDst, packetType);
377 }
378
379 m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc);
380
381 return;
382}
383
385{
386 NS_LOG_FUNCTION (this << index);
387 m_ifIndex = index;
388}
389
391{
392 NS_LOG_FUNCTION (this);
393 return m_ifIndex;
394}
395
397{
398 NS_LOG_FUNCTION (this);
399 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
400
401 return m_netDevice->GetChannel ();
402}
403
405{
406 NS_LOG_FUNCTION (this << address);
407 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
408
410}
411
413{
414 NS_LOG_FUNCTION (this);
415 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
416
417 return m_netDevice->GetAddress ();
418}
419
420bool SixLowPanNetDevice::SetMtu (const uint16_t mtu)
421{
422 NS_LOG_FUNCTION (this << mtu);
423 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
424
425 return m_netDevice->SetMtu (mtu);
426}
427
428uint16_t SixLowPanNetDevice::GetMtu (void) const
429{
430 NS_LOG_FUNCTION (this);
431
432 uint16_t mtu = m_netDevice->GetMtu ();
433
434 // RFC 4944, section 4.
435 if (mtu < 1280)
436 {
437 mtu = 1280;
438 }
439 return mtu;
440}
441
443{
444 NS_LOG_FUNCTION (this);
445 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
446
447 return m_netDevice->IsLinkUp ();
448}
449
451{
452 NS_LOG_FUNCTION (this);
453 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
454
455 return m_netDevice->AddLinkChangeCallback (callback);
456}
457
459{
460 NS_LOG_FUNCTION (this);
461 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
462
463 return m_netDevice->IsBroadcast ();
464}
465
467{
468 NS_LOG_FUNCTION (this);
469 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
470
471 return m_netDevice->GetBroadcast ();
472}
473
475{
476 NS_LOG_FUNCTION (this);
477 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
478
479 return m_netDevice->IsMulticast ();
480}
481
483{
484 NS_LOG_FUNCTION (this << multicastGroup);
485 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
486
487 return m_netDevice->GetMulticast (multicastGroup);
488}
489
491{
492 NS_LOG_FUNCTION (this << addr);
493 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
494
495 return m_netDevice->GetMulticast (addr);
496}
497
499{
500 NS_LOG_FUNCTION (this);
501 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
502
503 return m_netDevice->IsPointToPoint ();
504}
505
507{
508 NS_LOG_FUNCTION (this);
509 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
510
511 return m_netDevice->IsBridge ();
512}
513
515 const Address& dest,
516 uint16_t protocolNumber)
517{
518 NS_LOG_FUNCTION (this << *packet << dest << protocolNumber);
519 bool ret = false;
520 Address src;
521
522 ret = DoSend (packet, src, dest, protocolNumber, false);
523 return ret;
524}
525
527 const Address& src,
528 const Address& dest,
529 uint16_t protocolNumber)
530{
531 NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber);
532 bool ret = false;
533
534 ret = DoSend (packet, src, dest, protocolNumber, true);
535 return ret;
536}
537
539 const Address& src,
540 const Address& dest,
541 uint16_t protocolNumber,
542 bool doSendFrom)
543{
544 NS_LOG_FUNCTION (this << *packet << src << dest << protocolNumber << doSendFrom);
545 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
546
547 Ptr<Packet> origPacket = packet->Copy ();
548 uint32_t origHdrSize = 0;
549 uint32_t origPacketSize = packet->GetSize ();
550 bool ret = false;
551
552 Address destination = dest;
553
554 bool useMesh = m_meshUnder;
555
557 {
558 protocolNumber = m_etherType;
559 }
560
561 if (m_useIphc)
562 {
563 NS_LOG_LOGIC ("Compressing packet using IPHC");
564 origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), destination);
565 }
566 else
567 {
568 NS_LOG_LOGIC ("Compressing packet using HC1");
569 origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), destination);
570 }
571
572 uint16_t pktSize = packet->GetSize ();
573
574 SixLowPanMesh meshHdr;
575 SixLowPanBc0 bc0Hdr;
576 uint32_t extraHdrSize = 0;
577
578 if (useMesh)
579 {
580 Address source = src;
581 if (!doSendFrom)
582 {
583 source = m_netDevice->GetAddress ();
584 }
585
586 if (Mac48Address::IsMatchingType (source))
587 {
588 // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
589 source = Get16MacFrom48Mac (source);
590 }
591 if (Mac48Address::IsMatchingType (destination))
592 {
593 // We got a Mac48 pseudo-MAC. We need its original Mac16 here.
594 destination = Get16MacFrom48Mac (destination);
595 }
596
597 meshHdr.SetOriginator (source);
598 meshHdr.SetFinalDst (destination);
600 destination = m_netDevice->GetBroadcast ();
601 // We are storing sum of mesh and bc0 header sizes. We will need it if packet is fragmented.
602 extraHdrSize = meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
603 pktSize += extraHdrSize;
604 }
605
607 {
608 NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
609 packet = origPacket;
610 SixLowPanIpv6 ipv6UncompressedHdr;
611 packet->AddHeader (ipv6UncompressedHdr);
612 pktSize = packet->GetSize ();
613 if (useMesh)
614 {
615 pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
616 }
617 }
618
619
620 if (pktSize > m_netDevice->GetMtu ())
621 {
622 NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
623 // fragment
624 std::list<Ptr<Packet> > fragmentList;
625 DoFragmentation (packet, origPacketSize, origHdrSize, extraHdrSize, fragmentList);
626 std::list<Ptr<Packet> >::iterator it;
627 bool success = true;
628 for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
629 {
630 NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
631 m_txTrace (*it, this, GetIfIndex ());
632
633 if (useMesh)
634 {
636 (*it)->AddHeader (bc0Hdr);
637 (*it)->AddHeader (meshHdr);
638 }
639 if (doSendFrom)
640 {
641 success &= m_netDevice->SendFrom (*it, src, destination, protocolNumber);
642 }
643 else
644 {
645 success &= m_netDevice->Send (*it, destination, protocolNumber);
646 }
647 }
648 ret = success;
649 }
650 else
651 {
652 m_txTrace (packet, this, GetIfIndex ());
653
654 if (useMesh)
655 {
657 packet->AddHeader (bc0Hdr);
658 packet->AddHeader (meshHdr);
659 }
660
661 if (doSendFrom)
662 {
663 NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
664 ret = m_netDevice->SendFrom (packet, src, destination, protocolNumber);
665 }
666 else
667 {
668 NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
669 ret = m_netDevice->Send (packet, destination, protocolNumber);
670 }
671 }
672
673 return ret;
674}
675
677{
678 NS_LOG_FUNCTION (this);
679 return m_node;
680}
681
683{
684 NS_LOG_FUNCTION (this << node);
685 m_node = node;
686}
687
689{
690 NS_LOG_FUNCTION (this);
691 NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
692
693 return m_netDevice->NeedsArp ();
694}
695
697{
698 NS_LOG_FUNCTION (this << &cb);
699 m_rxCallback = cb;
700}
701
703{
704 NS_LOG_FUNCTION (this << &cb);
706}
707
709{
710 NS_LOG_FUNCTION (this);
711 return true;
712}
713
716{
717 NS_LOG_FUNCTION (this << *packet << src << dst);
718
719 Ipv6Header ipHeader;
720 SixLowPanHc1 hc1Header;
721 uint32_t size = 0;
722
723 NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () );
724
725 if ( packet->PeekHeader (ipHeader) != 0 )
726 {
727 packet->RemoveHeader (ipHeader);
728 size += ipHeader.GetSerializedSize ();
729
730 hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
731
732 uint8_t bufOne[16];
733 uint8_t bufTwo[16];
734 Ipv6Address srcAddr = ipHeader.GetSource ();
735 srcAddr.GetBytes (bufOne);
737
738 NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
739
740 mySrcAddr.GetBytes (bufTwo);
741 bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
742
743 if (srcAddr.IsLinkLocal () && isSrcSrc )
744 {
746 }
747 else if (srcAddr.IsLinkLocal () )
748 {
750 hc1Header.SetSrcInterface (bufOne + 8);
751 }
752 else if ( isSrcSrc )
753 {
755 hc1Header.SetSrcPrefix (bufOne);
756 }
757 else
758 {
760 hc1Header.SetSrcInterface (bufOne + 8);
761 hc1Header.SetSrcPrefix (bufOne);
762 }
763
764 Ipv6Address dstAddr = ipHeader.GetDestination ();
765 dstAddr.GetBytes (bufOne);
767
768 NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
769
770 myDstAddr.GetBytes (bufTwo);
771 bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
772
773 if (dstAddr.IsLinkLocal () && isDstDst )
774 {
776 }
777 else if (dstAddr.IsLinkLocal () )
778 {
780 hc1Header.SetDstInterface (bufOne + 8);
781 }
782 else if ( isDstDst )
783 {
785 hc1Header.SetDstPrefix (bufOne);
786 }
787 else
788 {
790 hc1Header.SetDstInterface (bufOne + 8);
791 hc1Header.SetDstPrefix (bufOne);
792 }
793
794 if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
795 {
796 hc1Header.SetTcflCompression (true);
797 }
798 else
799 {
800 hc1Header.SetTcflCompression (false);
801 hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
802 hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
803 }
804
805 uint8_t nextHeader = ipHeader.GetNextHeader ();
806 hc1Header.SetNextHeader (nextHeader);
807
808 // \todo implement HC2 compression
809 hc1Header.SetHc2HeaderPresent (false);
810
811 NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
812 NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
813
814 packet->AddHeader (hc1Header);
815
816 return size;
817 }
818
819 return 0;
820}
821
822void
824{
825 NS_LOG_FUNCTION (this << *packet << src << dst);
826
827 Ipv6Header ipHeader;
828 SixLowPanHc1 encoding;
829
830 [[maybe_unused]] uint32_t ret = packet->RemoveHeader (encoding);
831 NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
832
833 ipHeader.SetHopLimit (encoding.GetHopLimit ());
834
835 switch (encoding.GetSrcCompression ())
836 {
837 const uint8_t* interface;
838 const uint8_t* prefix;
839 uint8_t address[16];
840
842 prefix = encoding.GetSrcPrefix ();
843 interface = encoding.GetSrcInterface ();
844 for (int j = 0; j < 8; j++)
845 {
846 address[j + 8] = interface[j];
847 address[j] = prefix[j];
848 }
849 ipHeader.SetSource ( Ipv6Address (address) );
850 break;
852 prefix = encoding.GetSrcPrefix ();
853 for (int j = 0; j < 8; j++)
854 {
855 address[j + 8] = 0;
856 address[j] = prefix[j];
857 }
859 break;
861 interface = encoding.GetSrcInterface ();
862 address[0] = 0xfe;
863 address[1] = 0x80;
864 for (int j = 0; j < 8; j++)
865 {
866 address[j + 8] = interface[j];
867 }
868 ipHeader.SetSource ( Ipv6Address (address) );
869 break;
872 break;
873 }
874
875 switch (encoding.GetDstCompression ())
876 {
877 const uint8_t* interface;
878 const uint8_t* prefix;
879 uint8_t address[16];
880
882 prefix = encoding.GetDstPrefix ();
883 interface = encoding.GetDstInterface ();
884 for (int j = 0; j < 8; j++)
885 {
886 address[j + 8] = interface[j];
887 address[j] = prefix[j];
888 }
889 ipHeader.SetDestination ( Ipv6Address (address) );
890 break;
892 prefix = encoding.GetDstPrefix ();
893 for (int j = 0; j < 8; j++)
894 {
895 address[j + 8] = 0;
896 address[j] = prefix[j];
897 }
899 break;
901 interface = encoding.GetDstInterface ();
902 address[0] = 0xfe;
903 address[1] = 0x80;
904 for (int j = 0; j < 8; j++)
905 {
906 address[j + 8] = interface[j];
907 }
908 ipHeader.SetDestination ( Ipv6Address (address) );
909 break;
912 break;
913 }
914
915 if ( !encoding.IsTcflCompression () )
916 {
917 ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
918 ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
919 }
920 else
921 {
922 ipHeader.SetFlowLabel (0);
923 ipHeader.SetTrafficClass (0);
924 }
925
926 ipHeader.SetNextHeader (encoding.GetNextHeader ());
927
928 ipHeader.SetPayloadLength (packet->GetSize ());
929
930 NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
931 "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
932
933 packet->AddHeader (ipHeader);
934
935 NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
936}
937
940{
941 NS_LOG_FUNCTION (this << *packet << src << dst);
942
943 Ipv6Header ipHeader;
944 SixLowPanIphc iphcHeader;
945 uint32_t size = 0;
946
947 NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () << " src: " << src << " dst: " << dst);
948
949 if ( packet->PeekHeader (ipHeader) != 0 )
950 {
951 packet->RemoveHeader (ipHeader);
952 size += ipHeader.GetSerializedSize ();
953
954 // Set the TF field
955 if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
956 {
957 iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
958 }
959 else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
960 {
961 iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
962 iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
963 iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
964 iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
965 }
966 else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
967 {
969 iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
970 iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
971 }
972 else
973 {
975 iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
976 iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
977 }
978
979 // Set the NH field and NextHeader
980
981 uint8_t nextHeader = ipHeader.GetNextHeader ();
982 if (CanCompressLowPanNhc (nextHeader))
983 {
984 if (nextHeader == Ipv6Header::IPV6_UDP)
985 {
986 iphcHeader.SetNh (true);
987 size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
988 }
989 else if (nextHeader == Ipv6Header::IPV6_IPV6)
990 {
991 iphcHeader.SetNh (true);
992 size += CompressLowPanIphc (packet, src, dst);
993 }
994 else
995 {
996 uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
997 // the compression might fail due to Extension header size.
998 if (sizeNhc)
999 {
1000 iphcHeader.SetNh (true);
1001 size += sizeNhc;
1002 }
1003 else
1004 {
1005 iphcHeader.SetNh (false);
1006 iphcHeader.SetNextHeader (nextHeader);
1007 }
1008 }
1009 }
1010 else
1011 {
1012 iphcHeader.SetNh (false);
1013 iphcHeader.SetNextHeader (nextHeader);
1014 }
1015
1016 // Set the HLIM field
1017 if (ipHeader.GetHopLimit () == 1)
1018 {
1020 }
1021 else if (ipHeader.GetHopLimit () == 0x40)
1022 {
1024 }
1025 else if (ipHeader.GetHopLimit () == 0xFF)
1026 {
1028 }
1029 else
1030 {
1032 // Set the HopLimit
1033 iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
1034 }
1035
1036 // Set the CID + SAC + DAC fields to their default value
1037 iphcHeader.SetCid (false);
1038 iphcHeader.SetSac (false);
1039 iphcHeader.SetDac (false);
1040
1041
1042 Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
1043 uint8_t unicastAddrCheckerBuf[16];
1044 checker.GetBytes (unicastAddrCheckerBuf);
1045 uint8_t addressBuf[16];
1046
1047 // This is just to limit the scope of some variables.
1048 if (true)
1049 {
1050 Ipv6Address srcAddr = ipHeader.GetSource ();
1051 uint8_t srcContextId;
1052
1053 // The "::" address is compressed as a fake stateful compression.
1054 if (srcAddr == Ipv6Address::GetAny ())
1055 {
1056 // No context information is needed.
1057 iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1058 iphcHeader.SetSac (true);
1059 }
1060 // Check if the address can be compressed with stateful compression
1061 else if ( FindUnicastCompressionContext (srcAddr, srcContextId) )
1062 {
1063 // We can do stateful compression.
1064 NS_LOG_LOGIC ("Checking stateful source compression: " << srcAddr );
1065
1066 iphcHeader.SetSac (true);
1067 if (srcContextId != 0)
1068 {
1069 // the default context is zero, no need to explicit it if it's zero
1070 iphcHeader.SetSrcContextId (srcContextId);
1071 iphcHeader.SetCid (true);
1072 }
1073
1074 // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1075
1076 if (Ipv6Address::MakeAutoconfiguredAddress (src, m_contextTable[srcContextId].contextPrefix) == srcAddr)
1077 {
1078 iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1079 }
1080 else
1081 {
1082 Ipv6Address cleanedAddr = CleanPrefix (srcAddr, m_contextTable[srcContextId].contextPrefix);
1083 uint8_t serializedCleanedAddress[16];
1084 cleanedAddr.Serialize (serializedCleanedAddress);
1085
1086 if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1087 serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1088 serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1089 {
1091 iphcHeader.SetSrcInlinePart (serializedCleanedAddress+14, 2);
1092 }
1093 else
1094 {
1096 iphcHeader.SetSrcInlinePart (serializedCleanedAddress+8, 8);
1097
1098 }
1099 }
1100 }
1101 else
1102 {
1103 // We must do stateless compression.
1104 NS_LOG_LOGIC ("Checking stateless source compression: " << srcAddr );
1105
1106 srcAddr.GetBytes (addressBuf);
1107
1108 uint8_t serializedSrcAddress[16];
1109 srcAddr.Serialize (serializedSrcAddress);
1110
1112 {
1113 iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
1114 }
1115 else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1116 {
1117 iphcHeader.SetSrcInlinePart (serializedSrcAddress+14, 2);
1119 }
1120 else if ( srcAddr.IsLinkLocal () )
1121 {
1122 iphcHeader.SetSrcInlinePart (serializedSrcAddress+8, 8);
1124 }
1125 else
1126 {
1127 iphcHeader.SetSrcInlinePart (serializedSrcAddress, 16);
1128 iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
1129 }
1130 }
1131 }
1132
1133 // Set the M field
1134 if (ipHeader.GetDestination ().IsMulticast ())
1135 {
1136 iphcHeader.SetM (true);
1137 }
1138 else
1139 {
1140 iphcHeader.SetM (false);
1141 }
1142
1143 // This is just to limit the scope of some variables.
1144 if (true)
1145 {
1146 Ipv6Address dstAddr = ipHeader.GetDestination ();
1147 dstAddr.GetBytes (addressBuf);
1148
1149 NS_LOG_LOGIC ("Checking destination compression: " << dstAddr );
1150
1151 uint8_t serializedDstAddress[16];
1152 dstAddr.Serialize (serializedDstAddress);
1153
1154 if ( !iphcHeader.GetM () )
1155 {
1156 // Unicast address
1157
1158 uint8_t dstContextId;
1159 if ( FindUnicastCompressionContext (dstAddr, dstContextId) )
1160 {
1161 // We can do stateful compression.
1162 NS_LOG_LOGIC ("Checking stateful destination compression: " << dstAddr );
1163
1164 iphcHeader.SetDac (true);
1165 if (dstContextId != 0)
1166 {
1167 // the default context is zero, no need to explicit it if it's zero
1168 iphcHeader.SetDstContextId (dstContextId);
1169 iphcHeader.SetCid (true);
1170 }
1171
1172 // Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
1173 if (Ipv6Address::MakeAutoconfiguredAddress (dst, m_contextTable[dstContextId].contextPrefix) == dstAddr)
1174 {
1175 iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1176 }
1177 else
1178 {
1179 Ipv6Address cleanedAddr = CleanPrefix (dstAddr, m_contextTable[dstContextId].contextPrefix);
1180
1181 uint8_t serializedCleanedAddress[16];
1182 cleanedAddr.Serialize (serializedCleanedAddress);
1183
1184 if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
1185 serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
1186 serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
1187 {
1189 iphcHeader.SetDstInlinePart (serializedCleanedAddress+14, 2);
1190 }
1191 else
1192 {
1194 iphcHeader.SetDstInlinePart (serializedCleanedAddress+8, 8);
1195 }
1196 }
1197 }
1198 else
1199 {
1200 NS_LOG_LOGIC ("Checking stateless destination compression: " << dstAddr );
1201
1203 {
1204 iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1205 }
1206 else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
1207 {
1208 iphcHeader.SetDstInlinePart (serializedDstAddress+14, 2);
1210 }
1211 else if ( dstAddr.IsLinkLocal () )
1212 {
1213 iphcHeader.SetDstInlinePart (serializedDstAddress+8, 8);
1215 }
1216 else
1217 {
1218 iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1219 iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1220 }
1221 }
1222 }
1223 else
1224 {
1225 // Multicast address
1226
1227 uint8_t dstContextId;
1228 if ( FindMulticastCompressionContext (dstAddr, dstContextId) )
1229 {
1230 // Stateful compression (only one possible case)
1231
1232 // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1233 uint8_t dstInlinePart[6] = {};
1234 dstInlinePart[0] = serializedDstAddress[1];
1235 dstInlinePart[1] = serializedDstAddress[2];
1236 dstInlinePart[2] = serializedDstAddress[12];
1237 dstInlinePart[3] = serializedDstAddress[13];
1238 dstInlinePart[4] = serializedDstAddress[14];
1239 dstInlinePart[5] = serializedDstAddress[15];
1240
1241 iphcHeader.SetDac (true);
1242 if (dstContextId != 0)
1243 {
1244 // the default context is zero, no need to explicit it if it's zero
1245 iphcHeader.SetDstContextId (dstContextId);
1246 iphcHeader.SetCid (true);
1247 }
1248 iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1249 iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1250 }
1251 else
1252 {
1253 // Stateless compression
1254
1255 uint8_t multicastAddrCheckerBuf[16];
1256 Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
1257 multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
1258
1259 // The address takes the form ff02::00XX.
1260 if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
1261 {
1262 iphcHeader.SetDstInlinePart (serializedDstAddress+15, 1);
1263 iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
1264 }
1265 // The address takes the form ffXX::00XX:XXXX.
1266 // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
1267 else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1268 && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
1269 {
1270 uint8_t dstInlinePart[4] = {};
1271 memcpy (dstInlinePart, serializedDstAddress+1, 1);
1272 memcpy (dstInlinePart+1, serializedDstAddress+13, 3);
1273 iphcHeader.SetDstInlinePart (dstInlinePart, 4);
1275 }
1276 // The address takes the form ffXX::00XX:XXXX:XXXX.
1277 // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
1278 else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
1279 && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
1280 {
1281 uint8_t dstInlinePart[6] = {};
1282 memcpy (dstInlinePart, serializedDstAddress+1, 1);
1283 memcpy (dstInlinePart+1, serializedDstAddress+11, 5);
1284 iphcHeader.SetDstInlinePart (dstInlinePart, 6);
1286 }
1287 else
1288 {
1289 iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
1290 iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
1291 }
1292 }
1293 }
1294 }
1295
1296 NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
1297 NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
1298
1299 packet->AddHeader (iphcHeader);
1300
1301 NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
1302
1303 return size;
1304 }
1305 return 0;
1306}
1307
1308bool
1310{
1311 bool ret = false;
1312
1313 switch (nextHeader)
1314 {
1320 ret = true;
1321 break;
1323 default:
1324 ret = false;
1325 }
1326 return ret;
1327}
1328
1329bool
1331{
1332 NS_LOG_FUNCTION (this << *packet << src << dst);
1333
1334 Ipv6Header ipHeader;
1335 SixLowPanIphc encoding;
1336
1337 [[maybe_unused]] uint32_t ret = packet->RemoveHeader (encoding);
1338 NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1339
1340 // Hop Limit
1341 ipHeader.SetHopLimit (encoding.GetHopLimit ());
1342
1343 // Source address
1344 if ( encoding.GetSac () )
1345 {
1346 // Source address compression uses stateful, context-based compression.
1347 if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1348 {
1349 ipHeader.SetSource ( Ipv6Address::GetAny () );
1350 }
1351 else
1352 {
1353 uint8_t contextId = encoding.GetSrcContextId ();
1354 if (m_contextTable.find (contextId) == m_contextTable.end ())
1355 {
1356 NS_LOG_LOGIC ("Unknown Source compression context (" << +contextId << "), dropping packet");
1357 return true;
1358 }
1359 if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1360 {
1361 NS_LOG_LOGIC ("Expired Source compression context (" << +contextId << "), dropping packet");
1362 return true;
1363 }
1364
1365 uint8_t contexPrefix[16];
1366 m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1367 uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1368
1369 uint8_t srcAddress[16] = { };
1370 if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1371 {
1372 memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1373 }
1374 else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1375 {
1376 srcAddress[11] = 0xff;
1377 srcAddress[12] = 0xfe;
1378 memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1379 }
1380 else // SixLowPanIphc::HC_COMPR_0
1381 {
1383 }
1384
1385 uint8_t bytesToCopy = contextLength / 8;
1386 uint8_t bitsToCopy = contextLength % 8;
1387
1388 // Do not combine the prefix - we want to override the bytes.
1389 for (uint8_t i=0; i<bytesToCopy; i++)
1390 {
1391 srcAddress[i] = contexPrefix[i];
1392 }
1393 if (bitsToCopy)
1394 {
1395 uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1396 uint8_t prefixBitMask = ~addressBitMask;
1397 srcAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (srcAddress[bytesToCopy] & addressBitMask);
1398 }
1399 ipHeader.SetSource ( Ipv6Address::Deserialize (srcAddress) );
1400 }
1401 }
1402 else
1403 {
1404 // Source address compression uses stateless compression.
1405
1406 if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
1407 {
1408 uint8_t srcAddress[16] = { };
1409 memcpy (srcAddress, encoding.GetSrcInlinePart (), 16);
1410 ipHeader.SetSource ( Ipv6Address::Deserialize (srcAddress) );
1411 }
1412 else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
1413 {
1414 uint8_t srcAddress[16] = { };
1415 memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
1416 srcAddress[0] = 0xfe;
1417 srcAddress[1] = 0x80;
1418 ipHeader.SetSource ( Ipv6Address::Deserialize (srcAddress) );
1419 }
1420 else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
1421 {
1422 uint8_t srcAddress[16] = { };
1423 memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
1424 srcAddress[0] = 0xfe;
1425 srcAddress[1] = 0x80;
1426 srcAddress[11] = 0xff;
1427 srcAddress[12] = 0xfe;
1428 ipHeader.SetSource ( Ipv6Address::Deserialize (srcAddress) );
1429 }
1430 else // SixLowPanIphc::HC_COMPR_0
1431 {
1433 }
1434 }
1435 // Destination address
1436 if ( encoding.GetDac () )
1437 {
1438 // Destination address compression uses stateful, context-based compression.
1439 if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
1440 || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
1441 || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
1442 || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
1443 {
1444 NS_ABORT_MSG ("Reserved code found");
1445 }
1446
1447 uint8_t contextId = encoding.GetDstContextId ();
1448 if (m_contextTable.find (contextId) == m_contextTable.end ())
1449 {
1450 NS_LOG_LOGIC ("Unknown Destination compression context (" << +contextId << "), dropping packet");
1451 return true;
1452 }
1453 if (m_contextTable[contextId].validLifetime < Simulator::Now ())
1454 {
1455 NS_LOG_LOGIC ("Expired Destination compression context (" << +contextId << "), dropping packet");
1456 return true;
1457 }
1458
1459 uint8_t contexPrefix[16];
1460 m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
1461 uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
1462
1463 if (encoding.GetM () == false)
1464 {
1465 // unicast
1466 uint8_t dstAddress[16] = { };
1467 if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1468 {
1469 memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1470 }
1471 else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1472 {
1473 dstAddress[11] = 0xff;
1474 dstAddress[12] = 0xfe;
1475 memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1476 }
1477 else // SixLowPanIphc::HC_COMPR_0
1478 {
1480 }
1481
1482 uint8_t bytesToCopy = m_contextTable[contextId].contextPrefix.GetPrefixLength () / 8;
1483 uint8_t bitsToCopy = contextLength % 8;
1484
1485 // Do not combine the prefix - we want to override the bytes.
1486 for (uint8_t i=0; i<bytesToCopy; i++)
1487 {
1488 dstAddress[i] = contexPrefix[i];
1489 }
1490 if (bitsToCopy)
1491 {
1492 uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
1493 uint8_t prefixBitMask = ~addressBitMask;
1494 dstAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (dstAddress[bytesToCopy] & addressBitMask);
1495 }
1496 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1497 }
1498 else
1499 {
1500 // multicast
1501 // Just one possibility: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1502 uint8_t dstAddress[16] = { };
1503 dstAddress[0] = 0xff;
1504 memcpy (dstAddress +1, encoding.GetDstInlinePart (), 2);
1505 dstAddress[3] = contextLength;
1506 memcpy (dstAddress +4, contexPrefix, 8);
1507 memcpy (dstAddress +12, encoding.GetDstInlinePart ()+2, 4);
1508 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1509 }
1510 }
1511 else
1512 {
1513 // Destination address compression uses stateless compression.
1514 if (encoding.GetM () == false)
1515 {
1516 // unicast
1517 if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1518 {
1519 uint8_t dstAddress[16] = { };
1520 memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1521 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1522 }
1523 else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1524 {
1525 uint8_t dstAddress[16] = { };
1526 memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
1527 dstAddress[0] = 0xfe;
1528 dstAddress[1] = 0x80;
1529 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1530 }
1531 else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1532 {
1533 uint8_t dstAddress[16] = { };
1534 memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
1535 dstAddress[0] = 0xfe;
1536 dstAddress[1] = 0x80;
1537 dstAddress[11] = 0xff;
1538 dstAddress[12] = 0xfe;
1539 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1540 }
1541 else // SixLowPanIphc::HC_COMPR_0
1542 {
1544 }
1545 }
1546 else
1547 {
1548 // multicast
1549 if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
1550 {
1551 uint8_t dstAddress[16] = { };
1552 memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
1553 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1554 }
1555 else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
1556 {
1557 uint8_t dstAddress[16] = { };
1558 dstAddress[0] = 0xff;
1559 memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1560 memcpy (dstAddress +11, encoding.GetDstInlinePart ()+1, 5);
1561 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1562 }
1563 else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
1564 {
1565 uint8_t dstAddress[16] = { };
1566 dstAddress[0] = 0xff;
1567 memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
1568 memcpy (dstAddress +13, encoding.GetDstInlinePart ()+1, 3);
1569 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1570 }
1571 else // SixLowPanIphc::HC_COMPR_0
1572 {
1573 uint8_t dstAddress[16] = { };
1574 dstAddress[0] = 0xff;
1575 dstAddress[1] = 0x02;
1576 memcpy (dstAddress+15, encoding.GetDstInlinePart (), 1);
1577 ipHeader.SetDestination ( Ipv6Address::Deserialize (dstAddress) );
1578 }
1579 }
1580 }
1581
1582 // Traffic class and Flow Label
1583 uint8_t traf = 0x00;
1584 switch (encoding.GetTf ())
1585 {
1587 traf |= encoding.GetEcn ();
1588 traf = ( traf << 6 ) | encoding.GetDscp ();
1589 ipHeader.SetTrafficClass (traf);
1590 ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
1591 break;
1593 traf |= encoding.GetEcn ();
1594 traf <<= 2; // Add 2-bit pad
1595 ipHeader.SetTrafficClass (traf);
1596 ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
1597 break;
1599 traf |= encoding.GetEcn ();
1600 traf = ( traf << 6 ) | encoding.GetDscp ();
1601 ipHeader.SetTrafficClass (traf);
1602 ipHeader.SetFlowLabel (0);
1603 break;
1605 ipHeader.SetFlowLabel (0);
1606 ipHeader.SetTrafficClass (0);
1607 break;
1608 }
1609
1610 if ( encoding.GetNh () )
1611 {
1612 // Next Header
1613 uint8_t dispatchRawVal = 0;
1615
1616 packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1617 dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1618
1619 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1620 {
1622 DecompressLowPanUdpNhc (packet, ipHeader.GetSource (), ipHeader.GetDestination ());
1623 }
1624 else
1625 {
1626 std::pair <uint8_t, bool> retval = DecompressLowPanNhc (packet, src, dst, ipHeader.GetSource (), ipHeader.GetDestination ());
1627 if ( retval.second == true )
1628 {
1629 return true;
1630 }
1631 else
1632 {
1633 ipHeader.SetNextHeader (retval.first);
1634 }
1635 }
1636 }
1637 else
1638 {
1639 ipHeader.SetNextHeader (encoding.GetNextHeader ());
1640 }
1641
1642 ipHeader.SetPayloadLength (packet->GetSize ());
1643
1644 packet->AddHeader (ipHeader);
1645
1646 NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
1647
1648 return false;
1649}
1650
1652SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst)
1653{
1654 NS_LOG_FUNCTION (this << *packet << int(headerType));
1655
1656 SixLowPanNhcExtension nhcHeader;
1657 uint32_t size = 0;
1658 Buffer blob;
1659
1660 if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1661 {
1663 packet->PeekHeader (hopHeader);
1664 if (hopHeader.GetLength () >= 0xff)
1665 {
1666 NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1667 "that have more than 255 octets following the Length field after compression. "
1668 "Packet uncompressed.");
1669 return 0;
1670 }
1671
1672 size += packet->RemoveHeader (hopHeader);
1674
1675 // recursively compress other headers
1676 uint8_t nextHeader = hopHeader.GetNextHeader ();
1677 if (CanCompressLowPanNhc (nextHeader))
1678 {
1679 if (nextHeader == Ipv6Header::IPV6_UDP)
1680 {
1681 nhcHeader.SetNh (true);
1682 size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1683 }
1684 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1685 {
1686 nhcHeader.SetNh (true);
1687 size += CompressLowPanIphc (packet, src, dst);
1688 }
1689 else
1690 {
1691 uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1692 // the compression might fail due to Extension header size.
1693 if (sizeNhc)
1694 {
1695 nhcHeader.SetNh (true);
1696 size += sizeNhc;
1697 }
1698 else
1699 {
1700 nhcHeader.SetNh (false);
1701 nhcHeader.SetNextHeader (nextHeader);
1702 }
1703 }
1704 }
1705 else
1706 {
1707 nhcHeader.SetNh (false);
1708 nhcHeader.SetNextHeader (nextHeader);
1709 }
1710
1711 uint32_t blobSize = hopHeader.GetSerializedSize ();
1712 blob.AddAtStart (blobSize);
1713 hopHeader.Serialize (blob.Begin ());
1714 blob.RemoveAtStart (2);
1715 blobSize = blob.GetSize ();
1716 nhcHeader.SetBlob (blob.PeekData (), blobSize);
1717 }
1718 else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
1719 {
1720 Ipv6ExtensionRoutingHeader routingHeader;
1721 packet->PeekHeader (routingHeader);
1722 if (routingHeader.GetLength () >= 0xff)
1723 {
1724 NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1725 "that have more than 255 octets following the Length field after compression. "
1726 "Packet uncompressed.");
1727 return 0;
1728 }
1729
1730 size += packet->RemoveHeader (routingHeader);
1732
1733 // recursively compress other headers
1734 uint8_t nextHeader = routingHeader.GetNextHeader ();
1735 if (CanCompressLowPanNhc (nextHeader))
1736 {
1737 if (nextHeader == Ipv6Header::IPV6_UDP)
1738 {
1739 nhcHeader.SetNh (true);
1740 size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1741 }
1742 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1743 {
1744 nhcHeader.SetNh (true);
1745 size += CompressLowPanIphc (packet, src, dst);
1746 }
1747 else
1748 {
1749 uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1750 // the compression might fail due to Extension header size.
1751 if (sizeNhc)
1752 {
1753 nhcHeader.SetNh (true);
1754 size += sizeNhc;
1755 }
1756 else
1757 {
1758 nhcHeader.SetNh (false);
1759 nhcHeader.SetNextHeader (nextHeader);
1760 }
1761 }
1762 }
1763 else
1764 {
1765 nhcHeader.SetNh (false);
1766 nhcHeader.SetNextHeader (nextHeader);
1767 }
1768
1769 uint32_t blobSize = routingHeader.GetSerializedSize ();
1770 blob.AddAtStart (blobSize);
1771 routingHeader.Serialize (blob.Begin ());
1772 blob.RemoveAtStart (2);
1773 blobSize = blob.GetSize ();
1774 nhcHeader.SetBlob (blob.PeekData (), blobSize);
1775 }
1776 else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
1777 {
1778 Ipv6ExtensionFragmentHeader fragHeader;
1779 packet->PeekHeader (fragHeader);
1780 if (fragHeader.GetLength () >= 0xff)
1781 {
1782 NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1783 "that have more than 255 octets following the Length field after compression. "
1784 "Packet uncompressed.");
1785 return 0;
1786 }
1787 size += packet->RemoveHeader (fragHeader);
1789
1790 // recursively compress other headers
1791 uint8_t nextHeader = fragHeader.GetNextHeader ();
1792 if (CanCompressLowPanNhc (nextHeader))
1793 {
1794 if (nextHeader == Ipv6Header::IPV6_UDP)
1795 {
1796 nhcHeader.SetNh (true);
1797 size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1798 }
1799 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1800 {
1801 nhcHeader.SetNh (true);
1802 size += CompressLowPanIphc (packet, src, dst);
1803 }
1804 else
1805 {
1806 uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1807 // the compression might fail due to Extension header size.
1808 if (sizeNhc)
1809 {
1810 nhcHeader.SetNh (true);
1811 size += sizeNhc;
1812 }
1813 else
1814 {
1815 nhcHeader.SetNh (false);
1816 nhcHeader.SetNextHeader (nextHeader);
1817 }
1818 }
1819 }
1820 else
1821 {
1822 nhcHeader.SetNh (false);
1823 nhcHeader.SetNextHeader (nextHeader);
1824 }
1825
1826 uint32_t blobSize = fragHeader.GetSerializedSize ();
1827 blob.AddAtStart (blobSize);
1828 fragHeader.Serialize (blob.Begin ());
1829 blob.RemoveAtStart (2);
1830 blobSize = blob.GetSize ();
1831 nhcHeader.SetBlob (blob.PeekData (), blobSize);
1832 }
1833 else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
1834 {
1836 packet->PeekHeader (destHeader);
1837 if (destHeader.GetLength () >= 0xff)
1838 {
1839 NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
1840 "that have more than 255 octets following the Length field after compression. "
1841 "Packet uncompressed.");
1842 return 0;
1843 }
1844 size += packet->RemoveHeader (destHeader);
1846
1847 // recursively compress other headers
1848 uint8_t nextHeader = destHeader.GetNextHeader ();
1849 if (CanCompressLowPanNhc (nextHeader))
1850 {
1851 if (nextHeader == Ipv6Header::IPV6_UDP)
1852 {
1853 nhcHeader.SetNh (true);
1854 size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
1855 }
1856 else if (nextHeader == Ipv6Header::IPV6_IPV6)
1857 {
1858 nhcHeader.SetNh (true);
1859 size += CompressLowPanIphc (packet, src, dst);
1860 }
1861 else
1862 {
1863 uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
1864 // the compression might fail due to Extension header size.
1865 if (sizeNhc)
1866 {
1867 nhcHeader.SetNh (true);
1868 size += sizeNhc;
1869 }
1870 else
1871 {
1872 nhcHeader.SetNh (false);
1873 nhcHeader.SetNextHeader (nextHeader);
1874 }
1875 }
1876 }
1877 else
1878 {
1879 nhcHeader.SetNh (false);
1880 nhcHeader.SetNextHeader (nextHeader);
1881 }
1882
1883 uint32_t blobSize = destHeader.GetSerializedSize ();
1884 blob.AddAtStart (blobSize);
1885 destHeader.Serialize (blob.Begin ());
1886 blob.RemoveAtStart (2);
1887 blobSize = blob.GetSize ();
1888 nhcHeader.SetBlob (blob.PeekData (), blobSize);
1889 }
1890 else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
1891 {
1892 // \todo: IPv6 Mobility Header is not supported in ns-3
1893 NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
1894 return 0;
1895 }
1896 else
1897 {
1898 NS_ABORT_MSG ("Unexpected Extension Header");
1899 }
1900
1901 NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
1902 NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
1903
1904 packet->AddHeader (nhcHeader);
1905
1906 NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
1907 return size;
1908}
1909
1910std::pair <uint8_t, bool>
1911SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
1912{
1913 NS_LOG_FUNCTION (this << *packet);
1914
1915 SixLowPanNhcExtension encoding;
1916
1917 [[maybe_unused]] uint32_t ret = packet->RemoveHeader (encoding);
1918 NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
1919
1921 Ipv6ExtensionRoutingHeader routingHeader;
1922 Ipv6ExtensionFragmentHeader fragHeader;
1924
1925 uint32_t blobSize;
1926 uint8_t blobData[260];
1927 blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
1928 uint8_t paddingSize = 0;
1929
1930 uint8_t actualEncodedHeaderType = encoding.GetEid ();
1931 uint8_t actualHeaderType;
1932 Buffer blob;
1933
1934 switch (actualEncodedHeaderType)
1935 {
1937 actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
1938 if ( encoding.GetNh () )
1939 {
1940 // Next Header
1941 uint8_t dispatchRawVal = 0;
1943
1944 packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1945 dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1946
1947 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
1948 {
1949 blobData [0] = Ipv6Header::IPV6_UDP;
1950 DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
1951 }
1952 else
1953 {
1954 blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
1955 }
1956 }
1957 else
1958 {
1959 blobData [0] = encoding.GetNextHeader ();
1960 }
1961
1962 // manually add some padding if needed
1963 if ((blobSize + 2) % 8 > 0)
1964 {
1965 paddingSize = 8 - (blobSize + 2) % 8;
1966 }
1967 if (paddingSize == 1)
1968 {
1969 blobData[blobSize + 2] = 0;
1970 }
1971 else if (paddingSize > 1)
1972 {
1973 blobData[blobSize + 2] = 1;
1974 blobData[blobSize + 2 + 1] = paddingSize - 2;
1975 for (uint8_t i = 0; i < paddingSize - 2; i++)
1976 {
1977 blobData[blobSize + 2 + 2 + i] = 0;
1978 }
1979 }
1980 blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
1981 blob.AddAtStart (blobSize + 2 + paddingSize);
1982 blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
1983 hopHeader.Deserialize (blob.Begin ());
1984
1985 packet->AddHeader (hopHeader);
1986 break;
1987
1989 actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
1990 if ( encoding.GetNh () )
1991 {
1992 // Next Header
1993 uint8_t dispatchRawVal = 0;
1995
1996 packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
1997 dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
1998
1999 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2000 {
2001 blobData [0] = Ipv6Header::IPV6_UDP;
2002 DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2003 }
2004 else
2005 {
2006 blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2007 }
2008 }
2009 else
2010 {
2011 blobData [0] = encoding.GetNextHeader ();
2012 }
2013 blobData [1] = ((blobSize + 2) >> 3) - 1;
2014 blob.AddAtStart (blobSize + 2);
2015 blob.Begin ().Write (blobData, blobSize + 2);
2016 routingHeader.Deserialize (blob.Begin ());
2017 packet->AddHeader (routingHeader);
2018 break;
2019
2021 actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
2022 if ( encoding.GetNh () )
2023 {
2024 // Next Header
2025 uint8_t dispatchRawVal = 0;
2027
2028 packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2029 dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2030
2031 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2032 {
2033 blobData [0] = Ipv6Header::IPV6_UDP;
2034 DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2035 }
2036 else
2037 {
2038 blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2039 }
2040 }
2041 else
2042 {
2043 blobData [0] = encoding.GetNextHeader ();
2044 }
2045 blobData [1] = 0;
2046
2047 blob.AddAtStart (blobSize + 2);
2048 blob.Begin ().Write (blobData, blobSize + 2);
2049
2050 fragHeader.Deserialize (blob.Begin ());
2051 packet->AddHeader (fragHeader);
2052 break;
2053
2055 actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
2056 if ( encoding.GetNh () )
2057 {
2058 // Next Header
2059 uint8_t dispatchRawVal = 0;
2061
2062 packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
2063 dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
2064
2065 if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
2066 {
2067 blobData [0] = Ipv6Header::IPV6_UDP;
2068 DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
2069 }
2070 else
2071 {
2072 blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
2073 }
2074 }
2075 else
2076 {
2077 blobData [0] = encoding.GetNextHeader ();
2078 }
2079
2080 // manually add some padding if needed
2081 if ((blobSize + 2) % 8 > 0)
2082 {
2083 paddingSize = 8 - (blobSize + 2) % 8;
2084 }
2085 if (paddingSize == 1)
2086 {
2087 blobData[blobSize + 2] = 0;
2088 }
2089 else if (paddingSize > 1)
2090 {
2091 blobData[blobSize + 2] = 1;
2092 blobData[blobSize + 2 + 1] = paddingSize - 2;
2093 for (uint8_t i = 0; i < paddingSize - 2; i++)
2094 {
2095 blobData[blobSize + 2 + 2 + i] = 0;
2096 }
2097 }
2098 blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
2099 blob.AddAtStart (blobSize + 2 + paddingSize);
2100 blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
2101 destHeader.Deserialize (blob.Begin ());
2102
2103 packet->AddHeader (destHeader);
2104 break;
2106 // \todo: IPv6 Mobility Header is not supported in ns-3
2107 NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
2108 break;
2110 actualHeaderType = Ipv6Header::IPV6_IPV6;
2111 if (DecompressLowPanIphc (packet, src, dst))
2112 {
2114 return std::pair<uint8_t, bool> (0, true);
2115 }
2116 break;
2117 default:
2118 NS_ABORT_MSG ("Trying to decode unknown Extension Header");
2119 break;
2120 }
2121
2122 NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2123 return std::pair<uint8_t, bool> (actualHeaderType, false);
2124}
2125
2128{
2129 NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
2130
2131 UdpHeader udpHeader;
2132 SixLowPanUdpNhcExtension udpNhcHeader;
2133 uint32_t size = 0;
2134
2135 NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
2136
2137 size += packet->RemoveHeader (udpHeader);
2138
2139 // Set the C field and checksum
2140 udpNhcHeader.SetC (false);
2141 uint16_t checksum = udpHeader.GetChecksum ();
2142 udpNhcHeader.SetChecksum (checksum);
2143
2144 if (omitChecksum && udpHeader.IsChecksumOk ())
2145 {
2146 udpNhcHeader.SetC (true);
2147 }
2148
2149 // Set the value of the ports
2150 udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
2151 udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
2152
2153 //Set the P field
2154 if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
2155 {
2157 }
2158 else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
2159 {
2161 }
2162 else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
2163 {
2165 }
2166 else
2167 {
2169 }
2170
2171 NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
2172 NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
2173
2174 packet->AddHeader (udpNhcHeader);
2175
2176 NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
2177
2178 return size;
2179}
2180
2181void
2183{
2184 NS_LOG_FUNCTION (this << *packet);
2185
2186 UdpHeader udpHeader;
2187 SixLowPanUdpNhcExtension encoding;
2188
2189 [[maybe_unused]] uint32_t ret = packet->RemoveHeader (encoding);
2190 NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
2191
2192 // Set the value of the ports
2193 switch ( encoding.GetPorts () )
2194 {
2195 uint16_t temp;
2197 udpHeader.SetSourcePort (encoding.GetSrcPort ());
2198 udpHeader.SetDestinationPort (encoding.GetDstPort ());
2199 break;
2201 udpHeader.SetSourcePort (encoding.GetSrcPort ());
2202 temp = 0xf0;
2203 temp |= (temp << 8) | encoding.GetDstPort ();
2204 udpHeader.SetDestinationPort (temp);
2205 break;
2207 temp = 0xf0;
2208 temp |= (temp << 8) | encoding.GetSrcPort ();
2209 udpHeader.SetSourcePort (temp);
2210 udpHeader.SetDestinationPort (encoding.GetDstPort ());
2211 break;
2213 temp = 0xf0b;
2214 temp |= (temp << 4) | encoding.GetSrcPort ();
2215 udpHeader.SetSourcePort (temp);
2216 temp = 0xf0b;
2217 temp |= (temp << 4) | encoding.GetDstPort ();
2218 udpHeader.SetDestinationPort (temp);
2219 break;
2220 }
2221
2222 // Get the C field and checksum
2223 if (Node::ChecksumEnabled ())
2224 {
2225 if ( encoding.GetC () )
2226 {
2227 NS_LOG_LOGIC ("Recalculating UDP Checksum");
2228 udpHeader.EnableChecksums ();
2229 udpHeader.InitializeChecksum (saddr,
2230 daddr,
2232 packet->AddHeader (udpHeader);
2233 }
2234 else
2235 {
2236 NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
2237 udpHeader.ForceChecksum (encoding.GetChecksum ());
2238 packet->AddHeader (udpHeader);
2239 NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
2240 }
2241 }
2242 else
2243 {
2244 packet->AddHeader (udpHeader);
2245 }
2246
2247 NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
2248}
2249
2251 uint32_t origPacketSize,
2252 uint32_t origHdrSize,
2253 uint32_t extraHdrSize,
2254 std::list<Ptr<Packet> >& listFragments)
2255{
2256 NS_LOG_FUNCTION (this << *packet);
2257
2258 Ptr<Packet> p = packet->Copy ();
2259
2260 uint16_t offsetData = 0;
2261 uint16_t offset = 0;
2262 uint16_t l2Mtu = m_netDevice->GetMtu ();
2263 uint32_t packetSize = packet->GetSize ();
2264 uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
2265
2266 uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
2267 NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
2268
2269 // first fragment
2270 SixLowPanFrag1 frag1Hdr;
2271 frag1Hdr.SetDatagramTag (tag);
2272
2273 uint32_t size;
2274 NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
2275 "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
2276
2277 // All the headers are substracted to get remaining units for data
2278 size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize - extraHdrSize;
2279 size -= size % 8;
2280 size += compressedHeaderSize;
2281
2282 frag1Hdr.SetDatagramSize (origPacketSize);
2283
2284 Ptr<Packet> fragment1 = p->CreateFragment (offsetData, size);
2285 offset += size + origHdrSize - compressedHeaderSize;
2286 offsetData += size;
2287
2288 fragment1->AddHeader (frag1Hdr);
2289 listFragments.push_back (fragment1);
2290
2291 bool moreFrag = true;
2292 do
2293 {
2294 SixLowPanFragN fragNHdr;
2295 fragNHdr.SetDatagramTag (tag);
2296 fragNHdr.SetDatagramSize (origPacketSize);
2297 fragNHdr.SetDatagramOffset ((offset) >> 3);
2298
2299 size = l2Mtu - fragNHdr.GetSerializedSize () - extraHdrSize;
2300 size -= size % 8;
2301
2302 if ( (offsetData + size) > packetSize )
2303 {
2304 size = packetSize - offsetData;
2305 moreFrag = false;
2306 }
2307
2308 if (size > 0)
2309 {
2310 NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
2311 Ptr<Packet> fragment = p->CreateFragment (offsetData, size);
2312 NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
2313
2314 offset += size;
2315 offsetData += size;
2316
2317 fragment->AddHeader (fragNHdr);
2318 listFragments.push_back (fragment);
2319 }
2320 }
2321 while (moreFrag);
2322
2323 return;
2324}
2325
2326bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst)
2327{
2328 NS_LOG_FUNCTION ( this << *packet );
2329 SixLowPanFrag1 frag1Header;
2330 SixLowPanFragN fragNHeader;
2331 FragmentKey_t key;
2332 uint16_t packetSize;
2333 key.first = std::pair<Address, Address> (src, dst);
2334
2335 Ptr<Packet> p = packet->Copy ();
2336 uint16_t offset = 0;
2337
2338 /* Implementation note:
2339 *
2340 * The fragment offset is relative to the *uncompressed* packet.
2341 * On the other hand, the packet can not be uncompressed correctly without all
2342 * its fragments, as the UDP checksum can not be computed otherwise.
2343 *
2344 * As a consequence we must uncompress the packet twice, and save its first
2345 * fragment for the final one.
2346 */
2347
2348 if ( isFirst )
2349 {
2350 uint8_t dispatchRawValFrag1 = 0;
2351 SixLowPanDispatch::Dispatch_e dispatchValFrag1;
2352
2353 p->RemoveHeader (frag1Header);
2354 packetSize = frag1Header.GetDatagramSize ();
2355 p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
2356 dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
2357 NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
2358 NS_LOG_DEBUG ( "Packet: " << *p );
2359
2360 switch ( dispatchValFrag1 )
2361 {
2363 {
2364 SixLowPanIpv6 uncompressedHdr;
2365 p->RemoveHeader (uncompressedHdr);
2366 }
2367 break;
2369 DecompressLowPanHc1 (p, src, dst);
2370 break;
2372 if (DecompressLowPanIphc (p, src, dst))
2373 {
2375 return false;
2376 }
2377 break;
2378 default:
2379 NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
2380 break;
2381 }
2382
2383 key.second = std::pair<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
2384 }
2385 else
2386 {
2387 p->RemoveHeader (fragNHeader);
2388 packetSize = fragNHeader.GetDatagramSize ();
2389 offset = fragNHeader.GetDatagramOffset () << 3;
2390 key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
2391 }
2392
2393 Ptr<Fragments> fragments;
2394
2395 MapFragments_t::iterator it = m_fragments.find (key);
2396 if (it == m_fragments.end ())
2397 {
2398 // erase the oldest packet.
2400 {
2402 FragmentKey_t oldestKey = std::get<1> (*iter);
2403
2404 std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
2405 for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2406 fragIter != storedFragments.end (); fragIter++)
2407 {
2408 m_dropTrace (DROP_FRAGMENT_BUFFER_FULL, *fragIter, this, GetIfIndex ());
2409 }
2410
2411 m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
2412 m_fragments[oldestKey] = 0;
2413 m_fragments.erase (oldestKey);
2414
2415 }
2416 fragments = Create<Fragments> ();
2417 fragments->SetPacketSize (packetSize);
2418 m_fragments.insert (std::make_pair (key, fragments));
2419 uint32_t ifIndex = GetIfIndex ();
2420
2421 FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
2422 fragments->SetTimeoutIter (iter);
2423 }
2424 else
2425 {
2426 fragments = it->second;
2427 }
2428
2429 fragments->AddFragment (p, offset);
2430
2431 // add the very first fragment so we can correctly decode the packet once is rebuilt.
2432 // this is needed because otherwise the UDP header length and checksum can not be calculated.
2433 if ( isFirst )
2434 {
2435 fragments->AddFirstFragment (packet);
2436 }
2437
2438 if ( fragments->IsEntire () )
2439 {
2440 packet = fragments->GetPacket ();
2441 NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
2442
2443 SixLowPanFrag1 frag1Header;
2444 packet->RemoveHeader (frag1Header);
2445
2446 NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
2447 m_timeoutEventList.erase (fragments->GetTimeoutIter ());
2448 fragments = 0;
2449 m_fragments.erase (key);
2450 return true;
2451 }
2452
2453 return false;
2454}
2455
2457{
2458 NS_LOG_FUNCTION (this);
2459 m_packetSize = 0;
2460}
2461
2463{
2464 NS_LOG_FUNCTION (this);
2465}
2466
2467void SixLowPanNetDevice::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset)
2468{
2469 NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
2470
2471 std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
2472 bool duplicate = false;
2473
2474 for (it = m_fragments.begin (); it != m_fragments.end (); it++)
2475 {
2476 if (it->second > fragmentOffset)
2477 {
2478 break;
2479 }
2480 if (it->second == fragmentOffset)
2481 {
2482 duplicate = true;
2483 NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
2484 break;
2485 }
2486 }
2487 if (!duplicate)
2488 {
2489 m_fragments.insert (it, std::make_pair (fragment, fragmentOffset));
2490 }
2491}
2492
2494{
2495 NS_LOG_FUNCTION (this << *fragment);
2496
2497 m_firstFragment = fragment;
2498}
2499
2501{
2502 NS_LOG_FUNCTION (this);
2503
2504 bool ret = m_fragments.size () > 0;
2505 uint16_t lastEndOffset = 0;
2506
2507 if (ret)
2508 {
2509 for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
2510 {
2511 // overlapping fragments should not exist
2512 NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
2513
2514 if (lastEndOffset < it->second)
2515 {
2516 ret = false;
2517 break;
2518 }
2519 // fragments might overlap in strange ways
2520 uint16_t fragmentEnd = it->first->GetSize () + it->second;
2521 lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
2522 }
2523 }
2524
2525 if ( ret && (lastEndOffset == m_packetSize))
2526 {
2527 return true;
2528 }
2529 return false;
2530}
2531
2533{
2534 NS_LOG_FUNCTION (this);
2535
2536 std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
2537
2538 Ptr<Packet> p = Create<Packet> ();
2539 uint16_t lastEndOffset = 0;
2540
2541 p->AddAtEnd (m_firstFragment);
2542 it = m_fragments.begin ();
2543 lastEndOffset = it->first->GetSize ();
2544
2545 for ( it++; it != m_fragments.end (); it++)
2546 {
2547 if ( lastEndOffset > it->second )
2548 {
2549 NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
2550 }
2551 else
2552 {
2553 NS_LOG_LOGIC ("Adding: " << *(it->first) );
2554 p->AddAtEnd (it->first);
2555 }
2556 lastEndOffset += it->first->GetSize ();
2557 }
2558
2559 return p;
2560}
2561
2563{
2564 NS_LOG_FUNCTION (this << packetSize);
2565 m_packetSize = packetSize;
2566}
2567
2568std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
2569{
2570 std::list< Ptr<Packet> > fragments;
2571 std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
2572 for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
2573 {
2574 fragments.push_back (iter->first);
2575 }
2576 return fragments;
2577}
2578
2579void
2581{
2582 m_timeoutIter = iter;
2583 return;
2584}
2585
2588{
2589 return m_timeoutIter;
2590}
2591
2593{
2594 NS_LOG_FUNCTION (this);
2595
2596 MapFragments_t::iterator it = m_fragments.find (key);
2597 std::list< Ptr<Packet> > storedFragments = it->second->GetFraments ();
2598 for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
2599 fragIter != storedFragments.end (); fragIter++)
2600 {
2601 m_dropTrace (DROP_FRAGMENT_TIMEOUT, *fragIter, this, iif);
2602 }
2603 // clear the buffers
2604 it->second = 0;
2605
2606 m_fragments.erase (key);
2607}
2608
2610{
2611 NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
2612
2613 uint8_t buf[6];
2614 addr.CopyTo (buf);
2615
2616 Mac16Address shortAddr;
2617 shortAddr.CopyFrom (buf + 4);
2618
2619 return shortAddr;
2620}
2621
2623{
2624 if (m_timeoutEventList.empty ())
2625 {
2627 }
2629
2631
2632 return (iter);
2633}
2634
2636{
2637 Time now = Simulator::Now ();
2638
2639 while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
2640 {
2641 HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
2642 std::get<2> (*m_timeoutEventList.begin ()));
2643 m_timeoutEventList.pop_front ();
2644 }
2645
2646 if (m_timeoutEventList.empty ())
2647 {
2648 return;
2649 }
2650
2651 Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
2653
2654 return;
2655}
2656
2657void SixLowPanNetDevice::AddContext (uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
2658{
2659 NS_LOG_FUNCTION (this << +contextId << Ipv6Address::GetOnes ().CombinePrefix (contextPrefix) << contextPrefix << compressionAllowed << validLifetime.As (Time::S));
2660
2661 if (contextId > 15)
2662 {
2663 NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2664 return;
2665 }
2666
2667 if (validLifetime == Time(0))
2668 {
2669 NS_LOG_LOGIC ("Context (" << +contextId << "), removed (validity time is zero)");
2670 m_contextTable.erase (contextId);
2671 return;
2672 }
2673
2674 m_contextTable[contextId].contextPrefix = contextPrefix;
2675 m_contextTable[contextId].compressionAllowed = compressionAllowed;
2676 m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2677
2678 return;
2679}
2680
2681bool SixLowPanNetDevice::GetContext (uint8_t contextId, Ipv6Prefix& contextPrefix, bool& compressionAllowed, Time& validLifetime)
2682{
2683 NS_LOG_FUNCTION (this << +contextId);
2684
2685 if (contextId > 15)
2686 {
2687 NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2688 return false;
2689 }
2690
2691 if (m_contextTable.find (contextId) == m_contextTable.end ())
2692 {
2693 NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2694 return false;
2695 }
2696
2697 contextPrefix = m_contextTable[contextId].contextPrefix;
2698 compressionAllowed = m_contextTable[contextId].compressionAllowed;
2699 validLifetime = m_contextTable[contextId].validLifetime;
2700
2701 return true;
2702}
2703
2704void SixLowPanNetDevice::RenewContext (uint8_t contextId, Time validLifetime)
2705{
2706 NS_LOG_FUNCTION (this << +contextId << validLifetime.As (Time::S));
2707
2708 if (contextId > 15)
2709 {
2710 NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2711 return;
2712 }
2713
2714 if (m_contextTable.find (contextId) == m_contextTable.end ())
2715 {
2716 NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2717 return;
2718 }
2719 m_contextTable[contextId].compressionAllowed = true;
2720 m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
2721 return;
2722}
2723
2724
2726{
2727 NS_LOG_FUNCTION (this << +contextId);
2728
2729 if (contextId > 15)
2730 {
2731 NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2732 return;
2733 }
2734
2735 if (m_contextTable.find (contextId) == m_contextTable.end ())
2736 {
2737 NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2738 return;
2739 }
2740 m_contextTable[contextId].compressionAllowed = false;
2741 return;
2742}
2743
2745{
2746 NS_LOG_FUNCTION (this << +contextId);
2747
2748 if (contextId > 15)
2749 {
2750 NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
2751 return;
2752 }
2753
2754 if (m_contextTable.find (contextId) == m_contextTable.end ())
2755 {
2756 NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
2757 return;
2758 }
2759
2760 m_contextTable.erase (contextId);
2761 return;
2762}
2763
2765{
2766 NS_LOG_FUNCTION (this << address);
2767
2768 for (const auto& iter: m_contextTable)
2769 {
2770 ContextEntry context = iter.second;
2771
2772 if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2773 {
2774
2775 if (address.HasPrefix (context.contextPrefix))
2776 {
2777 NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2778 Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2779
2780 contextId = iter.first;
2781 return true;
2782 }
2783 }
2784 }
2785 return false;
2786}
2787
2789{
2790 NS_LOG_FUNCTION (this << address);
2791
2792 // The only allowed context-based compressed multicast address is in the form
2793 // ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
2794
2795 for (const auto& iter: m_contextTable)
2796 {
2797 ContextEntry context = iter.second;
2798
2799 if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
2800 {
2801 uint8_t contextLength = context.contextPrefix.GetPrefixLength ();
2802
2803 if (contextLength <= 64) // only 64-bit prefixes or less are allowed.
2804 {
2805 uint8_t contextBytes[16];
2806 uint8_t addressBytes[16];
2807
2808 context.contextPrefix.GetBytes (contextBytes);
2809 address.GetBytes (addressBytes);
2810
2811 if (addressBytes[3] == contextLength &&
2812 addressBytes[4] == contextBytes[0] &&
2813 addressBytes[5] == contextBytes[1] &&
2814 addressBytes[6] == contextBytes[2] &&
2815 addressBytes[7] == contextBytes[3] &&
2816 addressBytes[8] == contextBytes[4] &&
2817 addressBytes[9] == contextBytes[5] &&
2818 addressBytes[10] == contextBytes[6] &&
2819 addressBytes[11] == contextBytes[7])
2820 {
2821 NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
2822 Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
2823
2824 contextId = iter.first;
2825 return true;
2826 }
2827 }
2828 }
2829 }
2830 return false;
2831}
2832
2834{
2835 uint8_t addressBytes[16];
2836 address.GetBytes (addressBytes);
2837 uint8_t prefixLength = prefix.GetPrefixLength ();
2838
2839 uint8_t bytesToClean = prefixLength / 8;
2840 uint8_t bitsToClean = prefixLength % 8;
2841 for (uint8_t i=0; i<bytesToClean; i++)
2842 {
2843 addressBytes[i] = 0;
2844 }
2845 if (bitsToClean)
2846 {
2847 uint8_t cleanupMask = (1<<bitsToClean)-1;
2848 addressBytes[bytesToClean] &= cleanupMask;
2849 }
2850
2851 Ipv6Address cleanedAddress = Ipv6Address::Deserialize (addressBytes);
2852
2853 return cleanedAddress;
2854}
2855
2856}
2857
2858// namespace ns3
#define max(a, b)
Definition: 80211b.c:43
a polymophic address class
Definition: address.h:91
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
Definition: address.cc:82
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:954
automatically resized byte buffer
Definition: buffer.h:93
uint32_t GetSize(void) const
Definition: buffer.h:1063
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
uint8_t const * PeekData(void) const
Definition: buffer.cc:710
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:443
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Describes an IPv6 address.
Definition: ipv6-address.h:50
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static Ipv6Address Deserialize(const uint8_t buf[16])
Deserialize this address.
static Ipv6Address MakeAutoconfiguredAddress(Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address from a Mac address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the address.
void Serialize(uint8_t buf[16]) const
Serialize this address to a 16-byte buffer.
static Ipv6Address GetOnes()
Get the "all-1" IPv6 address (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
Header of IPv6 Extension Destination.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Header of IPv6 Extension Fragment.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
uint16_t GetLength() const
Get the length of the extension.
uint8_t GetNextHeader() const
Get the next header.
Header of IPv6 Extension "Hop by Hop".
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Header of IPv6 Extension Routing.
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Packet header for IPv6.
Definition: ipv6-header.h:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:115
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Ipv6Address GetSource(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:105
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:163
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:85
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
void SetFlowLabel(uint32_t flow)
Set the "Flow label" field.
Definition: ipv6-header.cc:55
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
Definition: ipv6-header.cc:45
uint32_t GetFlowLabel(void) const
Get the "Flow label" field.
Definition: ipv6-header.cc:60
Ipv6Address GetDestination(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:125
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:456
uint8_t GetPrefixLength() const
Get prefix length.
void GetBytes(uint8_t buf[16]) const
Get the bytes corresponding to the prefix.
This class can contain 16 bit addresses.
Definition: mac16-address.h:42
bool IsBroadcast(void) const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
static bool IsMatchingType(const Address &address)
static Mac16Address ConvertFrom(const Address &address)
bool IsMulticast(void) const
Checks if the address is a multicast address according to RFC 4944 Section 9 (i.e....
void CopyFrom(const uint8_t buffer[2])
static bool IsMatchingType(const Address &address)
Network layer to device interface.
Definition: net-device.h:96
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)=0
virtual bool IsMulticast(void) const =0
virtual bool SetMtu(const uint16_t mtu)=0
virtual Address GetBroadcast(void) const =0
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
virtual Address GetAddress(void) const =0
virtual bool IsBroadcast(void) const =0
virtual bool IsPointToPoint(void) const =0
Return true if the net device is on a point-to-point link.
virtual uint16_t GetMtu(void) const =0
virtual Address GetMulticast(Ipv4Address multicastGroup) const =0
Make and return a MAC multicast address using the provided multicast group.
virtual bool IsBridge(void) const =0
Return true if the net device is acting as a bridge.
virtual void AddLinkChangeCallback(Callback< void > callback)=0
virtual bool NeedsArp(void) const =0
virtual void SetAddress(Address address)=0
Set the address of this interface.
virtual Ptr< Channel > GetChannel(void) const =0
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:297
virtual bool IsLinkUp(void) const =0
static bool ChecksumEnabled(void)
Definition: node.cc:278
uint32_t GetId(void) const
Definition: node.cc:109
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:229
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: object.cc:79
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
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
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
6LoWPAN BC0 header - see RFC 4944.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint8_t GetSequenceNumber(void) const
Get the "Sequence Number" field.
void SetSequenceNumber(uint8_t seqNumber)
Set the "Sequence Number" field.
static Dispatch_e GetDispatchType(uint8_t dispatch)
Get the Dispatch type.
static NhcDispatch_e GetNhcDispatchType(uint8_t dispatch)
Get the NhcDispatch type.
NhcDispatch_e
Dispatch values for Next Header compression.
6LoWPAN FRAG1 header - see RFC 4944.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint16_t GetDatagramSize(void) const
Get the datagram size.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
6LoWPAN FRAGN header - see RFC 4944.
uint16_t GetDatagramTag(void) const
Get the datagram tag.
uint8_t GetDatagramOffset(void) const
Get the datagram offset.
void SetDatagramSize(uint16_t datagramSize)
Set the datagram size.
uint16_t GetDatagramSize(void) const
Get the datagram size.
void SetDatagramTag(uint16_t datagramTag)
Set the datagram tag.
void SetDatagramOffset(uint8_t datagramOffset)
Set the datagram offset.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
6LoWPAN HC1 header - see RFC 4944.
void SetTcflCompression(bool tcflCompression)
Set the Traffic Class and Flow Labels as compressed.
const uint8_t * GetSrcPrefix() const
Get the source prefix.
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label value.
uint8_t GetTrafficClass() const
Get the Traffic Class value.
void SetDstCompression(LowPanHc1Addr_e dstCompression)
Set Destination Compression type.
void SetTrafficClass(uint8_t trafficClass)
Set the Traffic Class 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).
uint32_t GetFlowLabel() const
Get the Flow Label value.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
const uint8_t * GetDstPrefix() const
Get the destination prefix.
void SetHc2HeaderPresent(bool hc2HeaderPresent)
Set the next header a HC2 compressed header.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header value.
void SetSrcCompression(LowPanHc1Addr_e srcCompression)
Set Source Compression type.
void SetDstInterface(const uint8_t *dstInterface)
Set the destination interface.
void SetDstPrefix(const uint8_t *dstPrefix)
Set the destination prefix.
void SetSrcPrefix(const uint8_t *srcPrefix)
Set the source prefix.
uint8_t GetNextHeader() const
Get the Next Header value.
void SetSrcInterface(const uint8_t *srcInterface)
Set the source interface.
LowPanHc1Addr_e GetDstCompression() const
Get Destination Compression type.
bool IsHc2HeaderPresent() const
Check if there is a HC2 compressed header.
LowPanHc1Addr_e GetSrcCompression() const
Get Source Compression type.
bool IsTcflCompression() const
Check if the Traffic Class and Flow Labels are compressed.
LOWPAN_IPHC base Encoding - see RFC 6282.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field.
bool GetM(void) const
Get the M (Multicast) compression.
void SetHlim(Hlim_e hlimField)
Set the HLIM (Hop Limit) compression.
bool GetSac(void) const
Get the SAC (Source Address Compression) compression.
void SetDstContextId(uint8_t dstContextId)
Set the DstContextId.
void SetSam(HeaderCompression_e samField)
Set the SAM (Source Address Mode) compression.
void SetNh(bool nhField)
Set the NH (Next Header) compression.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetEcn(uint8_t ecn)
Set the ECN (2bits).
void SetFlowLabel(uint32_t flowLabel)
Set the Flow Label (20bits).
TrafficClassFlowLabel_e GetTf(void) const
Get the TF (Traffic Class, Flow Label) compression.
bool GetDac(void) const
Get the DAC (Destination Address Compression) compression.
void SetDscp(uint8_t dscp)
Set the DSCP (6bits).
uint8_t GetDstContextId(void) const
Get the DstContextId.
void SetTf(TrafficClassFlowLabel_e tfField)
Set the TF (Traffic Class, Flow Label) compression.
const uint8_t * GetDstInlinePart(void) const
brief Get the destination address inline part
void SetDam(HeaderCompression_e damField)
Set the DAM (Destination Address Mode) compression.
void SetCid(bool cidField)
Set the CID (Context Identifier Extension) compression.
uint8_t GetEcn(void) const
Get the ECN.
HeaderCompression_e GetSam(void) const
Get the SAM (Source Address Mode) compression.
uint8_t GetHopLimit(void) const
Get the Hop Limit field.
bool GetNh(void) const
Get the NH (Next Header) compression.
void SetSac(bool sacField)
Set the SAC (Source Address Compression) compression.
HeaderCompression_e GetDam(void) const
Get the DAM (Destination Address Mode) compression.
const uint8_t * GetSrcInlinePart(void) const
brief Get the source address inline part
void SetDstInlinePart(uint8_t dstInlinePart[16], uint8_t size)
brief Set the destination address inline part
uint8_t GetSrcContextId(void) const
Get the SrcContextId.
void SetSrcContextId(uint8_t srcContextId)
Set the SrcContextId.
void SetSrcInlinePart(uint8_t srcInlinePart[16], uint8_t size)
brief Set the source address inline part
uint8_t GetDscp(void) const
Get the DSCP.
void SetM(bool mField)
Set the M (Multicast) compression.
uint32_t GetFlowLabel(void) const
Get the Flow Label.
uint8_t GetNextHeader(void) const
Get the Next Header field.
void SetHopLimit(uint8_t hopLimit)
Set the Hop Limit field.
void SetDac(bool dacField)
Set the DAC (Destination Address Compression) compression.
6LoWPAN IPv6 uncompressed header - see RFC 4944.
6LoWPAN Mesh header - see RFC 4944.
void SetHopsLeft(uint8_t hopsLeft)
Set the "Hops Left" field.
Address GetFinalDst(void) const
Get the "Final Destination" address.
void SetFinalDst(Address finalDst)
Set the "Final Destination" address.
Address GetOriginator(void) const
Get the "Originator" address.
uint8_t GetHopsLeft(void) const
Get the "Hops Left" field.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
void SetOriginator(Address originator)
Set the "Originator" address.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
bool IsEntire() const
If all fragments have been added.
void SetPacketSize(uint32_t packetSize)
Set the packet-to-be-defragmented size.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset)
Add a fragment to the pool.
uint32_t m_packetSize
The size of the reconstructed packet (bytes).
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
Ptr< Packet > GetPacket() const
Get the entire packet.
std::list< Ptr< Packet > > GetFraments() const
Get a list of the current stored fragments.
void AddFirstFragment(Ptr< Packet > fragment)
Add the first packet fragment.
Shim performing 6LoWPAN compression, decompression and fragmentation.
bool DecompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Decompress the headers according to IPHC compression.
std::map< FragmentKey_t, Ptr< Fragments > >::iterator MapFragmentsI_t
Container Iterator for fragment key -> fragments.
void DecompressLowPanUdpNhc(Ptr< Packet > packet, Ipv6Address saddr, Ipv6Address daddr)
Decompress the headers according to NHC compression.
bool DoSend(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber, bool doSendFrom)
Ipv6Address CleanPrefix(Ipv6Address address, Ipv6Prefix prefix)
Clean an address from its prefix.
uint32_t CompressLowPanHc1(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to HC1 compression.
uint8_t m_bc0Serial
Serial number used in BC0 header.
EventId m_timeoutEvent
Event for the next scheduled timeout.
virtual Ptr< Channel > GetChannel(void) const
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
Ptr< UniformRandomVariable > m_rng
Rng for the fragments tag.
uint16_t m_meshCacheLength
length of the cache for each source.
bool m_useIphc
Use IPHC or HC1.
void RenewContext(uint8_t contextId, Time validLifetime)
Renew a context used in IPHC stateful compression.
virtual Address GetAddress(void) const
virtual Address GetBroadcast(void) const
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.
void DoFragmentation(Ptr< Packet > packet, uint32_t origPacketSize, uint32_t origHdrSize, uint32_t extraHdrSize, std::list< Ptr< Packet > > &listFragments)
Performs a packet fragmentation.
virtual bool SupportsSendFrom() const
Ptr< Node > m_node
Smart pointer to the Node.
uint32_t CompressLowPanNhc(Ptr< Packet > packet, uint8_t headerType, Address const &src, Address const &dst)
Compress the headers according to NHC compression.
virtual void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
bool CanCompressLowPanNhc(uint8_t headerType)
Checks if the next header can be compressed using NHC.
virtual void SetReceiveCallback(NetDevice::ReceiveCallback cb)
virtual Ptr< Node > GetNode(void) const
std::list< std::tuple< Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
bool m_forceEtherType
Force the EtherType number.
virtual uint32_t GetIfIndex(void) const
virtual bool NeedsArp(void) const
uint32_t m_compressionThreshold
Minimum L2 payload size.
virtual void AddLinkChangeCallback(Callback< void > callback)
void DecompressLowPanHc1(Ptr< Packet > packet, Address const &src, Address const &dst)
Decompress the headers according to HC1 compression.
Ptr< NetDevice > GetNetDevice() const
Returns a smart pointer to the underlying NetDevice.
virtual bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)
uint32_t CompressLowPanIphc(Ptr< Packet > packet, Address const &src, Address const &dst)
Compress the headers according to IPHC compression.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
@ DROP_DISALLOWED_COMPRESSION
HC1 while in IPHC mode or viceversa.
@ DROP_UNKNOWN_EXTENSION
Unsupported compression kind.
@ DROP_FRAGMENT_BUFFER_FULL
Fragment buffer size exceeded.
@ DROP_SATETFUL_DECOMPRESSION_PROBLEM
Decompression failed due to missing or expired context.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
void AddContext(uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
Add, remove, or update a context used in IPHC stateful compression.
static TypeId GetTypeId(void)
Get the type ID.
Ptr< NetDevice > m_netDevice
Smart pointer to the underlying NetDevice.
std::pair< uint8_t, bool > DecompressLowPanNhc(Ptr< Packet > packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
Decompress the headers according to NHC compression.
void SetNetDevice(Ptr< NetDevice > device)
Setup SixLowPan to be a proxy for the specified NetDevice.
std::map< uint8_t, ContextEntry > m_contextTable
Table of the contexts used in compression/decompression.
TracedCallback< Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
bool ProcessFragment(Ptr< Packet > &packet, Address const &src, Address const &dst, bool isFirst)
Process a packet fragment.
bool GetContext(uint8_t contextId, Ipv6Prefix &contextPrefix, bool &compressionAllowed, Time &validLifetime)
Get a context used in IPHC stateful compression.
virtual bool IsBridge(void) const
Return true if the net device is acting as a bridge.
virtual bool IsMulticast(void) const
Address Get16MacFrom48Mac(Address addr)
Get a Mac16 from its Mac48 pseudo-MAC.
TracedCallback< DropReason, Ptr< const Packet >, Ptr< SixLowPanNetDevice >, uint32_t > m_dropTrace
Callback to trace drop packets.
bool FindUnicastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given unicast address matches a context for compression.
Ptr< RandomVariableStream > m_meshUnderJitter
Random variable for the mesh-under packet retransmission.
virtual Address GetMulticast(Ipv4Address multicastGroup) const
Make and return a MAC multicast address using the provided multicast group.
virtual bool IsPointToPoint(void) const
Return true if the net device is on a point-to-point link.
virtual void DoDispose(void)
Destructor implementation.
uint32_t CompressLowPanUdpNhc(Ptr< Packet > packet, bool omitChecksum)
Compress the headers according to NHC compression.
virtual bool IsLinkUp(void) const
void RemoveContext(uint8_t contextId)
Remove a context used in IPHC stateful compression.
bool m_omitUdpChecksum
Omit UDP checksum in NC1 encoding.
std::pair< std::pair< Address, Address >, std::pair< uint16_t, uint16_t > > FragmentKey_t
Fragment identifier type: src/dst address src/dst port.
virtual bool SetMtu(const uint16_t mtu)
uint32_t m_ifIndex
Interface index.
virtual bool IsBroadcast(void) const
virtual void SetAddress(Address address)
Set the address of this interface.
virtual uint16_t GetMtu(void) const
Returns the link-layer MTU for this interface.
void HandleTimeout(void)
Handles a fragmented packet timeout.
virtual void SetIfIndex(const uint32_t index)
Time m_fragmentExpirationTimeout
Time limit for fragment rebuilding.
uint16_t m_fragmentReassemblyListSize
How many packets can be rebuilt at the same time.
uint8_t m_meshUnderHopsLeft
Start value for mesh-under hops left.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
virtual void SetNode(Ptr< Node > node)
NetDevice::PromiscReceiveCallback m_promiscRxCallback
The callback used to notify higher layers that a packet has been received in promiscuous mode.
void HandleFragmentsTimeout(FragmentKey_t key, uint32_t iif)
Process the timeout for packet fragments.
void InvalidateContext(uint8_t contextId)
Invalidate a context used in IPHC stateful compression.
NetDevice::ReceiveCallback m_rxCallback
The callback used to notify higher layers that a packet has been received.
virtual bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
MapFragments_t m_fragments
Fragments hold to be rebuilt.
bool FindMulticastCompressionContext(Ipv6Address address, uint8_t &contextId)
Finds if the given multicast address matches a context for compression.
bool m_meshUnder
Use a mesh-under routing.
std::map< Address, std::list< uint8_t > > m_seenPkts
Seen packets, memorized by OriginatorAdddress, SequenceNumber.
SixLowPanNetDevice()
Constructor for the SixLowPanNetDevice.
uint16_t m_etherType
EtherType number (used only if m_forceEtherType is true).
LOWPAN_NHC Extension Header Encoding - see RFC 6282.
uint8_t GetNextHeader(void) const
Get the Next Header field value.
void SetNh(bool nhField)
Set the NH field values.
Eid_e GetEid(void) const
Get the Extension Header Type.
void SetEid(Eid_e extensionHeaderType)
Set the Extension Header Type.
void SetBlob(const uint8_t *blob, uint32_t size)
Set the option header data blob.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint32_t CopyBlob(uint8_t *blob, uint32_t size) const
Get the option header data blob.
bool GetNh(void) const
Get the Next Header field value.
void SetNextHeader(uint8_t nextHeader)
Set the Next Header field values.
UDP LOWPAN_NHC Extension Header Encoding - see RFC 6282.
uint16_t GetDstPort() const
Get the Destination Port.
void SetPorts(Ports_e port)
Set the compressed Src and Dst Ports.
uint16_t GetChecksum(void) const
Get the Checksum field value.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
bool GetC(void) const
Get the C (Checksum).
void SetChecksum(uint16_t checksum)
Set the Checksum field values.
void SetDstPort(uint16_t port)
Set the Destination Port.
void SetSrcPort(uint16_t port)
Set the Source Port.
void SetC(bool cField)
Set the C (Checksum).
Ports_e GetPorts(void) const
Get the compressed Src and Dst Ports.
uint16_t GetSrcPort() const
Get the Source Port.
Hold variables of type string.
Definition: string.h:41
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ S
second
Definition: nstime.h:114
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:432
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
Packet header for UDP packets.
Definition: udp-header.h:40
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:49
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
void ForceChecksum(uint16_t checksum)
Force the UDP checksum to a given value.
Definition: udp-header.cc:142
bool IsChecksumOk(void) const
Is the UDP checksum correct ?
Definition: udp-header.cc:136
uint16_t GetChecksum()
Return the checksum (only known after a Deserialize)
Definition: udp-header.cc:241
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:75
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:60
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:55
static const uint8_t PROT_NUMBER
protocol number (0x11)
Hold an unsigned integer type.
Definition: uinteger.h:44
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
#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
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
address
Definition: first.py:44
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:793
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:536
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:1648
Definition: second.py:1
#define list
Structure holding the informations for a context (used in compression and decompression)
Ipv6Prefix contextPrefix
context prefix to be used in compression/decompression
bool compressionAllowed
compression and decompression allowed (true), decompression only (false)
Time validLifetime
validity period
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:89
static const uint32_t packetSize
Pcket size generated at the AP.