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-header.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  * - nqos 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 (packet << hdr);
302  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
303  if (!m_pcfCallback.IsNull ())
304  {
305  m_pcfCallback ();
306  }
307  OriginatorRxStatus *originator = Lookup (hdr);
318  {
319  NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
320  " currently seen=" << hdr->GetSequenceControl ());
321  }
322  //filter duplicates.
323  if (IsDuplicate (hdr, originator))
324  {
325  NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
326  ", seq=" << hdr->GetSequenceNumber () <<
327  ", frag=" << +hdr->GetFragmentNumber ());
328  return;
329  }
330  Ptr<Packet> aggregate = HandleFragments (packet, hdr, originator);
331  if (aggregate == 0)
332  {
333  return;
334  }
335  NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
336  ", seq=" << hdr->GetSequenceNumber () <<
337  ", frag=" << +hdr->GetFragmentNumber ());
338  if (!hdr->GetAddr1 ().IsGroup ())
339  {
340  originator->SetSequenceControl (hdr->GetSequenceControl ());
341  }
342  m_callback (aggregate, hdr);
343 }
344 
345 void
347 {
348  m_pcfCallback = callback;
349 }
350 
351 } //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 "...
Callback template class.
Definition: callback.h:1176
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:204
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.
void Receive(Ptr< Packet > packet, const WifiMacHeader *hdr)
Receive a packet.
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:272
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...
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1270
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.