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 "mac-rx-middle.h"
22 #include "wifi-mac-header.h"
23 #include "ns3/assert.h"
24 #include "ns3/log.h"
25 #include "ns3/packet.h"
26 #include "ns3/simulator.h"
27 #include "ns3/sequence-number.h"
28 #include <list>
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
33 
39 {
40 private:
44  typedef std::list<Ptr<const Packet> > Fragments;
48  typedef std::list<Ptr<const Packet> >::const_iterator FragmentsCI;
49 
52  Fragments m_fragments;
53 
54 
55 public:
57  {
58  /* this is a magic value necessary. */
59  m_lastSequenceControl = 0xffff;
60  m_defragmenting = false;
61  }
63  {
64  m_fragments.clear ();
65  }
72  bool IsDeFragmenting (void)
73  {
74  return m_defragmenting;
75  }
83  {
84  NS_ASSERT (!m_defragmenting);
85  m_defragmenting = true;
86  m_fragments.push_back (packet);
87  }
99  {
100  NS_ASSERT (m_defragmenting);
101  m_fragments.push_back (packet);
102  m_defragmenting = false;
103  Ptr<Packet> full = Create<Packet> ();
104  for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++)
105  {
106  full->AddAtEnd (*i);
107  }
108  m_fragments.erase (m_fragments.begin (), m_fragments.end ());
109  return full;
110  }
118  {
119  NS_ASSERT (m_defragmenting);
120  m_fragments.push_back (packet);
121  }
131  bool IsNextFragment (uint16_t sequenceControl)
132  {
133  if ((sequenceControl >> 4) == (m_lastSequenceControl >> 4)
134  && (sequenceControl & 0x0f) == ((m_lastSequenceControl & 0x0f) + 1))
135  {
136  return true;
137  }
138  else
139  {
140  return false;
141  }
142  }
148  uint16_t GetLastSequenceControl (void)
149  {
150  return m_lastSequenceControl;
151  }
157  void SetSequenceControl (uint16_t sequenceControl)
158  {
159  m_lastSequenceControl = sequenceControl;
160  }
161 };
162 
163 
165 {
167 }
168 
170 {
172  for (OriginatorsI i = m_originatorStatus.begin ();
173  i != m_originatorStatus.end (); i++)
174  {
175  delete (*i).second;
176  }
177  m_originatorStatus.erase (m_originatorStatus.begin (),
178  m_originatorStatus.end ());
179  for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
180  i != m_qosOriginatorStatus.end (); i++)
181  {
182  delete (*i).second;
183  }
185  m_qosOriginatorStatus.end ());
186 }
187 
188 void
190 {
192  m_callback = callback;
193 }
194 
197 {
198  NS_LOG_FUNCTION (hdr);
199  OriginatorRxStatus *originator;
200  Mac48Address source = hdr->GetAddr2 ();
201  if (hdr->IsQosData ()
202  && !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 == 0)
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  * - nqos data frames
217  * see section 7.1.3.4.1
218  */
219  originator = m_originatorStatus[source];
220  if (originator == 0)
221  {
222  originator = new OriginatorRxStatus ();
223  m_originatorStatus[source] = originator;
224  }
225  }
226  return originator;
227 }
228 
229 bool
231  OriginatorRxStatus *originator) const
232 {
233  NS_LOG_FUNCTION (hdr << originator);
234  if (hdr->IsRetry ()
235  && originator->GetLastSequenceControl () == hdr->GetSequenceControl ())
236  {
237  return true;
238  }
239  return false;
240 }
241 
244  OriginatorRxStatus *originator)
245 {
246  NS_LOG_FUNCTION (packet << hdr << originator);
247  if (originator->IsDeFragmenting ())
248  {
249  if (hdr->IsMoreFragments ())
250  {
251  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
252  {
253  NS_LOG_DEBUG ("accumulate fragment seq=" << hdr->GetSequenceNumber () <<
254  ", frag=" << hdr->GetFragmentNumber () <<
255  ", size=" << packet->GetSize ());
256  originator->AccumulateFragment (packet);
257  originator->SetSequenceControl (hdr->GetSequenceControl ());
258  }
259  else
260  {
261  NS_LOG_DEBUG ("non-ordered fragment");
262  }
263  return 0;
264  }
265  else
266  {
267  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
268  {
269  NS_LOG_DEBUG ("accumulate last fragment seq=" << hdr->GetSequenceNumber () <<
270  ", frag=" << hdr->GetFragmentNumber () <<
271  ", size=" << hdr->GetSize ());
272  Ptr<Packet> p = originator->AccumulateLastFragment (packet);
273  originator->SetSequenceControl (hdr->GetSequenceControl ());
274  return p;
275  }
276  else
277  {
278  NS_LOG_DEBUG ("non-ordered fragment");
279  return 0;
280  }
281  }
282  }
283  else
284  {
285  if (hdr->IsMoreFragments ())
286  {
287  NS_LOG_DEBUG ("accumulate first fragment seq=" << hdr->GetSequenceNumber () <<
288  ", frag=" << hdr->GetFragmentNumber () <<
289  ", size=" << packet->GetSize ());
290  originator->AccumulateFirstFragment (packet);
291  originator->SetSequenceControl (hdr->GetSequenceControl ());
292  return 0;
293  }
294  else
295  {
296  return packet;
297  }
298  }
299 }
300 
301 void
303 {
304  NS_LOG_FUNCTION (packet << hdr);
305  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
306  OriginatorRxStatus *originator = Lookup (hdr);
316  if (!(SequenceNumber16 (originator->GetLastSequenceControl ()) < SequenceNumber16 (hdr->GetSequenceControl ())))
317  {
318  NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
319  " currently seen=" << hdr->GetSequenceControl ());
320  }
321  //filter duplicates.
322  if (IsDuplicate (hdr, originator))
323  {
324  NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
325  ", seq=" << hdr->GetSequenceNumber () <<
326  ", frag=" << hdr->GetFragmentNumber ());
327  return;
328  }
329  Ptr<Packet> agregate = HandleFragments (packet, hdr, originator);
330  if (agregate == 0)
331  {
332  return;
333  }
334  NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
335  ", seq=" << hdr->GetSequenceNumber () <<
336  ", frag=" << hdr->GetFragmentNumber ());
337  if (!hdr->GetAddr1 ().IsGroup ())
338  {
339  originator->SetSequenceControl (hdr->GetSequenceControl ());
340  }
341  m_callback (agregate, hdr);
342 }
343 
344 } //namespace ns3
uint16_t GetLastSequenceControl(void)
Return the last sequence control we received.
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint16_t GetFragmentNumber(void) const
Return the fragment number of the header.
void AccumulateFirstFragment(Ptr< const Packet > packet)
We have received a first fragmented packet.
void SetForwardCallback(ForwardUpCallback callback)
Set a callback to forward the packet up.
#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:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
std::map< std::pair< Mac48Address, uint8_t >, OriginatorRxStatus *, std::less< std::pair< Mac48Address, uint8_t > > >::iterator QosOriginatorsI
typedef for an interator for QosOriginators
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
void Receive(Ptr< Packet > packet, const WifiMacHeader *hdr)
Ptr< Packet > HandleFragments(Ptr< Packet > packet, const WifiMacHeader *hdr, OriginatorRxStatus *originator)
Check if the received packet is a fragment and handle it appropriately.
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
std::map< Mac48Address, OriginatorRxStatus *, std::less< Mac48Address > >::iterator OriginatorsI
typedef for an interator for Originators
void AccumulateFragment(Ptr< const Packet > packet)
We received a fragmented packet (not first and not last).
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:313
OriginatorRxStatus * Lookup(const WifiMacHeader *hdr)
Look up for OriginatorRxStatus associated with the sender address (by looking at ADDR2 field in the h...
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
Originators m_originatorStatus
bool IsNextFragment(uint16_t sequenceControl)
Check if the sequence control (i.e.
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...
bool IsMgt(void) const
Return true if the Type is Management.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Generic "sequence number" class.
bool IsGroup(void) const
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 IsDeFragmenting(void)
Check if we are de-fragmenting packets.
std::list< Ptr< const Packet > > Fragments
typedef for a list of fragments (i.e.
bool IsData(void) const
Return true if the Type is DATA.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
ForwardUpCallback m_callback
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
std::list< Ptr< const Packet > >::const_iterator FragmentsCI
typedef for a const iterator for Fragments
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
A class to keep track of the packet originator status.
QosOriginators m_qosOriginatorStatus
bool IsRetry(void) const
Return if the Retry bit is set.
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.