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 (auto 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  return (sequenceControl >> 4) == (m_lastSequenceControl >> 4) &&
138  (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1);
139  }
140 
146  uint16_t GetLastSequenceControl() const
147  {
148  return m_lastSequenceControl;
149  }
150 
156  void SetSequenceControl(uint16_t sequenceControl)
157  {
158  m_lastSequenceControl = sequenceControl;
159  }
160 };
161 
163 {
165 }
166 
168 {
170  for (auto i = m_originatorStatus.begin(); i != m_originatorStatus.end(); i++)
171  {
172  delete (*i).second;
173  }
175  for (auto i = m_qosOriginatorStatus.begin(); i != m_qosOriginatorStatus.end(); i++)
176  {
177  delete (*i).second;
178  }
180 }
181 
182 void
184 {
186  m_callback = callback;
187 }
188 
191 {
192  NS_LOG_FUNCTION(hdr);
193  OriginatorRxStatus* originator;
194  Mac48Address source = hdr->GetAddr2();
195  if (hdr->IsQosData() && !hdr->GetAddr2().IsGroup())
196  {
197  /* only for QoS data non-broadcast frames */
198  originator = m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())];
199  if (originator == nullptr)
200  {
201  originator = new OriginatorRxStatus();
202  m_qosOriginatorStatus[std::make_pair(source, hdr->GetQosTid())] = originator;
203  }
204  }
205  else
206  {
207  /* - management frames
208  * - QoS data broadcast frames
209  * - non-QoS data frames
210  * see section 7.1.3.4.1
211  */
212  originator = m_originatorStatus[source];
213  if (originator == nullptr)
214  {
215  originator = new OriginatorRxStatus();
216  m_originatorStatus[source] = originator;
217  }
218  }
219  return originator;
220 }
221 
222 bool
224 {
225  NS_LOG_FUNCTION(hdr << originator);
226  return hdr->IsRetry() && originator->GetLastSequenceControl() == hdr->GetSequenceControl();
227 }
228 
231  const WifiMacHeader* hdr,
232  OriginatorRxStatus* originator)
233 {
234  NS_LOG_FUNCTION(packet << hdr << originator);
235  if (originator->IsDeFragmenting())
236  {
237  if (hdr->IsMoreFragments())
238  {
239  if (originator->IsNextFragment(hdr->GetSequenceControl()))
240  {
241  NS_LOG_DEBUG("accumulate fragment seq=" << hdr->GetSequenceNumber()
242  << ", frag=" << +hdr->GetFragmentNumber()
243  << ", size=" << packet->GetSize());
244  originator->AccumulateFragment(packet);
245  originator->SetSequenceControl(hdr->GetSequenceControl());
246  }
247  else
248  {
249  NS_LOG_DEBUG("non-ordered fragment");
250  }
251  return nullptr;
252  }
253  else
254  {
255  if (originator->IsNextFragment(hdr->GetSequenceControl()))
256  {
257  NS_LOG_DEBUG("accumulate last fragment seq="
258  << hdr->GetSequenceNumber() << ", frag=" << +hdr->GetFragmentNumber()
259  << ", size=" << hdr->GetSize());
260  Ptr<Packet> p = originator->AccumulateLastFragment(packet);
261  originator->SetSequenceControl(hdr->GetSequenceControl());
262  return p;
263  }
264  else
265  {
266  NS_LOG_DEBUG("non-ordered fragment");
267  return nullptr;
268  }
269  }
270  }
271  else
272  {
273  if (hdr->IsMoreFragments())
274  {
275  NS_LOG_DEBUG("accumulate first fragment seq=" << hdr->GetSequenceNumber()
276  << ", frag=" << +hdr->GetFragmentNumber()
277  << ", size=" << packet->GetSize());
278  originator->AccumulateFirstFragment(packet);
279  originator->SetSequenceControl(hdr->GetSequenceControl());
280  return nullptr;
281  }
282  else
283  {
284  return packet;
285  }
286  }
287 }
288 
289 void
291 {
292  NS_LOG_FUNCTION(*mpdu << +linkId);
293  // consider the MAC header of the original MPDU (makes a difference for data frames only)
294  const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
295  NS_ASSERT(hdr->IsData() || hdr->IsMgt());
296 
297  OriginatorRxStatus* originator = Lookup(hdr);
307  if (!(SequenceNumber16(originator->GetLastSequenceControl()) <
309  {
310  NS_LOG_DEBUG("Sequence numbers have looped back. last recorded="
311  << originator->GetLastSequenceControl()
312  << " currently seen=" << hdr->GetSequenceControl());
313  }
314  // filter duplicates.
315  if (IsDuplicate(hdr, originator))
316  {
317  NS_LOG_DEBUG("duplicate from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
318  << ", frag=" << +hdr->GetFragmentNumber());
319  return;
320  }
321  Ptr<const Packet> aggregate = HandleFragments(mpdu->GetPacket(), hdr, originator);
322  if (!aggregate)
323  {
324  return;
325  }
326  NS_LOG_DEBUG("forwarding data from=" << hdr->GetAddr2() << ", seq=" << hdr->GetSequenceNumber()
327  << ", frag=" << +hdr->GetFragmentNumber());
328  if (!hdr->GetAddr1().IsGroup())
329  {
330  originator->SetSequenceControl(hdr->GetSequenceControl());
331  }
332  if (aggregate == mpdu->GetPacket())
333  {
334  m_callback(mpdu, linkId);
335  }
336  else
337  {
338  // We could do this in all cases, but passing the received mpdu in case of
339  // A-MSDUs saves us the time to deaggregate the A-MSDU in MSDUs (which are
340  // kept separate in the received mpdu) and allows us to pass the originally
341  // transmitted packets (i.e., with the same UID) to the receiver.
342  m_callback(Create<WifiMpdu>(aggregate, *hdr), linkId);
343  }
344 }
345 
346 } // namespace ns3
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
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...
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:861
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.
virtual 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.