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 
24 #include "ns3/assert.h"
25 #include "ns3/log.h"
26 #include "ns3/packet.h"
27 #include "ns3/simulator.h"
28 #include "ns3/sequence-number.h"
29 #include <list>
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("MacRxMiddle");
34 
40 {
41 private:
45  typedef std::list<Ptr<const Packet> > Fragments;
49  typedef std::list<Ptr<const Packet> >::const_iterator FragmentsCI;
50 
53  Fragments m_fragments;
54 public:
56  {
57  /* this is a magic value necessary. */
58  m_lastSequenceControl = 0xffff;
59  m_defragmenting = false;
60  }
62  {
63  m_fragments.clear ();
64  }
71  bool IsDeFragmenting (void)
72  {
73  return m_defragmenting;
74  }
82  {
83  NS_ASSERT (!m_defragmenting);
84  m_defragmenting = true;
85  m_fragments.push_back (packet);
86  }
97  {
98  NS_ASSERT (m_defragmenting);
99  m_fragments.push_back (packet);
100  m_defragmenting = false;
101  Ptr<Packet> full = Create<Packet> ();
102  for (FragmentsCI i = m_fragments.begin (); i != m_fragments.end (); i++)
103  {
104  full->AddAtEnd (*i);
105  }
106  m_fragments.erase (m_fragments.begin (), m_fragments.end ());
107  return full;
108  }
116  {
117  NS_ASSERT (m_defragmenting);
118  m_fragments.push_back (packet);
119  }
128  bool IsNextFragment (uint16_t sequenceControl)
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)
146  {
147  return m_lastSequenceControl;
148  }
154  void SetSequenceControl (uint16_t sequenceControl)
155  {
156  m_lastSequenceControl = sequenceControl;
157  }
158 
159 };
160 
161 
163 {
165 }
166 
168 {
170  for (OriginatorsI i = m_originatorStatus.begin ();
171  i != m_originatorStatus.end (); i++)
172  {
173  delete (*i).second;
174  }
175  m_originatorStatus.erase (m_originatorStatus.begin (),
176  m_originatorStatus.end ());
177  for (QosOriginatorsI i = m_qosOriginatorStatus.begin ();
178  i != m_qosOriginatorStatus.end (); i++)
179  {
180  delete (*i).second;
181  }
183  m_qosOriginatorStatus.end ());
184 }
185 
186 void
188 {
190  m_callback = callback;
191 }
192 
195 {
196  NS_LOG_FUNCTION (hdr);
197  OriginatorRxStatus *originator;
198  Mac48Address source = hdr->GetAddr2 ();
199  if (hdr->IsQosData ()
200  && !hdr->GetAddr2 ().IsGroup ())
201  {
202  /* only for qos data non-broadcast frames */
203  originator = m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())];
204  if (originator == 0)
205  {
206  originator = new OriginatorRxStatus ();
207  m_qosOriginatorStatus[std::make_pair (source, hdr->GetQosTid ())] = originator;
208  }
209  }
210  else
211  {
212  /* - management frames
213  * - qos data broadcast frames
214  * - nqos data frames
215  * see section 7.1.3.4.1
216  */
217  originator = m_originatorStatus[source];
218  if (originator == 0)
219  {
220  originator = new OriginatorRxStatus ();
221  m_originatorStatus[source] = originator;
222  }
223  }
224  return originator;
225 }
226 
227 bool
229  OriginatorRxStatus *originator) const
230 {
231  NS_LOG_FUNCTION (hdr << originator);
232  if (hdr->IsRetry ()
233  && originator->GetLastSequenceControl () == hdr->GetSequenceControl ())
234  {
235  return true;
236  }
237  return false;
238 }
239 
242  OriginatorRxStatus *originator)
243 {
244  NS_LOG_FUNCTION (packet << hdr << originator);
245  if (originator->IsDeFragmenting ())
246  {
247  if (hdr->IsMoreFragments ())
248  {
249  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
250  {
251  NS_LOG_DEBUG ("accumulate fragment seq=" << hdr->GetSequenceNumber () <<
252  ", frag=" << hdr->GetFragmentNumber () <<
253  ", size=" << packet->GetSize ());
254  originator->AccumulateFragment (packet);
255  originator->SetSequenceControl (hdr->GetSequenceControl ());
256  }
257  else
258  {
259  NS_LOG_DEBUG ("non-ordered fragment");
260  }
261  return 0;
262  }
263  else
264  {
265  if (originator->IsNextFragment (hdr->GetSequenceControl ()))
266  {
267  NS_LOG_DEBUG ("accumulate last fragment seq=" << hdr->GetSequenceNumber () <<
268  ", frag=" << hdr->GetFragmentNumber () <<
269  ", size=" << hdr->GetSize ());
270  Ptr<Packet> p = originator->AccumulateLastFragment (packet);
271  originator->SetSequenceControl (hdr->GetSequenceControl ());
272  return p;
273  }
274  else
275  {
276  NS_LOG_DEBUG ("non-ordered fragment");
277  return 0;
278  }
279  }
280  }
281  else
282  {
283  if (hdr->IsMoreFragments ())
284  {
285  NS_LOG_DEBUG ("accumulate first fragment seq=" << hdr->GetSequenceNumber () <<
286  ", frag=" << hdr->GetFragmentNumber () <<
287  ", size=" << packet->GetSize ());
288  originator->AccumulateFirstFragment (packet);
289  originator->SetSequenceControl (hdr->GetSequenceControl ());
290  return 0;
291  }
292  else
293  {
294  return packet;
295  }
296  }
297 }
298 
299 void
301 {
302  NS_LOG_FUNCTION (packet << hdr);
303  NS_ASSERT (hdr->IsData () || hdr->IsMgt ());
304  OriginatorRxStatus *originator = Lookup (hdr);
314  if (!(SequenceNumber16 (originator->GetLastSequenceControl ()) < SequenceNumber16 (hdr->GetSequenceControl ())))
315  {
316  NS_LOG_DEBUG ("Sequence numbers have looped back. last recorded=" << originator->GetLastSequenceControl () <<
317  " currently seen=" << hdr->GetSequenceControl ());
318  }
319  // filter duplicates.
320  if (IsDuplicate (hdr, originator))
321  {
322  NS_LOG_DEBUG ("duplicate from=" << hdr->GetAddr2 () <<
323  ", seq=" << hdr->GetSequenceNumber () <<
324  ", frag=" << hdr->GetFragmentNumber ());
325  return;
326  }
327  Ptr<Packet> agregate = HandleFragments (packet, hdr, originator);
328  if (agregate == 0)
329  {
330  return;
331  }
332  NS_LOG_DEBUG ("forwarding data from=" << hdr->GetAddr2 () <<
333  ", seq=" << hdr->GetSequenceNumber () <<
334  ", frag=" << hdr->GetFragmentNumber ());
335  if (!hdr->GetAddr1 ().IsGroup ())
336  {
337  originator->SetSequenceControl (hdr->GetSequenceControl ());
338  }
339  m_callback (agregate, hdr);
340 }
341 
342 } // 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:61
#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:766
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:317
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.