A Discrete-Event Network Simulator
API
mac-rx-middle.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/sequence-number.h"
23 #include "ns3/packet.h"
24 #include "mac-rx-middle.h"
25 #include "wifi-mac-queue-item.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
30 
36 {
37 private:
41  typedef std::list<Ptr<const Packet> > Fragments;
45  typedef std::list<Ptr<const Packet> >::const_iterator FragmentsCI;
46 
50 
51 
52 public:
54  {
55  /* this is a magic value necessary. */
56  m_lastSequenceControl = 0xffff;
57  m_defragmenting = false;
58  }
60  {
61  m_fragments.clear ();
62  }
69  bool IsDeFragmenting (void) const
70  {
71  return m_defragmenting;
72  }
80  {
82  m_defragmenting = true;
83  m_fragments.push_back (packet);
84  }
96  {
98  m_fragments.push_back (packet);
99  m_defragmenting = false;
100  Ptr<Packet> full = Create<Packet> ();
101  for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++)
102  {
103  full->AddAtEnd (*i);
104  }
105  m_fragments.erase (m_fragments.begin (), m_fragments.end ());
106  return full;
107  }
115  {
117  m_fragments.push_back (packet);
118  }
128  bool IsNextFragment (uint16_t sequenceControl) const
129  {
130  if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4)
131  && (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
132  {
133  return true;
134  }
135  else
136  {
137  return false;
138  }
139  }
145  uint16_t GetLastSequenceControl (void) const
146  {
147  return m_lastSequenceControl;
148  }
154  void SetSequenceControl (uint16_t sequenceControl)
155  {
156  m_lastSequenceControl = sequenceControl;
157  }
158 };
159 
160 
162 {
164 }
165 
167 {
169  for (OriginatorsI i = m_originatorStatus.begin ();
170  i != m_originatorStatus.end (); i++)
171  {
172  delete (*i).second;
173  }
174  m_originatorStatus.erase (m_originatorStatus.begin (),
175  m_originatorStatus.end ());
176  for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
177  i != m_qosOriginatorStatus.end (); i++)
178  {
179  delete (*i).second;
180  }
182  m_qosOriginatorStatus.end ());
183 }
184 
185 void
187 {
189  m_callback = callback;
190 }
191 
194 {
195  NS_LOG_FUNCTION (hdr);
196  OriginatorRxStatus *originator;
197  Mac48Address source = hdr->GetAddr2 ();
198  if (hdr->IsQosData ()
199  && !hdr->GetAddr2 ().IsGroup ())
200  {
201  /* only for QoS data non-broadcast frames */
202  originator = m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())];
203  if (originator == 0)
204  {
205  originator = new OriginatorRxStatus ();
206  m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())] = originator;
207  }
208  }
209  else
210  {
211  /* - management frames
212  * - QoS data broadcast frames
213  * - non-QoS data frames
214  * see section 7.1.3.4.1
215  */
216  originator = m_originatorStatus[source];
217  if (originator == 0)
218  {
219  originator = new OriginatorRxStatus ();
220  m_originatorStatus[source] = originator;
221  }
222  }
223  return originator;
224 }
225 
226 bool
228  OriginatorRxStatus *originator) const
229 {
230  NS_LOG_FUNCTION (hdr << originator);
231  if (hdr->IsRetry ()
232  && originator->GetLastSequenceControl () == hdr->GetSequenceControl ())
233  {
234  return true;
235  }
236  return false;
237 }
238 
241  OriginatorRxStatus *originator)
242 {
243  NS_LOG_FUNCTION (packet << hdr << originator);
244  if (originator->IsDeFragmenting ())
245  {
246  if (hdr->IsMoreFragments ())
247  {
248  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
249  {
250  NS_LOG_DEBUG ("accumulate fragment seq=" << hdr->GetSequenceNumber () <<
251  ", frag=" << +hdr->GetFragmentNumber () <<
252  ", size=" << packet->GetSize ());
253  originator->AccumulateFragment (packet);
254  originator->SetSequenceControl (hdr->GetSequenceControl ());
255  }
256  else
257  {
258  NS_LOG_DEBUG ("non-ordered fragment");
259  }
260  return 0;
261  }
262  else
263  {
264  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
265  {
266  NS_LOG_DEBUG ("accumulate last fragment seq=" << hdr->GetSequenceNumber () <<
267  ", frag=" << +hdr->GetFragmentNumber () <<
268  ", size=" << hdr->GetSize ());
269  Ptr<Packet> p = originator->AccumulateLastFragment (packet);
270  originator->SetSequenceControl (hdr->GetSequenceControl ());
271  return p;
272  }
273  else
274  {
275  NS_LOG_DEBUG ("non-ordered fragment");
276  return 0;
277  }
278  }
279  }
280  else
281  {
282  if (hdr->IsMoreFragments ())
283  {
284  NS_LOG_DEBUG ("accumulate first fragment seq=" << hdr->GetSequenceNumber () <<
285  ", frag=" << +hdr->GetFragmentNumber () <<
286  ", size=" << packet->GetSize ());
287  originator->AccumulateFirstFragment (packet);
288  originator->SetSequenceControl (hdr->GetSequenceControl ());
289  return 0;
290  }
291  else
292  {
293  return packet;
294  }
295  }
296 }
297 
298 void
300 {
301  NS_LOG_FUNCTION (*mpdu);
302  const WifiMacHeader* hdr = &mpdu->GetHeader ();
303  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
304  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
305  if (!m_pcfCallback.IsNull ())
306  {
307  m_pcfCallback ();
308  }
309  OriginatorRxStatus *originator = Lookup (hdr);
320  {
321  NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
322  " currently seen=" << hdr->GetSequenceControl ());
323  }
324  //filter duplicates.
325  if (IsDuplicate (hdr, originator))
326  {
327  NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
328  ", seq=" << hdr->GetSequenceNumber () <<
329  ", frag=" << +hdr->GetFragmentNumber ());
330  return;
331  }
332  Ptr<Packet> aggregate = HandleFragments (packet, hdr, originator);
333  if (aggregate == 0)
334  {
335  return;
336  }
337  NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
338  ", seq=" << hdr->GetSequenceNumber () <<
339  ", frag=" << +hdr->GetFragmentNumber ());
340  if (!hdr->GetAddr1 ().IsGroup ())
341  {
342  originator->SetSequenceControl (hdr->GetSequenceControl ());
343  }
344  if (aggregate == packet)
345  {
346  m_callback (mpdu);
347  }
348  else
349  {
350  // We could do this in all cases, but passing the received mpdu in case of
351  // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
352  // kept separate in the received mpdu) and allows us to pass the originally
353  // transmitted packets (i.e., with the same UID) to the receiver.
354  m_callback (Create<WifiMacQueueItem> (aggregate, *hdr));
355  }
356 }
357 
358 void
360 {
361  m_pcfCallback = callback;
362 }
363 
364 } //namespace ns3
bool IsRetry(void) const
Return if the Retry bit is set.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void AccumulateFirstFragment(Ptr< const Packet > packet)
We have received a first fragmented packet.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
uint16_t m_lastSequenceControl
last sequence control
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
Fragments m_fragments
fragments
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
std::map< std::pair< Mac48Address, uint8_t >, OriginatorRxStatus *, std::less< std::pair< Mac48Address, uint8_t > > >::iterator QosOriginatorsI
typedef for an iterator for QosOriginators
bool IsNextFragment(uint16_t sequenceControl) const
Check if the sequence control (i.e.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Ptr< Packet > HandleFragments(Ptr< Packet > packet, const WifiMacHeader *hdr, OriginatorRxStatus *originator)
Check if the received packet is a fragment and handle it appropriately.
std::map< Mac48Address, OriginatorRxStatus *, std::less< Mac48Address > >::iterator OriginatorsI
typedef for an iterator for Originators
void AccumulateFragment(Ptr< const Packet > packet)
We received a fragmented packet (not first and not last).
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint16_t GetLastSequenceControl(void) const
Return the last sequence control we received.
OriginatorRxStatus * Lookup(const WifiMacHeader *hdr)
Look up for OriginatorRxStatus associated with the sender address (by looking at ADDR2 field in the h...
Originators m_originatorStatus
originator status
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
void SetPcfCallback(Callback< void > callback)
Set a callback to trigger the next PCF frame.
bool IsDuplicate(const WifiMacHeader *hdr, OriginatorRxStatus *originator) const
Check if we have already received the packet from the sender before (by looking at the sequence contr...
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
bool IsData(void) const
Return true if the Type is DATA.
Generic "sequence number" class.
Ptr< Packet > AccumulateLastFragment(Ptr< const Packet > packet)
We have received a last fragment of the fragmented packets (indicated by the no more fragment field)...
void SetSequenceControl(uint16_t sequenceControl)
Set the last sequence control we received.
an EUI-48 address
Definition: mac48-address.h:43
bool IsGroup(void) const
Callback< void > m_pcfCallback
PCF callback.
bool m_defragmenting
flag to indicate whether we are defragmenting
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
std::list< Ptr< const Packet > > Fragments
typedef for a list of fragments (i.e.
bool IsMgt(void) const
Return true if the Type is Management.
ForwardUpCallback m_callback
forward up callback
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
std::list< Ptr< const Packet > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data...
void Receive(Ptr< WifiMacQueueItem > mpdu)
Receive a packet.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1372
uint8_t GetFragmentNumber(void) const
Return the fragment number of the header.
bool IsDeFragmenting(void) const
Check if we are de-fragmenting packets.
A class to keep track of the packet originator status.
QosOriginators m_qosOriginatorStatus
QOS originator status.
Implements the IEEE 802.11 MAC header.
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.