A Discrete-Event Network Simulator
API
mac-rx-middle.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  */
19 
20 #include "mac-rx-middle.h"
21 
22 #include "wifi-mpdu.h"
23 
24 #include "ns3/log.h"
25 #include "ns3/packet.h"
26 #include "ns3/sequence-number.h"
27 
28 namespace ns3
29 {
30 
31 NS_LOG_COMPONENT_DEFINE("MacRxMiddle");
32 
38 {
39  private:
43  typedef std::list<Ptr<const Packet>> Fragments;
47  typedef std::list<Ptr<const Packet>>::const_iterator FragmentsCI;
48 
52 
53  public:
55  {
56  /* this is a magic value necessary. */
57  m_lastSequenceControl = 0xffff;
58  m_defragmenting = false;
59  }
60 
62  {
63  m_fragments.clear();
64  }
65 
72  bool IsDeFragmenting() const
73  {
74  return m_defragmenting;
75  }
76 
84  {
86  m_defragmenting = true;
87  m_fragments.push_back(packet);
88  }
89 
101  {
103  m_fragments.push_back(packet);
104  m_defragmenting = false;
105  Ptr<Packet> full = Create<Packet>();
106  for (FragmentsCI i = m_fragments.begin(); i != m_fragments.end(); i++)
107  {
108  full->AddAtEnd(*i);
109  }
110  m_fragments.erase(m_fragments.begin(), m_fragments.end());
111  return full;
112  }
113 
121  {
123  m_fragments.push_back(packet);
124  }
125 
135  bool IsNextFragment(uint16_t sequenceControl) const
136  {
137  if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
138  (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
139  {
140  return true;
141  }
142  else
143  {
144  return false;
145  }
146  }
147 
153  uint16_t GetLastSequenceControl() const
154  {
155  return m_lastSequenceControl;
156  }
157 
163  void SetSequenceControl(uint16_t sequenceControl)
164  {
165  m_lastSequenceControl = sequenceControl;
166  }
167 };
168 
170 {
172 }
173 
175 {
177  for (OriginatorsI i = m_originatorStatus.begin(); i != m_originatorStatus.end(); i++)
178  {
179  delete (*i).second;
180  }
182  for (QosOriginatorsI i = m_qosOriginatorStatus.begin(); i != m_qosOriginatorStatus.end(); i++)
183  {
184  delete (*i).second;
185  }
187 }
188 
189 void
191 {
193  m_callback = callback;
194 }
195 
198 {
199  NS_LOG_FUNCTION(hdr);
200  OriginatorRxStatus* originator;
201  Mac48Address source = hdr->GetAddr2();
202  if (hdr->IsQosData() && !hdr->GetAddr2().IsGroup())
203  {
204  /* only for QoS data non-broadcast frames */
205  originator = m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())];
206  if (originator == nullptr)
207  {
208  originator = new OriginatorRxStatus();
209  m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())] = originator;
210  }
211  }
212  else
213  {
214  /* - management frames
215  * - QoS data broadcast frames
216  * - non-QoS data frames
217  * see section 7.1.3.4.1
218  */
219  originator = m_originatorStatus[source];
220  if (originator == nullptr)
221  {
222  originator = new OriginatorRxStatus();
223  m_originatorStatus[source] = originator;
224  }
225  }
226  return originator;
227 }
228 
229 bool
231 {
232  NS_LOG_FUNCTION(hdr << originator);
233  if (hdr->IsRetry() && originator->GetLastSequenceControl() == hdr->GetSequenceControl())
234  {
235  return true;
236  }
237  return false;
238 }
239 
242  const WifiMacHeader* hdr,
243  OriginatorRxStatus* originator)
244 {
245  NS_LOG_FUNCTION(packet << hdr << originator);
246  if (originator->IsDeFragmenting())
247  {
248  if (hdr->IsMoreFragments())
249  {
250  if (originator->IsNextFragment(hdr->GetSequenceControl()))
251  {
252  NS_LOG_DEBUG("accumulate fragment seq=" << hdr->GetSequenceNumber()
253  << ", frag=" << +hdr->GetFragmentNumber()
254  << ", size=" << packet->GetSize());
255  originator->AccumulateFragment(packet);
256  originator->SetSequenceControl(hdr->GetSequenceControl());
257  }
258  else
259  {
260  NS_LOG_DEBUG("non-ordered fragment");
261  }
262  return nullptr;
263  }
264  else
265  {
266  if (originator->IsNextFragment(hdr->GetSequenceControl()))
267  {
268  NS_LOG_DEBUG("accumulate last fragment seq="
269  << hdr->GetSequenceNumber() << ", frag=" << +hdr->GetFragmentNumber()
270  << ", size=" << hdr->GetSize());
271  Ptr<Packet> p = originator->AccumulateLastFragment(packet);
272  originator->SetSequenceControl(hdr->GetSequenceControl());
273  return p;
274  }
275  else
276  {
277  NS_LOG_DEBUG("non-ordered fragment");
278  return nullptr;
279  }
280  }
281  }
282  else
283  {
284  if (hdr->IsMoreFragments())
285  {
286  NS_LOG_DEBUG("accumulate first fragment seq=" << hdr->GetSequenceNumber()
287  << ", frag=" << +hdr->GetFragmentNumber()
288  << ", size=" << packet->GetSize());
289  originator->AccumulateFirstFragment(packet);
290  originator->SetSequenceControl(hdr->GetSequenceControl());
291  return nullptr;
292  }
293  else
294  {
295  return packet;
296  }
297  }
298 }
299 
300 void
302 {
303  NS_LOG_FUNCTION(*mpdu << +linkId);
304  // consider the MAC header of the original MPDU (makes a difference for data frames only)
305  const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
306  NS_ASSERT(hdr->IsData() || hdr->IsMgt());
307 
308  OriginatorRxStatus* originator = Lookup(hdr);
318  if (!(SequenceNumber16(originator->GetLastSequenceControl()) <
320  {
321  NS_LOG_DEBUG("Sequence numbers have looped back. last recorded="
322  << originator->GetLastSequenceControl()
323  << " currently seen=" << hdr->GetSequenceControl());
324  }
325  // filter duplicates.
326  if (IsDuplicate(hdr, originator))
327  {
328  NS_LOG_DEBUG("duplicate from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
329  << ", frag=" << +hdr->GetFragmentNumber());
330  return;
331  }
332  Ptr<const Packet> aggregate = HandleFragments(mpdu->GetPacket(), hdr, originator);
333  if (!aggregate)
334  {
335  return;
336  }
337  NS_LOG_DEBUG("forwarding data from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
338  << ", frag=" << +hdr->GetFragmentNumber());
339  if (!hdr->GetAddr1().IsGroup())
340  {
341  originator->SetSequenceControl(hdr->GetSequenceControl());
342  }
343  if (aggregate == mpdu->GetPacket())
344  {
345  m_callback(mpdu, linkId);
346  }
347  else
348  {
349  // We could do this in all cases, but passing the received mpdu in case of
350  // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
351  // kept separate in the received mpdu) and allows us to pass the originally
352  // transmitted packets (i.e., with the same UID) to the receiver.
353  m_callback(Create<WifiMpdu>(aggregate, *hdr), linkId);
354  }
355 }
356 
357 } // namespace ns3
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
std::map< std::pair< Mac48Address, uint8_t >, OriginatorRxStatus *, std::less< std::pair< Mac48Address, uint8_t > > >::iterator QosOriginatorsI
typedef for an iterator for QosOriginators
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
Originators m_originatorStatus
originator status
Ptr< const Packet > HandleFragments(Ptr< const Packet > packet, const WifiMacHeader *hdr, OriginatorRxStatus *originator)
Check if the received packet is a fragment and handle it appropriately.
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...
std::map< Mac48Address, OriginatorRxStatus *, std::less< Mac48Address > >::iterator OriginatorsI
typedef for an iterator for Originators
void Receive(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Receive an MPDU on the given link.
QosOriginators m_qosOriginatorStatus
QOS originator status.
ForwardUpCallback m_callback
forward up callback
OriginatorRxStatus * Lookup(const WifiMacHeader *hdr)
Look up for OriginatorRxStatus associated with the sender address (by looking at ADDR2 field in the h...
A class to keep track of the packet originator status.
void AccumulateFragment(Ptr< const Packet > packet)
We received a fragmented packet (not first and not last).
Fragments m_fragments
fragments
uint16_t m_lastSequenceControl
last sequence control
void SetSequenceControl(uint16_t sequenceControl)
Set the last sequence control we received.
bool IsDeFragmenting() const
Check if we are de-fragmenting packets.
Ptr< Packet > AccumulateLastFragment(Ptr< const Packet > packet)
We have received a last fragment of the fragmented packets (indicated by the no more fragment field).
std::list< Ptr< const Packet > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
std::list< Ptr< const Packet > > Fragments
typedef for a list of fragments (i.e.
void AccumulateFirstFragment(Ptr< const Packet > packet)
We have received a first fragmented packet.
bool m_defragmenting
flag to indicate whether we are defragmenting
bool IsNextFragment(uint16_t sequenceControl) const
Check if the sequence control (i.e.
uint16_t GetLastSequenceControl() const
Return the last sequence control we received.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
Generic "sequence number" class.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
bool IsMoreFragments() const
Return if the More Fragment bit is set.
uint16_t GetSequenceControl() const
Return the raw Sequence Control field.
bool IsRetry() const
Return if the Retry bit is set.
bool IsMgt() const
Return true if the Type is Management.
uint32_t GetSize() const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
uint8_t GetFragmentNumber() const
Return the fragment number of the header.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
SequenceNumber< uint16_t, int16_t > SequenceNumber16
16 bit Sequence number.
Every class exported by the ns3 library is enclosed in the ns3 namespace.