A Discrete-Event Network Simulator
API
wimax-mac-queue.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007,2008 INRIA, UDcast
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: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
19  * Mohamed Amine Ismail <Amine.Ismail@sophia.inria.fr>
20  * <Amine.Ismail@UDcast.com>
21  */
22 
23 #include "wimax-mac-queue.h"
24 #include "ns3/packet.h"
25 #include "ns3/trace-source-accessor.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/simulator.h"
28 #include "ns3/log.h"
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("WimaxMacQueue");
33 
34 NS_OBJECT_ENSURE_REGISTERED (WimaxMacQueue);
35 
37  : m_packet (Create<Packet> ()),
38  m_hdrType (MacHeaderType ()),
39  m_hdr (
40  GenericMacHeader ()),
41  m_timeStamp (Seconds (0)),
42  m_fragmentation (false),
43  m_fragmentNumber (0),
44  m_fragmentOffset (0)
45 {
46 }
47 
49  const MacHeaderType &hdrType,
50  const GenericMacHeader &hdr, Time timeStamp)
51  : m_packet (packet),
52  m_hdrType (hdrType),
53  m_hdr (hdr),
54  m_timeStamp (timeStamp),
55  m_fragmentation (false),
56  m_fragmentNumber (0),
57  m_fragmentOffset (0)
58 {
59 }
60 
61 uint32_t
63 {
64  uint32_t size = m_packet->GetSize () + m_hdrType.GetSerializedSize ();
65 
66  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
67  has already been added to the packet) in which case Generic MAC Header will not be added to it.
68  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
69  if (m_hdrType.GetType () == MacHeaderType::HEADER_TYPE_GENERIC)
70  {
71  size += m_hdr.GetSerializedSize ();
72  }
73 
74  return size;
75 }
76 
77 TypeId
79 {
80  static TypeId tid = TypeId ("ns3::WimaxMacQueue")
81  .SetParent<Object> ()
82  .SetGroupName("Wimax")
83  .AddAttribute (
84  "MaxSize",
85  "Maximum size",
86  UintegerValue (1024),
89  MakeUintegerChecker<uint32_t> ())
90  .AddTraceSource ("Enqueue",
91  "Enqueue trace",
93  "ns3::Packet::TracedCallback")
94  .AddTraceSource ("Dequeue",
95  "Dequeue trace",
97  "ns3::Packet::TracedCallback")
98  .AddTraceSource ("Drop",
99  "Drop trace",
101  "ns3::Packet::TracedCallback")
102  ;
103  return tid;
104 }
105 
107  : m_maxSize (0),
108  m_bytes (0),
109  m_nrDataPackets (0),
111 {
112 }
113 
115  : m_maxSize (maxSize),
116  m_bytes (0),
117  m_nrDataPackets (0),
118  m_nrRequestPackets (0)
119 {
120 }
121 
123 {
124 }
125 
126 void
127 WimaxMacQueue::SetMaxSize (uint32_t maxSize)
128 {
129  m_maxSize = maxSize;
130 }
131 
132 uint32_t
134 {
135  return m_maxSize;
136 }
137 
138 bool
140  const GenericMacHeader &hdr)
141 {
142 
143  if (m_queue.size () == m_maxSize)
144  {
145 
146  m_traceDrop (packet);
147  return false;
148  }
149 
150  m_traceEnqueue (packet);
151  QueueElement element (packet, hdrType, hdr, Simulator::Now ());
152  m_queue.push_back (element);
153 
155  {
156  m_nrDataPackets++;
157  }
158  else
159  {
161  }
162 
163  m_bytes += element.GetSize ();
164  return true;
165 }
166 
169 {
170  if (!IsEmpty ())
171  {
172  QueueElement element = Front (packetType);
173  Pop (packetType);
174 
176  {
177  NS_LOG_INFO ("Enqueued Packet IS A data packet");
179  "Can not enqueue more packets: no space left in the queue");
180  m_nrDataPackets--;
181  }
182  else
183  {
184  NS_LOG_INFO ("Enqueued Packet IS A Request BW packet");
186  "Can not enqueue more packets: no space left in the queue");
188  }
189 
190  Ptr<Packet> packet = element.m_packet;
191 
192  if (!element.m_fragmentation)
193  {
194  NS_LOG_INFO ("FRAG_DEBUG: Enqueued Packet IS NOT a fragment" << std::endl);
195  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
196  has already been added to the packet) in which case Generic MAC Header will not be added to it.
197  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
198  m_bytes -= element.GetSize ();
200  {
201  packet->AddHeader (element.m_hdr);
202  }
203  packet->AddHeader (element.m_hdrType);
204 
205  m_traceDequeue (packet);
206  return packet;
207  }
208  else
209  {
210  /*
211  The enqueued packet is a fragment (the latest fragment)
212  We must modify type field of the m_hdr and add a fragmentation Subhdr
213  */
214  NS_LOG_INFO ("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);
215 
216  // Create a fragment
217  uint32_t fragmentOffset = element.m_fragmentOffset;
218  uint32_t fragmentSize = element.m_packet->GetSize () - fragmentOffset;
219 
220  NS_LOG_INFO ("\t Create a fragment"
221  "\n\t\t fragmentOffset=" << fragmentOffset <<
222  "\n\t\t packetSize=" << element.m_packet->GetSize () <<
223  "\n\t\t fragmentSize=" << fragmentSize << std::endl);
224 
225  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,fragmentSize);
226 
227  FragmentationSubheader fragmentSubhdr;
228  NS_LOG_INFO ("\t Latest Fragment" << std::endl);
229  fragmentSubhdr.SetFc (2); // This is the latest fragment
230  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
231 
232  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
233  fragment->AddHeader (fragmentSubhdr);
234 
235  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
236  has already been added to the packet) in which case Generic MAC Header will not be added to it.
237  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
239  {
240  uint8_t tmpType = element.m_hdr.GetType ();
241  tmpType |= 4;
242  element.m_hdr.SetType (tmpType);
243 
244  uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize ()
245  + fragmentSubhdr.GetSerializedSize ();
246  element.m_hdr.SetLen ((uint16_t)length);
247 
248  fragment->AddHeader (element.m_hdr);
249  }
250  fragment->AddHeader (element.m_hdrType);
251  m_bytes -= fragmentSize;
252 
253  m_traceDequeue (fragment);
254  return fragment;
255  }
256  }
257  return 0;
258 }
259 
261 WimaxMacQueue::Dequeue (MacHeaderType::HeaderType packetType, uint32_t availableByte)
262 {
263  if (!IsEmpty ())
264  {
265  NS_LOG_INFO ("FRAG_DEBUG: Dequeue function" << std::endl);
266  QueueElement element = Front (packetType);
267 
268  uint32_t headerSize = 2 + element.m_hdr.GetSerializedSize () +
269  element.m_hdrType.GetSerializedSize ();
270 
271  // Create a fragment
272  uint32_t maxFragmentSize = availableByte - headerSize;
273  uint32_t fragmentOffset = element.m_fragmentOffset; // It is the latest byte sent.
274 
275  Ptr<Packet> packet = element.m_packet->Copy ();
276  NS_LOG_INFO ("\t Create a fragment"
277  "\n\t\t availableByte=" << availableByte <<
278  "\n\t\t headerSize=" << headerSize <<
279  "\n\t\t maxFragmentSize=" << maxFragmentSize << ""
280  "\n\t\t fragmentOffset=" << fragmentOffset <<
281  "\n\t\t payloadSize=" << packet->GetSize ()
282  << std::endl);
283  Ptr<Packet> fragment = packet->CreateFragment (fragmentOffset,
284  maxFragmentSize);
285  m_bytes -= maxFragmentSize;
286 
287  FragmentationSubheader fragmentSubhdr;
288  if (!element.m_fragmentation)
289  {
290  NS_LOG_INFO ("\t First Fragment" << std::endl);
291  SetFragmentation (packetType);
292  fragmentSubhdr.SetFc (1);
293  }
294  else
295  {
296  NS_LOG_INFO ("\t Middle Fragment" << std::endl);
297  fragmentSubhdr.SetFc (3);
298  }
299  fragmentSubhdr.SetFsn (element.m_fragmentNumber);
300  NS_LOG_INFO ("\t FragmentSize=" << fragment->GetSize () << std::endl);
301  fragment->AddHeader (fragmentSubhdr);
302 
303  SetFragmentNumber (packetType);
304  SetFragmentOffset (packetType, maxFragmentSize);
305 
306  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
307  has already been added to the packet) in which case Generic MAC Header will not be added to it.
308  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
310  {
311  uint8_t tmpType = element.m_hdr.GetType ();
312  tmpType |= 4;
313  element.m_hdr.SetType (tmpType);
314 
315  uint32_t length = maxFragmentSize + element.m_hdr.GetSerializedSize ()
316  + fragmentSubhdr.GetSerializedSize ();
317  element.m_hdr.SetLen ((uint16_t)length);
318 
319  fragment->AddHeader (element.m_hdr);
320  }
321  fragment->AddHeader (element.m_hdrType);
322 
323  m_traceDequeue (fragment);
324  return fragment;
325  }
326  return 0;
327 }
328 
331 {
332  if (!IsEmpty ())
333  {
334  QueueElement element = m_queue.front ();
335  hdr = element.m_hdr;
336  Ptr<Packet> packet = element.m_packet->Copy ();
337 
338  // this function must not be used by SS as it may be then a bandwidth request header
339  packet->AddHeader (element.m_hdr);
340  return packet;
341  }
342 
343  return 0;
344 }
345 
347 WimaxMacQueue::Peek (GenericMacHeader &hdr, Time &timeStamp) const
348 {
349  if (!IsEmpty ())
350  {
351  QueueElement element = m_queue.front ();
352  hdr = element.m_hdr;
353  timeStamp = element.m_timeStamp;
354  Ptr<Packet> packet = element.m_packet->Copy ();
355 
356  // this function must not be used for by SS as it may be then a bandwidth request header
357  packet->AddHeader (element.m_hdr);
358  return packet;
359  }
360 
361  return 0;
362 }
363 
366 {
367  if (!IsEmpty ())
368  {
369  QueueElement element = Front (packetType);
370  Ptr<Packet> packet = element.m_packet->Copy ();
371 
372  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
373  has already been added to the packet) in which case Generic MAC Header will not be added to it.
374  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
376  {
377  packet->AddHeader (element.m_hdr);
378  }
379  return packet;
380  }
381 
382  return 0;
383 }
384 
387  Time &timeStamp) const
388 {
389  if (!IsEmpty ())
390  {
391  QueueElement element = Front (packetType);
392  timeStamp = element.m_timeStamp;
393  Ptr<Packet> packet = element.m_packet->Copy ();
394 
395  /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request Header
396  has already been added to the packet) in which case Generic MAC Header will not be added to it.
397  this will only happen in the case of SS as only SS sends the bandwidth request packet. */
399  {
400  packet->AddHeader (element.m_hdr);
401  }
402  return packet;
403  }
404 
405  return 0;
406 }
407 
408 uint32_t
410 {
411  return m_queue.size ();
412 }
413 
414 uint32_t
416 {
417  return m_bytes;
418 }
419 
421 {
422  uint32_t queueSize = GetNBytes ();
423  // Add MAC Overhead
424  queueSize += GetSize () * 6;
426  if (CheckForFragmentation (packetType))
427  {
428  queueSize += 2;
429  }
430  return queueSize;
431 }
432 
435 {
436  QueueElement element;
437 
438  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
439  != m_queue.end (); ++iter)
440  {
441  element = *iter;
442  if (element.m_hdrType.GetType () == packetType)
443  {
444  break;
445  }
446  }
447 
448  return element;
449 }
450 
451 void
453 {
454  QueueElement element;
455 
456  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
457  != m_queue.end (); ++iter)
458  {
459  element = *iter;
460  if (element.m_hdrType.GetType () == packetType)
461  {
462  m_queue.erase (iter);
463  break;
464  }
465  }
466 }
467 
468 bool
470 {
471  return m_queue.empty ();
472 }
473 
474 bool
476 {
477  if (packetType == MacHeaderType::HEADER_TYPE_GENERIC)
478  {
479  return m_nrDataPackets == 0;
480  }
481  else
482  {
483  return m_nrRequestPackets == 0;
484  }
485 
486  return true;
487 }
488 
491 {
492  return m_queue;
493 }
494 
495 bool
497 {
498  QueueElement element;
499  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
500  != m_queue.end (); ++iter)
501  {
502  element = *iter;
503  if (element.m_hdrType.GetType () == packetType)
504  {
505  break;
506  }
507  }
508 
509  if (element.m_fragmentation)
510  {
511  NS_LOG_INFO ("FRAG_DEBUG: CheckForFragmentation"
512  "\n\t\t m_fragmentation is true " << std::endl);
513  }
514 
515  return element.m_fragmentation;
516 }
517 
518 uint32_t
520 {
521  QueueElement element;
522  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
523  != m_queue.end (); ++iter)
524  {
525  element = *iter;
526  if (element.m_hdrType.GetType () == packetType)
527  {
528  break;
529  }
530  }
531 
532  NS_LOG_INFO ("\t\t GetFirstPacketHdrSize ()");
533 
534  uint32_t hdrSize = 0;
536  {
537  hdrSize += element.m_hdr.GetSerializedSize ();
538  NS_LOG_INFO ("\t\t\t m_hdr.GetSerializedSize=" <<
539  element.m_hdr.GetSerializedSize ());
540  }
541 
542  hdrSize += element.m_hdrType.GetSerializedSize ();
543  NS_LOG_INFO ("\t\t\t m_hdrType.GetSerializedSize=" <<
544  element.m_hdrType.GetSerializedSize ());
545 
546  if (CheckForFragmentation (packetType))
547  {
548  NS_LOG_INFO ("\t\t\t fragSubhdrSize=2");
549  hdrSize += 2;
550  }
551 
552  NS_LOG_INFO ("\t\t hdrSize=" << hdrSize);
553 
554  return hdrSize;
555 }
556 
557 uint32_t
559 {
560  QueueElement element;
561  for (std::deque<QueueElement>::const_iterator iter = m_queue.begin (); iter
562  != m_queue.end (); ++iter)
563  {
564  element = *iter;
565  if (element.m_hdrType.GetType () == packetType)
566  {
567  break;
568  }
569  }
570 
571  NS_LOG_INFO ("\t\t GetFirstPacketPayloadSize ()");
572 
573  if (CheckForFragmentation (packetType))
574  {
575  NS_LOG_INFO ("\t\t\t fullPayloadSize=" << element.m_packet->GetSize ()
576  << "\n\t\t\t fragmentOffset=" << element.m_fragmentOffset
577  << "\n\t\t\t (fragment)payloadSize=" <<
578  element.m_packet->GetSize () - element.m_fragmentOffset);
579 
580  return element.m_packet->GetSize () - element.m_fragmentOffset;
581  }
582  NS_LOG_INFO ("\t\t payloadSize=" <<
583  element.m_packet->GetSize ());
584 
585  return element.m_packet->GetSize ();
586 }
587 
588 uint32_t
590 {
591  NS_LOG_INFO ("\t GetFirstPacketRequiredByte ()");
592 
593  uint32_t requiredByte = GetFirstPacketPayloadSize (packetType) +
594  GetFirstPacketHdrSize (packetType);
595 
596  NS_LOG_INFO ("\t Required Bytes = " << requiredByte << std::endl);
597 
598  return requiredByte;
599 }
600 
601 void
603 {
604  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
605  != m_queue.end (); ++iter)
606  {
607  if (iter->m_hdrType.GetType () == packetType)
608  {
609  iter->SetFragmentation ();
610  break;
611  }
612  }
613 }
614 
615 void
617 {
618  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
619  != m_queue.end (); ++iter)
620  {
621  if (iter->m_hdrType.GetType () == packetType)
622  {
623  iter->SetFragmentNumber ();
624  break;
625  }
626  }
627 }
628 
629 void
631 {
632  for (std::deque<QueueElement>::iterator iter = m_queue.begin (); iter
633  != m_queue.end (); ++iter)
634  {
635  if (iter->m_hdrType.GetType () == packetType)
636  {
637  iter->SetFragmentOffset (offset);
638  break;
639  }
640  }
641 }
642 
643 void
645 {
646  m_fragmentation = true;
647 }
648 
649 void
651 {
652  m_fragmentNumber++;
653 }
654 
655 void
657 {
658  m_fragmentOffset += offset;
659 }
660 } // namespace ns3
This class implements the fragmentation sub-header as described by IEEE Standard for Local and metrop...
void SetFsn(uint8_t fsn)
Set FSN field.
void SetFc(uint8_t fc)
Set FC field.
uint32_t GetSerializedSize(void) const
This class implements the Generic mac Header as described by IEEE Standard for Local and metropolitan...
uint8_t GetType(void) const
Get type field.
void SetType(uint8_t type)
Set type field.
void SetLen(uint16_t len)
Set length field.
uint32_t GetSerializedSize(void) const
This class Represents the HT (Header Type) field of generic MAC and bandwidth request headers.
uint8_t GetType(void) const
Get type field.
HeaderType
Header type enumeration.
uint32_t GetSerializedSize(void) const
A base class which provides memory management and object aggregation.
Definition: object.h:88
network packets
Definition: packet.h:232
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
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
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
std::deque< QueueElement > PacketQueue
PacketQueue typedef.
Ptr< Packet > Peek(GenericMacHeader &hdr) const
Exclusively for BS.
uint32_t GetFirstPacketPayloadSize(MacHeaderType::HeaderType packetType)
Get first packet payload size of the specified type.
WimaxMacQueue::QueueElement Front(MacHeaderType::HeaderType packetType) const
In the case of non-UGS service flows at the SS side the queue will store both data packets and bandwi...
void Pop(MacHeaderType::HeaderType packetType)
Pop function.
void SetMaxSize(uint32_t maxSize)
set the maximum queue size
TracedCallback< Ptr< const Packet > > m_traceDequeue
dequeue trace callback
uint32_t GetFirstPacketRequiredByte(MacHeaderType::HeaderType packetType)
Get required number of bytes to hold first packet of packetType.
Ptr< Packet > Dequeue(MacHeaderType::HeaderType packetType)
Dequeue a packet of type packetType from the queue.
TracedCallback< Ptr< const Packet > > m_traceEnqueue
enqueue trace callback
static TypeId GetTypeId(void)
Get the type ID.
uint32_t GetQueueLengthWithMACOverhead(void)
Get queue length considering also the MAC overhead.
uint32_t GetSize(void) const
Get size of queue.
uint32_t GetMaxSize(void) const
uint32_t GetFirstPacketHdrSize(MacHeaderType::HeaderType packetType)
Get first packet header size of the specified type.
uint32_t m_bytes
bytes
void SetFragmentNumber(MacHeaderType::HeaderType packetType)
Set fragment number for first packet of type packetType.
void SetFragmentation(MacHeaderType::HeaderType packetType)
Set fragmentation function.
const WimaxMacQueue::PacketQueue & GetPacketQueue(void) const
Get packet queue function.
uint32_t GetNBytes(void) const
Get number of bytes in queue.
void SetFragmentOffset(MacHeaderType::HeaderType packetType, uint32_t offset)
Set fragment offset for first packet of type packetType.
bool CheckForFragmentation(MacHeaderType::HeaderType packetType)
Check for fragmentation of the first packet of the specified type.
uint32_t m_nrDataPackets
number data packets
uint32_t m_maxSize
maximum size
bool Enqueue(Ptr< Packet > packet, const MacHeaderType &hdrType, const GenericMacHeader &hdr)
Enqueue a packet.
PacketQueue m_queue
the queue
uint32_t m_nrRequestPackets
number request packets
bool IsEmpty(void) const
Check if queue is empty.
TracedCallback< Ptr< const Packet > > m_traceDrop
drop trace callback
#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 AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:409
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_fragmentNumber
incremented when a new fragment is sent
uint32_t GetSize(void) const
Get size function.
uint32_t m_fragmentOffset
tracks the start of the next fragment into the packet
bool m_fragmentation
To manage fragmentation feature, each QueueElement have 3 new fields: m_fragmentation that becomes tr...
MacHeaderType m_hdrType
header type
void SetFragmentation(void)
Set fragmentation.
void SetFragmentNumber(void)
Set fragment number.
GenericMacHeader m_hdr
header
void SetFragmentOffset(uint32_t offset)
Set fragment offset.